Mee's Engineer Blog

PHPエンジニアの技術ブログ

PHPのコーディング規約に関して(PSR-2)

コーディングルールって人によってまちまちだったりして、時として「うわ!このソース読みづらっ!」ってなったりしますよね。

そういう事もあり、コーディング規約に関して勉強しています。
今参考にしているのが現場でも採用されているPSR-2。
基本的なコーディング規約であるPSR-1にちょこちょこ追加されたものです。

コーディングの際の参考にして頂ければ。

<?php
// 開始は「<?php」または「<?=」のみ可
// ファイルの文字コードはUTF-8(BOMなし)
// 改行コードはLF
// 行の長さをソフトリミット120字とし、80字以内におさまるようにする

// 呼んだだけで動くファイルの中で宣言系の処理を書いてはいけない(クラス定数は除く)
// define("DEF_ITEM", '定数アイテム');

// クラス名はアッパーキャメルケース
// extendsは同じ行に書く
class RulesExplain extends RulesBase
// クラス名のあとの「{」は改行する
{
// インデントは半角スペース4つ
    
    // 定数は大文字+「_」で定義する
    const DEF_ITEM = '定数アイテム';
   
    // アクセス修飾子は必ずつける
    // 関数名は(ローワー)キャメルケース 
    // 引数後のカンマの前にスペースは入れない
    // 引数後のカンマの後にはスペースを入れる
    public function getRules($rule1, $rule2)
    // 関数名のあとの「{」は改行する
    {
        // 変数名に関しては一貫性を持たせればなんでもいい(今回はキャメルケース)
        $rulesName = $rule1;
        
        // 予約語は小文字にする
        $rulesBool = true;
        
        // 「if」などと「(」の間は半角スペースを空ける
        // 「)」と「{」の間は半角スペースを空ける
        // ifなどの後の「{」は改行しない
        if ($rulesName === $rulesBool) {
            echo 'rule!';
        // elseifはつなげる
        } elseif ($rulesName === $rule2) {        
        
        }
        
        //「;」の前の空白は不要
        for ($i = 0; $i < 5; $i++) {
            echo 'rule' . $i;
        }
    }
    
    public function tooMuchArgument(
        // 複数行になる場合、1行につき引数は1つまで
        $itemOne,
        $itemTwo,
        $itemThree,
        $itemFour,
        $itemFive,
    ) {
        $itemTemp = $itemOne;
        
        switch ($itemTemp) {
            case 1:
                echo '1以上';
                // no break
                // 空でないcaseで意図的にbreakしない場合その旨のコメントを使う
            case 2:
            case 3:
                echo '2以上';
                break;
        }
       
    }
}
// [EOF]
// ファイルの末尾は改行し空行をいれる
/* 「?>」は省略する */

説明部分をコメントとして残してみたけどえらく見づらいな(´Д`;)

コーディング規約を手短に伝えるため肝心のソースの中身は適当です(笑)

switch文で文字列を比較対象にする際の注意点

PHPのswitch文は比較を「==」で行っています。
従って、比較対象を文字列にした場合想定外の動作が起こります。

<?php
$arr = array('怠惰', 'ゼロ', 0);

foreach ($arr as $val) {
    switch ($val) {
        case '怠惰':
            echo $val . ' → 怠惰ですねぇ' . '<br>';
            break;
        default :
            break;
    }
}

// 出力結果
怠惰 → 怠惰ですねぇ
0 → 怠惰ですねぇ

このようになってしまうので、文字列を比較対象とする場合は
下のいずれかの対応を行う事で意図しない不具合を回避することができます。

方法1

<?php
$arr = array('怠惰', 'ゼロ', 0);

foreach ($arr as $val) {
    switch ((string)$val) {
        case '怠惰':
            echo $val . ' → 怠惰ですねぇ' . '<br>';
            break;
        default :
            break;
    }
}

// 出力結果
怠惰 → 怠惰ですねぇ

方法2

<?php
$arr = array('怠惰', 'ゼロ', 0);

foreach ($arr as $val) {
    switch (true) {
        case $val === '怠惰':
            echo $val . ' → 怠惰ですねぇ' . '<br>';
            break;
        default :
            break;
    }
}

// 出力結果
怠惰 → 怠惰ですねぇ

PHPの標準クラスstdClassに関して

クラスを利用する場合、通常は利用するクラスを定義しなければいけませんが
内部定義されているstdClassを利用することもできます。

<?php
$obj = new stdClass();
$obj->name = 'TKG';
$obj->purpose = '医療用';

// TKGは、それを医療用として利用しています。
echo $obj->name . 'は、それを' . $obj->purpose . 'として利用しています。';
?>

名前空間

通常クラス名が重複した場合、衝突しエラーが起こりますが
名前空間を設定する事によって衝突を回避することができます。

namespace Freedom;

class Sample
{
    function get_value()
    {
        return 1;
    }
}

このような場合、別ファイルからget_value()へアクセスするには

$sample = new Freedom\Sample();
$value  = $sample->get_value(); 
echo $value; // 1

と記述してあげます。

また名前空間を設定しているファイルでグローバル空間のクラスを参照する場合は頭に\をつけてあげる必要があります。

namespace Freedom;

class Sample extends \DatabaseAccess

{
    function get()
    {
        return 1;
    }
}

PHPによる入力値チェックや加工各種

リクエストデータを受け取った後の入力値チェックなどに便利な関数をいくつかリストアップします。

trim() スペースを削除する

$string = ' JAPAN          ';
$word   = trim( $string );

echo $word; // 'JAPAN'

get_magic_quotes_gpc() magic_quotes_gpcによるおせっかいエスケープを削除

if ( get_magic_quotes_gpc() )
{ 
    $var = stripslashes( $var );
}


NULLバイト攻撃対策

if ( preg_match( '/\0/' , $var ) ) 
{ 
    die( '不正な入力です。' );
}

SQLServerでIdentityが設定されているテーブルをコピーする方法

SQLServerで本番環境DBのテーブルデータを、試験環境DBのテーブルにコピーする必要がありました。
その際、対象テーブルにIdenityが設定されていた場合、普通にコピーすると採番が再設定されてしまうので
下記の方法で対応しました。

table_1 → コピー元テーブル
table_2 → コピー先テーブル
field_1 → フィールド1
filed_2 → フィールド2

【作業その1 フィールド名取得】
SELECT * FROM syscolumns
WHERE id = object_id('table_1')

【作業その2 コピー先テーブルのトランケート】
TRUNCATE TABLE table_2

【作業その3 コピー】
SET IDENTITY_INSERT table_2 ON
INSERT INTO 
table_2
(
field_1,
field_2,
.
.
.
)
SELECT * FROM tabke_1;
SET IDENTITY_INSERT table_2 OFF 

jsonを利用したデータ通信

jsonを利用したデータ通信方法です。

 $.ajax({
            url : "ファイルパス", //実行ファイルパス
            type: 'POST', //値の通信形式。指定しないとGET
            dataType: 'json', //サーバーから返されるデータの型
            timeout: 10000, //サーバーと通信をする間隔
            data:{ //送るデータの中身
                "id" : id,
                "user_id": user_id,
                "send_data": send_data
            },
        }).done(function(data){ //成功した時の処理
 
        }).fail(function(data){ //失敗した時の処理

        });

PHP側は配列を出力したい場合はjson_encodeした後にecho
そうでない場合は普通にechoで出力します。そしてexit;で終了。