ゼロから始めるPHP講座Vol.41 ユーザー定義関数②

      2015/12/18

Code部

ゼロから始めるPHP講座 ユーザー定義関数②

引数のデフォルト値

引数にはデフォルト値を設定することができます。dice.phpで作成したthrow_dice関数にデフォルト値を設定してみましょう。

<pre>
<?php
/*
print 'サイコロを1個振る:' . throw_dice(1) . "\n";
print 'サイコロを1個振る:' . throw_dice(1) . "\n";
print 'サイコロを2個振る:' . throw_dice(2) . "\n";
print 'サイコロを2個振る:' . throw_dice(2) . "\n";
print 'サイコロを3個振る:' . throw_dice(3) . "\n";
print 'サイコロを3個振る:' . throw_dice(3) . "\n";
*/
print 'サイコロを1個振る:' . throw_dice() . "\n";

function throw_dice($num = 1) {

    $sum = 0;

    for ($i = 0; $i < $num; $i++) {
        $sum += mt_rand(1,6);
    }

    return $sum;

}
?>
</pre>

php_func_application2-1-639「function throw_dice($num = 1)」と、引数に値を代入しておくことでデフォルト値を設定できます。

「throw_dice()」と関数実行時に引数が指定されなかった場合、ローカル変数$numはデフォルト値1が定義されます。

 

ユーザー定義関数の使用例

データベースから情報を取得し表示するプログラムをユーザー定義関数利用し書いてみましょう。
※本サンプルはコードの内容を理解することが重要であり、作成はコピー&ペーストでも構いません。
ファイル名:func_sample.php

<?php

define('TAX', 1.05);  // 消費税

define('DB_HOST',   'localhost'); // データベースのホスト名又はIPアドレス
define('DB_USER',   'username');  // MySQLのユーザ名
define('DB_PASSWD', 'passwd');    // MySQLのパスワード
define('DB_NAME',   'dbname');    // データベース名

define('HTML_CHARACTER_SET', 'UTF-8');  // HTML文字エンコーディング
define('DB_CHARACTER_SET',   'UTF8');   // DB文字エンコーディング

$goods_data = array();

// DB接続
$link = get_db_connect();

// 商品の一覧を取得
$goods_data = get_goods_table_list($link);

// DB切断
close_db_connect($link);

// 商品の値段を税込みに変換
$goods_data = price_before_tax_assoc_array($goods_data);

// 特殊文字をHTMLエンティティに変換
$goods_data = entity_assoc_array($goods_data);

/**
* 税込み価格へ変換する(端数は切り上げ)
* @param int  $price 税抜き価格
* @return int 税込み価格
*/
function price_before_tax($price) {
    return ceil($price * TAX);
}

/**
* 商品の値段を税込みに変換する(配列)
* @param array  $assoc_array 税抜き商品一覧配列データ
* @return array 税込み商品一覧配列データ
*/
function price_before_tax_assoc_array($assoc_array) {

    foreach ($assoc_array as $key => $value) {
        // 税込み価格へ変換(端数は切り上げ)
        $assoc_array[$key]['price'] = price_before_tax($assoc_array[$key]['price']);
    }

    return $assoc_array;

}

/**
* 特殊文字をHTMLエンティティに変換する
* @param str  $str 変換前文字
* @return str 変換後文字
*/
function entity_str($str) {
    return htmlspecialchars($str, ENT_QUOTES, HTML_CHARACTER_SET);
}

/**
* 特殊文字をHTMLエンティティに変換する(2次元配列の値)
* @param array  $assoc_array 変換前配列
* @return array 変換後配列
*/
function entity_assoc_array($assoc_array) {

    foreach ($assoc_array as $key => $value) {

        foreach ($value as $keys => $values) {
            // 特殊文字をHTMLエンティティに変換
            $assoc_array[$key][$keys] = entity_str($values);
        }

    }

    return $assoc_array;

}

/**
* DBハンドルを取得
* @return obj $link DBハンドル
*/
function get_db_connect() {

    // コネクション取得
    if (!$link = mysqli_connect(DB_HOST, DB_USER, DB_PASSWD, DB_NAME)) {
        die('error: ' . mysqli_connect_error());
    }

    // 文字コードセット
    mysqli_set_charset($link, DB_CHARACTER_SET);

    return $link;
}

/**
* DBとのコネクション切断
* @param obj $link DBハンドル
*/
function close_db_connect($link) {
    // 接続を閉じる
    mysqli_close($link);
}

/**
* クエリを実行しその結果を配列で取得する
*
* @param obj  $link DBハンドル
* @param str  $sql SQL文
* @return array 結果配列データ
*/
function get_as_array($link, $sql) {

    // 返却用配列
    $data = array();

    // クエリを実行する
    if ($result = mysqli_query($link, $sql)) {

        if (mysqli_num_rows($result) > 0) {

            // 1件ずつ取り出す
            while ($row = mysqli_fetch_assoc($result)) {
                $data[] = $row;
            }

        }

        // 結果セットを開放
        mysqli_free_result($result);

    }

    return $data;

}

/**
* 商品の一覧を取得する
*
* @param obj $link DBハンドル
* @return array 商品一覧配列データ
*/
function get_goods_table_list($link) {

    // SQL生成
    $sql = 'SELECT goods_name, price FROM goods_table';

    // クエリ実行
    return get_as_array($link, $sql);

}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ユーザー定義関数</title>
    <style type="text/css">
        table, td, th {
            border: solid black 1px;
        }
        table {
            width: 200px;
        }
        caption {
            text-align: left;
        }
    </style>
</head>
<body>
    <table>
    <caption>商品一覧(税込み)</caption>
        <tr>
            <th>商品名</th>
            <th>価格</th>
        <tr>
<?php foreach ($goods_data as $value) { ?>
        <tr>
            <td><?php print $value['goods_name']; ?></td>
            <td><?php print $value['price']; ?></td>
        </tr>
<?php } ?>
    </table>

</body>
</html>

php_func_application2-2-639表示内容は商品一覧が表示されているだけで特別なところはありませんが、ソースコードがこれまでと大きく変わっています。

// DB接続
$link = get_db_connect();

// 商品の一覧を取得
$goods_data = get_goods_table_list($link);

// DB切断
close_db_connect($link);

// 商品の値段を税込みに変換
$goods_data = price_before_tax_assoc_array($goods_data);

// 特殊文字をHTMLエンティティに変換
$goods_data = entity_assoc_array($goods_data);

各処理を基本的にユーザー定義関数で行うようにしています。

if文やfor文などを複数組み合わせると、プログラムの処理内容をすぐに把握するのが難しくなっていたと思います。

このように処理を関数にまとめることで、コメントと関数名からこのプログラムがどのような処理をしているのか、予測できるようになります。

例えばDB接続に関して、get_db_connect関数を作成しました。

/**
* DBハンドルを取得
* @return obj $link DBハンドル
*/
function get_db_connect() {

    // コネクション取得
    if (!$link = mysqli_connect(DB_HOST, DB_USER, DB_PASSWD, DB_NAME)) {
        die('error: ' . mysqli_connect_error());
    }

    // 文字コードセット
    mysqli_set_charset($link, DB_CHARACTER_SET);

    return $link;
}

DB接続の際に必ず行う、「DB接続」「接続確認」「文字コードセット」をこの関数でまとめて行っています。

DB切断に関してもclose_db_connect関数を作成しています。

/**
* DBとのコネクション切断
* @param obj $link DBハンドル
*/
function close_db_connect($link) {
    // 接続を閉じる
    mysqli_close($link);
}

「たった1行で戻り値もない関数に意味があるのか?」と疑問に思うかもしれませんが、このような関数にも意味があります。

関数のより効果的な利用方法の詳細は次の章で説明します。

 

課題

身長と体重を入力すると、BMIを計算し表示するプログラムを作成してください。

ソースコードは用意したものを利用し、「BMIの計算」「身長と体重の入力値チェック」を行うユーザー定義関数を追記し、プログラムを完成させてください。
※BMI指数 = 体重(kg) / (身長(m) × 身長(m))
ファイル名: challenge_func.php

<?php

// エラーメッセージ用配列
$err_msg = array();

// 初期化
$height = '';
$weight = '';
$bmi    = '';

// リクエストメソッド取得
$request_method = get_request_method();

// POSTの場合
if ($request_method === 'POST') {

    // POSTデータ取得
    $height = get_post_data('height');
    $weight = get_post_data('weight');

    // 身長の値が小数かチェック
    if (check_float($height) !== TRUE) {
        $err_msg[] = '身長は数値を入力してください';
    }

    // 体重の値が小数かチェック
    if (check_float($weight) !== TRUE) {
        $err_msg[] = '体重は数値を入力してください';
    }

    // エラーがない場合
    if (count($err_msg) === 0) {
        // BMI算出
        $bmi = calc_bmi($height, $weight);
    }

}

/**
* BMIを計算
* @param mixed $height 身長
* @param mixed $weight 体重
* @return float BMI
*/
/////////////////////
// calc_bmi関数作成
/////////////////////

/**
* 値が正の整数又は小数か確認
* @param mixed $float 確認する値
* @return bool TUREorFALSE
*/
/////////////////////
// check_float関数作成
/////////////////////

/**
* リクエストメソッドを取得
* @return str GET/POST/PUTなど
*/
function get_request_method() {
    return $_SERVER['REQUEST_METHOD'];
}

/**
* POSTデータを取得
* @param str $key 配列キー
* @return str POST値
*/
function get_post_data($key) {

    $str = '';

    if (isset($_POST[$key]) === TRUE) {
        $str = $_POST[$key];
    }

    return $str;

}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>BMI計算</title>
</head>
<body>
    <h1>BMI計算</h1>
    <form method="post">
        身長: <input type="text" name="height" value="<?php print $height ?>">
        体重: <input type="text" name="weight" value="<?php print $weight ?>">
        <input type="submit" value="BMI計算">
    </form>
<?php if (count($err_msg) > 0) { ?>
<?php     foreach ($err_msg as $value) { ?>
    <p><?php print $value; ?></p>
<?php     } ?>
<?php } ?>
<?php if ($request_method === 'POST' && count($err_msg) ===0) { ?>
    <p>あなたのBMIは<?php print $bmi; ?>です</p>
<?php } ?>
</body>
</html>

php_func_application2-3-639php_func_application2-4-639

 

NEXT LESSON ☛ MVCモデル①~MVCモデルとは?

PREV LESSON ☛ ユーザー定義関数①

 - PHP/MySQL, プログラミング, プログラミング基礎