【PHP第4回】関数

【PHP第4回】関数

PHPのプログラミングメモ第4回です。何回かに分けてメモを投稿していきます。なお、この記事はプログラミングメモですのでどんどん追記していきます。

【コードの格納先】
>> 20230205-php.php

【関連記事】

関数

関数とは?

  • 複数の命令をひとかたまりの命令にしたもの
  • その命令を呼び出すことで、複数の処理を行うことができる
  • また、毎回同じ処理を書く必要がなくなる
  • 何かの値を関数に与える → 関数の中で処理がされる → 新しい値が返ってくる
    →returnを使うと結果の値を返すことができる

関数の書き方

  • 関数には引数として値をいくつも渡すことができる → 渡す値によって返ってくる結果を変えることができる
  • 渡したい値を受け取る変数を作成する
  • 変数名はなんでもOK
  • 作った変数はこの関数の中だけで使える
  • 渡したい個数によってカンマで区切る、なければ空でOK

ハンズオン/変数を渡して3乗の整数を返す関数

// sample code 1
// int型の変数を宣言
// 変数を渡して3乗の整数を返す関数
// 変数を渡して3乗の値を返す関数を定義
function calcCubic($num){
    // 3乗した計算結果を$resultに代入 → 出力する
    $result = pow ($num, 3);
    return $result;
}
// 関数を実行
echo calcCubic(3);
// result
27

boolean型の引数を渡すと、結果を反転して返す関数

// sample code 2
// boolean型の引数を渡すと、結果を反転して返す関数
// 例) trueを渡す → falseが返ってくる
// 関数を定義(引数:boolean型の$flag)
function flagExsists (bool $flag) {
// 戻り値は$flagを反転させる
    return !$flag;
}
// 関数を実行(true か falseを返す)
echo var_export(flagExsists(true));
// result
false

複数の引数を扱う(型指定)関数

// sample code 3
// int型とString型の2つの変数を引数で渡す → 「int型:String型」という文字列を返す関数
// ※int型,String型は引数で渡す
// 出力例「 7:aaa」

// 関数を定義(引数の型指定あり)
// int型 $number
// string型 $text
function returnNumText(int $number, string $text){
    return $number.":".$text;
}

// 関数の呼び出し
echo returnNumText(7,'aaa');
echo PHP_EOL;

// 戻り値の値を確認
var_dump(returnNumText(7,'aaa'));
echo PHP_EOL;
// result
7:aaa
string(5) "7:aaa"

関数の中で条件分岐してみる

// sample code 4
// int型とboolean型を渡し boolean型:trueなら int型を1プラス/falseなら1マイナスする関数
// 引数の型宣言がある関数を定義
// int型$number
// boolean型 $flag
function calcByCondition(int $number, bool $flag){
    // boolean型がtrueなら int型を1プラスする
    if($flag === true){
        $number++;
    }
    // boolean型がfalseなら int型を1マイナスする
    elseif ($flag === false) {
        $number--;
    }
    return $number;
}

// 関数の呼び出し
echo calcByCondition(5,false);
echo PHP_EOL;
// result
4

関数の中でループしてみる

sample code 5
// int型とString型を渡しそのint型の数値の回数分 Stringを出力する関数
// 例外 入力値が0以下の時は"Out of range"と出力

// 引数の型宣言がある関数を定義
// int型 $count
// string型 $text
function repeatText(int $count, string $text){
    // 例外時の処理を記載
    if ($count <= 0) {
        echo "Out of range";
    }

    // 1 → int型の数値分($count)のループを実施
    for($i = 1; $i <= $count; $i++){
    // string型の$textの内容を出力
      echo $text;
      echo PHP_EOL;
    }
}

// 関数の呼び出し
repeatText(5,'aaa');

// result
aaa
aaa
aaa
aaa
aaa

  • テスト値は 「1」 「0」 「-1」 で実施
  • 境界線が0のため

【参考】
>> 境界値分析とは?境界値テストの手順と欠陥が潜む可能性が高い2つの理由


関数の中で文字列を検索してみる

// string型の変数を2つ宣言
// 第二引数のString(文字列)が第一引数に含まれているかどうか検索
// 結果をboolean型で返す関数

function isSubstring($str_range, $str_target) {
  $result = strpos($str_range, $str_target);

  if ( $result === false ) {
    return false;
  }
  return true; // 早期リターン
}

var_dump(isSubstring('abc', 'd'));
echo PHP_EOL;

// reslt
bool(false)

早期リターン

  • returnは値を返して関数を終了するという動作
  • 早期リターンを使用すると関数内のネストが減らせるため、可読性が上がる
  • else句を使うより理解しやすいメリットがある

strpos()

  • 上記ではstrpos()を使用して、第一引数の文字列に第二引数の文字列が含まれているかどうかを調べている
  • strpos()は、指定した文字列内で指定した文字列を検索し、最初に見つかった位置を返す
  • 見つからなかった場合はfalseを返す
  • strpos()がfalse以外の値を返す場合は、第二引数の文字列が第一引数の文字列に含まれると判断し、trueを返す

関数と標準入力の組み合わせてみる

  • 標準入力の結果を関数で受け取って処理
  • バリデーションもしてみる
// 名前を取得

/**
* 名前を取得
* 
* @param string $input_name 標準入力
* @return string $input_name
*/
function getName() {
    echo "あなたの名前を教えてください。";
$input_name = trim(fgets(STDIN));
    if ( empty($input_name) ) {
        echo "empty";
        echo PHP_EOL;
        return getName();
    }

    if ( mb_strlen($input_name) > 12 ) {
        echo '12文字以内で入力してください。';
        echo PHP_EOL;
        return getName();
    }
    return $input_name;
}

/**
* 年齢を取得
* 
* @param integer $input_age 標準入力
* @return integer $input_age
*/
function getAge($input_name) {
    echo "{$input_name}さん、あなたの年齢は何歳ですか?";
    $input_age = trim(fgets(STDIN));
    if ( empty($input_age) ) {
        echo "empty";
        echo PHP_EOL;
    return getAge($input_name);
    }
    if ( filter_var($input_age, FILTER_VALIDATE_INT) === false ) {
        echo "半角数字を入力してください";
        echo PHP_EOL;
    return getAge($input_name);
    }
return $input_age;
}

$input_name = getName();
$input_age = getAge($input_name);
echo "{$input_name}(年齢:{$input_age})さん、ご登録ありがとうございます!";


// input
name ヤマダタロウ
age  33

// result
ヤマダタロウ(年齢:33)さん、ご登録ありがとうございます!

デバッグ/var_dump、print_r、var_export

// sample code debug
// 変数を宣言
$number = 5;
$text = "test";
$flag = true;
$test = null;
$array = array(1,2,3);

// $number = 5;
var_dump($number);
print_r($number);
var_export($number);

// result
int(5)
5
5

// $text = "test";
var_dump($text);
print_r($text);
var_export($text);

// result
string(4) "test"
test
'test'


// $flag = true;
var_dump($flag);
print_r($flag);
var_export($flag);

// result
bool(true)
1
true


// $test = null;
var_dump($test);
print_r($test);
var_export($test);

// output
NULL
NULL

// $array = array(1,2,3);
var_dump($array);
print_r($array);
var_export($array);

// output
// var_dump($array);
// NULLarray(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

// print_r($array);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)

// var_export($array);
array (
    0 => 1,
    1 => 2,
    2 => 3,
)

関数作成時の注意点

  • 関数の定義と関数の実行はある程度まとまって書くこと
  • 関数の中で関数を使う(再起的に利用する)場合、returnで何を返すか注意すること
  • コメントは適度に書く
  • 関数やクラス単位では適切にコメントする
  • 関数名が同じでも、引数の個数が違うと別の関数として扱われる

関数の定義と関数の実行はある程度まとまって書くこと

  • 定義と実行は全く別物/「定義→実行→定義→実行」と書くとコードが読みにくくなる
  • 上部に関数の定義、下部に関数の実行でまとまって書くのがベター

コメントは適度に書く

  • コメントは最小限にする
  • 行単位のコメントは、どうしても注意喚起や複雑な事情がある時に留める
  • 「コード→コメント→コード→コメント」のようにコメントがありすぎると散見して本命のコードが読みにくくなる

関数やクラス単位では適切にコメントする

  • 例えば関数の仕様、特徴、使い方を説明をする
  • 自分に対するメモではなく、客観的に明瞭な内容であることがポイント
  • ブロックコメントで記載する
  • PHPDocというコメントを記述するルールがあるので、そちらに合わせるのがベター

【参考URL】
>> PHPDoc
>> PHPコメントの書き方(PHPDoc)