ホームページ  >  記事  >  バックエンド開発  >  PHP コードの品質を向上させるための非常に教えやすい 36 のヒント_PHP チュートリアル

PHP コードの品質を向上させるための非常に教えやすい 36 のヒント_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 15:16:391355ブラウズ

1. 相対パスを使用しないでください:
require_once('../../lib/some_class.php');
このメソッドには多くの欠点があります:
最初に指定された php インクルード パスを検索します。
現在のディレクトリを検索します。
チェックされるパスが多すぎます。
スクリプトが別のディレクトリに含まれている場合、そのベース ディレクトリが他のスクリプトが配置されているディレクトリになります。タスクはスクリプトを実行します。その親ディレクトリは作業ディレクトリではない可能性があります。したがって、最良の選択は、絶対パスを使用することです。
define('ROOT' , '/var/www/project/');
require_once(ROOT . '../.. /lib/some_class.php');
//残りのコード
絶対パスを定義しており、値はハードコードされています。パス /var/www/ も改善できます。プロジェクトも変更される可能性があります。その場合、毎回変更する必要がありますか? いいえ、次のような __FILE__ 定数を使用できます。
//スクリプトが /var/www/project/index.php であると仮定します
//次に __FILE__
define('ROOT' , pathinfo(__FILE__, PATHINFO_DIRNAME));
//残りのコード
さて、どのディレクトリに移動しても、外部サーバーに移動した場合、コードは変更せずに正しく実行できます

2. require、include、include_once、required_once を直接使用しないでください

クラス ライブラリ、ツール ファイル、ヘルパー関数などのヘッダー:
require_once('lib/Database.php'); require_once('helpers/utility_functions) .php');
この使用法は非常にオリジナルです。次のように、ファイルをインクルードするヘルパー関数を作成する必要があります。
//クラス ファイルへのパス
$ path = ROOT . $class_name . ' .php');
load_class('Database'); 何か違いはありますか?このコードはさらに読みやすくなっています。
将来的には、次のように関数を拡張できます。
functionload_class($class_name)
//クラス ファイルへのパス
$path = ROOT 。 $class_name . '.php');
if(file_exists ($path))
{
require_once( $path );
}
}
同じファイルの複数のディレクトリを検索する
簡単に変更できます各コードに個別のファイルを追加することなく、クラス ファイルが配置されるディレクトリを変更します。同様の関数を使用して、HTML コンテンツなどのファイルをロードできます。

3. アプリケーションのコードのデバッグを続けます。開発環境では、データベース クエリ ステートメントを出力し、問題のある変数値をダンプします。ただし、より良い方法は、デバッグ コードを保持することです。 ('環境' , '開発');
if(! $db->query( $query )
{
if(ENVIRONMENT == '開発')
{
echo "$クエリが失敗しました";
}
else
{
echo "データベース エラー。管理者に連絡してください"
}
}
サーバーでは、次のことができます:
define('ENVIRONMENT' , 'production'); $db->query( $query ) {
if(ENVIRONMENT == '開発')
{
echo "$query failed ";
}
else
{
echo "データベース エラー。管理者に連絡してください"
}
}

4.コマンドを実行するプラットフォーム関数

system、exec、passthru、shell_exec これらの 4 つの関数を使用できます。それぞれの動作は若干異なります。問題は、共有ホスティングでは、特定の機能が選択的に無効になる可能性があることです。初心者は、使用する前に毎回どの関数が利用可能であるかを最初に確認する傾向があります。
より良い解決策は、関数をクロスプラットフォーム関数にカプセル化することです。
functionterminal($command)
{
//システム
if(function_exists('system'))
{
ob_start();
$output = ob_get_contents()
//パススルー
; else if(function_exists('passthru'))
{
ob_start( );
$output = ob_get_contents()
}
//exec
else if( function_exists('exec')) {
exec($command, $output , $return_var);
$output = implode("n" , $output)
}
//shell_exec
else if(function_exists('shell_exec); '))
{
$output =shell_exec($command);
}
else
{
$output = 'このシステムではコマンドを実行できません'
$return_var = 1;
return array('output' => $output , 'status' => $return_var) ;
}
terminal('ls');
上記の関数は、システム関数が存在する限り、シェルコマンドを実行します。コード

5. 関数を柔軟に記述します
function add_to_cart($item_id, $qty)
{
$_SESSION['cart']['item_id'] = $qty;
add_to_cart( 'IPHONE3' , 2 );
使用上面的函数添加单个项目. 而当添加项列表的时候,你要创建另一个函数吗? 不用, 只要稍加留意不同类型的参数, 就会更灵活. 如:
function add_to_cart($item_id , $qty)
{
if(!is_array($item_id))
{
$_SESSION['cart']['item_id'] = $qty;
}
else
{
foreach($item_id as $i_id => $qty)
{
$_SESSION['cart']['i_id'] = $qty;
}
}
}
add_to_cart( 'IPHONE3' , 2 );
add_to_cart( array('IPHONE3' => 2 , 'IPAD' => 5) );
现在, 同个函数可以处理不同类型的输入参数了. 可以参照上面的例子重构你的多处代码, 使其更智能.
6. 有意忽略php关闭标签
我很想知道为什么这么多关于php建议的博客文章都没提到这点.
echo "Hello";
//Now dont close this tag
这將节约你很多时间. 我们举个例子:
一个 super_class.php 文件
class super_class
{
function super_function()
{
//super code
}
}
?>
//super extra character after the closing tag
index.php
require_once('super_class.php');
//echo an image or pdf , or set the cookies or session data
这样, 你將会得到一个 Headers already send error. 为什么? 因为 “super extra character” 已经被输出了. 现在你得开始调试啦. 这会花费大量时间寻找 super extra 的位置.
因此, 养成省略关闭符的习惯:
class super_class
{
function super_function()
{
//super code
}
}
//No closing tag
这会更好.
7. 在某地方收集所有输入, 一次输出给浏览器
这称为输出缓冲, 假如说你已在不同的函数输出内容:
function print_header()
{
echo "

";
}
function print_footer()
{
echo "";
}
print_header();
for($i = 0 ; $i < 100; $i++)
{
echo "I is : $i
';
}
print_footer();
替代方案, 在某地方集中收集输出. 你可以存储在函数的局部变量中, 也可以使用ob_start和ob_end_clean. 如下:
function print_header()
{
$o = "";
return $o;
}
function print_footer()
{
$o = "";
return $o;
}
echo print_header();
for($i = 0; $i {
echo "私は : $i
' ;
}
echo print_footer();
出力バッファリングが必要な理由: str_replaces 関数や preg_replaces など、出力を変更するか、HTML コンテンツを追加することができます。 > >ブラウザへの出力と PHP の処理を​​同時に行うと、処理と出力中にエラー メッセージが表示されるのを見たことがありますか?

8. 非 HTML コンテンツが出力される場合は、正しい MIME タイプのヘッダー情報を送信します。
$xml = ' '; $xml = "
0
//XML データを送信
echo $xml;ただし、いくつかの改善が必要です。 code>0
";
//xml データを送信
header("content-type: text/xml");
echo $xml;
ヘッダー行に注目してください。 XML タイプのコンテンツを送信していることをブラウザーに伝えます。そのため、ブラウザーはヘッダー情報にも依存します。
同様のライブラリには、JavaScript、CSS、jpg 画像、png 画像などがあります。 type: application/x-javascript");
echo "var a = 10";
CSS
header("content-type: text/css");
echo "#div id {background:#000;";

9. mysql 接続の文字エンコーディングを正しく設定する

以前、mysql テーブルに unicode/utf-8 エンコーディングが設定されており、phpadmin はそれを正しく表示できましたが、コンテンツを取得してそれをここで問題は mysql 接続の文字エンコーディングにあります
//データベースに接続しようとします
$c = mysqli_connect($this->host , $this->username, $this->) ;password);
//接続の有効性を確認します
if (! $c)
{
die ("データベース ホストに接続できませんでした:
".mysqli_connect_error());接続の文字セット
if(!mysqli_set_charset ( $c , 'UTF8' ))
{ die('mysqli_set_charset() failed')
}
データベースに接続したら、接続された文字セットを設定するのが最善ですアプリケーションで複数の言語をサポートしたい場合は、これが必要です。

10. htmlentities を使用して、正しいエンコード オプションを設定します。

php5.4 より前では、文字のデフォルトのエンコードは ISO-8859-1 です。 À â などの出力。
$value = htmlentities($this->value, ENT_QUOTES, CHARSET);
php5.4 以降では、デフォルトのエンコーディングは UTF-8 になり、アプリケーションの場合はこれで多くの問題が解決されます。

11. アプリケーションの出力では gzip 圧縮を使用しないでください。ob_gzhandler の使用を検討しましたか? それは無意味です。 PHP はアプリケーションを作成するためにのみ使用する必要があります。
Apache の mod_gzip/mod_deflate モジュール圧縮コンテンツを使用します。

動的 JavaScript コンテンツを出力する場合は、PHP を使用します。動的 JavaScript コンテンツを出力するには:
$images = array(
'myself.png' , 'friends.png' , 'colleagues.png'
); $js_code = ''; {
$js_code .= "'$image' ,"
}
$js_code = [' . $js_code . '] ';
echo $js_code ; self.png' ,'friends.png' ,'colleagues.png' ,];
もっと賢い方法としては、 json_encode を使用します: $images = array (
'myself.png' , 'friends.png' , 'colleagues.png '
);
$js_code = 'var images = ' . json_encode($images);
echo $js_code; //出力は var image = ["myself.png","friends.png","colleagues. png"]
エレガント?

13. ファイルを書き込む前に、ディレクトリの書き込み権限を確認してください

ファイルを書き込むか保存する前に、ディレクトリが書き込み可能であることを確認してください はい、書き込み可能でない場合は、エラー メッセージが出力されます。これにより、デバッグ時間を大幅に節約できます。Linux システムでは、権限を処理する必要があり、不適切なディレクトリ権限が原因で多くの問題が発生し、ファイルが読み取れなくなる可能性があります。
アプリケーションが重要な情報を出力できるように十分に機能していることを確認してください。情報。
$contents = "すべてのコンテンツ";
$file_path = "/var/www/project/content.txt";
これは一般的には正しいですが、いくつかの間接的なものもあります。 file_put_contents はいくつかの理由で失敗する可能性があります:
>>親ディレクトリが存在しない
>>ディレクトリは存在するが書き込み可能ではない
>>ファイルは書き込みロックされている
ファイルを書き込む前に明示的なチェックを実行します。
$dir = '/var/www/project'; ($dir))
{
file_put_contents($file_path , $contents);
}
else
{
die("ディレクトリ $dir が書き込み可能ではないか、存在しません。確認してください");
これを実行すると、ファイルが書き込まれた場所と失敗した理由に関する明確なメッセージが表示されます
14. アプリケーションによって作成されたファイルのアクセス許可を変更します
Linux 環境では、アクセス許可の問題により多くの時間が無駄になる可能性があります。今後は、ファイルを作成するときは必ず chmod を使用して正しいアクセス許可を設定してください。そうでない場合、ファイルは最初に「php」ユーザーによって作成された可能性がありますが、作業するには別のユーザーとしてログインしてください。システムはアクセスを拒否するか、ファイルを開くことになります。root 権限を取得したり、ファイル権限を変更したりする必要があります。
// 所有者に対しては読み取りと書き込みを行い、他の全員に対しては読み取りを行います
chmod("/somedir/somefile", 0644);
// すべては所有者のために、他の人のために読み取って実行します
chmod("/somedir/somefile", 0755);
15. フォーム送信の動作をチェックするために送信ボタンの値に依存しないでください
if($_POST[ 'submit'] == 'Save')
{
//内容を保存します

アプリケーションが多言語であることを除けば、「Save」は他の意味を持っている可能性があります。どのように区別しますか。したがって、送信ボタンの値に依存しないでください。
if( $ _SERVER['REQUEST_METHOD'] == 'POST' and isset($_POST['submit']) )
{
// 内容を保存します。
}
これで送信ボタンの値から解放されます
16. for 関数内で常に同じ値を持つ変数は静的変数として定義されます
//しばらく遅延します
function late()
{
$ sync_delay = get_option('sync_delay');
echo "
$ sync_delay 秒間遅延しています..."
echo "完了
";静的変数に置き換えます:
//しばらく遅延します
function late()
{
static $sync_lay = null;
if($sync_delay == null)
{
$sync_lay = get_option('sync_detail');
echo "
遅延中です...";
sleep ($sync_delay);
echo "Done
"; $_SESSION を使用しないでください。変数を直接使用する

いくつかの簡単な例:
$_SESSION['username'] = $username;
$ username = $_SESSION['username'];
これにより、複数のアプリケーションが同じドメイン名で実行されている場合、いくつかの問題が発生します。セッション変数は競合する可能性があります。たとえば、フロントエンド ポータルとバックエンド管理システムは同じドメイン名を使用します。ラッパー関数:
define('APP_ID' , 'abc_corp_ecommerce'); //セッション変数を取得する関数
function session_get($key)
$k = '.' ($_SESSION[$k]))
{
return $_SESSION[$k];
}
return false ;
}
//関数 session_set($key , $value)
$ k = APP_ID . '.' $key;
$_SESSION[$k] = $value;
}
18. 多くのユーティリティ関数をファイルに定義するとします。 functionutility_a()
{
//この関数は文字列処理などのユーティリティなことを行います
}
functionutility_b()
{
//この関数はデータベース処理などの他のユーティリティなことは行いません
}
functionutility_c()
{
//この関数は...
}
これらの関数の使用はアプリケーション全体に散在しています。これらをクラスにカプセル化することもできます。
class Utility { public static functionutility_a()
{
}
public static functionutility_b()
{
}
public static functionutility_c()
{
}
}
//それらを
$a = Utility::utility_a(); として呼び出します
$b = Utility::utility_b( );
明らかな利点は、php に同じ名前の組み込み関数がある場合、競合を回避できることです。
別の見方をすると、同じアプリケーション内で同じクラスの複数のバージョンを維持できるということです。これはカプセル化の基本的な利点であり、他にはありません

> >print の代わりに echo を使用してください
>>どうしても必要な場合を除き、 str_replace を使用してください。 ;>短いタグを使用しないでください
>>単純な文字列には二重引用符の代わりに一重引用符を使用してください
>>ヘッドヘビー オリエンテーションの後に必ず exit を使用してください
>> ループ内で関数を呼び出さないでください
> ;>isset は strlen より高速です
>> 常に一貫してコードをフォーマットします
>> ループや if-else 括弧を削除しないでください
if($a == true) $a_count++;
これは絶対に無駄です
次のように記述してください:
if($a == true)
$a_count++;
コードを短くするために構文を省略しないでください。
>>構文の強調表示を備えたテキスト エディタを使用すると、エラーを減らすことができます

たとえば、配列内のすべての要素をトリミングしたいとします。 : foreach($arr as $c => $v)
{
$arr[$c] = トリム($v);
ただし、array_map を使用する方が簡単です:
$arr = array_map('trim', $arr);
これは、$arr 配列の各要素に対して Trim を呼び出します。詳細については、ドキュメントを参照してください。
21. php フィルターを使用してデータを検証する
電子メールや IP アドレスなどを検証するために正規表現を使用する必要があります。はい、皆さんもそれを使用します。次に、
php のフィルターと呼ばれる別の方法を試してみましょう。拡張機能は、入力を検証およびチェックする簡単な方法を提供します
$amount = intval( $_GET['amount'] ); $rate = (int) $_GET[' rate'];これは良い習慣です

23. 必要に応じて、xdebug などのプロファイラーを使用してください
PHP を使用して大規模なアプリケーションを開発する場合、PHP は多くの計算を実行するため、速度が非常に重要な指標になります。コードの最適化に役立ちます。
24. 大きな配列は注意して処理してください。大きな配列と文字列の場合、よくあるエラーは、配列のコピーによってメモリ オーバーフローが発生し、致命的なエラーが発生することです。メモリ サイズがスローされます。 情報: $db_records_in_array_format; //これは、それぞれ 20 列を持つテーブルからの 1000 行を保持する大きな配列であり、各行は少なくとも 100 バイトであるため、合計 1000 * 20 * 100 = 2MB
$cc = $ db_records_in_array_format; //さらに 2MB
some_function($cc); //これは、CSV ファイルをインポートまたはエクスポートするときによく行われます
メモリ制限により、スクリプトがクラッシュすることはあまりありません。小さな変数の場合は問題ありませんが、大きな配列を扱う場合は必ず回避する必要があります: $a = get_large_array();
pass_to_function(&$a);
これを行った後、(配列をコピーする代わりに) 変数参照を関数に渡します。
class A
{
function first()
{
$this->a = get_large_array(); を参照してください。 ->pass_to_function();
}
function pass_to_function( )
{
//process $this->a
}
}
メモリを解放し、スクリプトの負担を軽減するために、できるだけ早く設定を解除してください。 25. 最初から最後まで単一のデータベース接続を使用します
スクリプトが最初から最後まで単一のデータベース接続を使用していることを確認してください。最初に接続を正しく開き、最後まで使用し、最後に閉じないでください。次のような関数で接続を開きます:
function add_to_cart()
{
$db = new Database();
$db->query("INSERT INTO....")
function empty_cart ()
{
$db = new Database();
$db->query( "DELETE FROM .....")
} 複数の接続を使用すると、アプリケーションの速度が低下します。接続の作成には時間とメモリが必要なため、
データベース接続などの特定の状況ではシングルトン パターンを使用してください。 次のようなステートメントをあまりにも多く記述するのは避けてください。 $query = "ユーザー (名前、メールアドレス、電話番号) に挿入 VALUES('$name', '$email ' , '$address' , '$phone')"; ); //mysqli_query() を呼び出します
これにはいくつかの欠点があります:
>> クエリが正しいことを確認するクエリ内のエラーを特定するには時間がかかります (毎回 if-else でチェックしない限り)
>> 複雑なメンテナンスが難しいため、クエリ
は関数を使用してカプセル化されます:
function insert_record($table_name , $data)
{
foreach($data as $key => $value)
{
//mysqli_real_escape_string
$data[$key] = $db ->mres($value)
}
$fields = implode(', ' , array_keys($data));
$values = "'" . implode("','" , array_values($data))
//最後のクエリ $query = " {$table}($fields) VALUES($values)";
return $db->query($query);
}
$data = array('name' => $name , 'email' => $email , 'address' => $address , 'phone' => $phone);
insert_record('users' , $data);
これは、より読みやすく、拡張可能です。
最大の利点は、データが配列に前処理されることです。
この関数は定義される必要があります。データベース クラスでは、 $db->insert_record のように呼び出すことができます。
データベースの処理を簡単にする方法については、この記事を参照してください。
同様に、update、select、および delete メソッドを作成することもできます。試してみてください。
27. データベースで生成されたコンテンツを静的ファイルにキャッシュします。すべてのコンテンツがデータベースから取得されたら、次回ページがリクエストされたときにそれらを一時ファイルに保存する必要があります。データベースをチェックする必要がなく、キャッシュから直接フェッチできます。
利点:
>>PHP ページの処理時間を節約し、より高速に実行します
>>データベース クエリが少なくなり、MySQL 接続のオーバーヘッドが減ります

28。データベース内のセッション
ファイルベースのセッション戦略には多くの制限があります。セッションは単一のサーバーに保存されるため、クラスターに拡張することはできません。問題を解決します。
セッション データをデータベースに保存すると、さらに多くの利点があります。
>> 同じユーザー名で同時に 2 か所にログインできない問題を解決します。 ; より準備ができる オンライン ユーザーのステータスを問い合わせる

>>定義/定数を使用する
>>クラスを使用してアクセスする$this
30. in head
で Base タグを使用します。以下を参照してください:



が非常に便利だとします。いくつかのサブディレクトリに分かれており、すべてに同じナビゲーション メニューが含まれています www.domain.com/store/home.php
www.domain.com/store/products/ipad.php
ホーム ページでは、次のように記述できます。 ホーム
iPad
Home
iPad ディレクトリが違うのはひどいことです。さまざまなバージョンのナビゲーション メニューを維持するため、

<ボディ>

;

次に、このコードをすべてのアプリケーション ディレクトリに適用します。

無関係なエラー レポートをオフにします。 1);
error_reporting (~E_WARNING & ~E_NOTICE & ~E_STRICT);

整数の長さは 32 ビット アーキテクチャと 64 ビット アーキテクチャでは異なることに注意してください。 64 ビット マシンでは、次の出力が表示されます。 ('1000-01-30');
-30607739600
php > echo strtotime('2100-01-30')
4104930600
ただし、32 ビット マシンでは、 bool(false) になります。詳細はこちら

33. set_time_limit にあまり依存しないでください

最小時間を制限したい場合は、次のスクリプトを使用できます:
set_time_limit(30);
残りのコードは、落ち着いてください。システムコール、ソケット操作、データベース操作などの外部実行に注意してください
したがって、データベースのクエリに時間がかかっても、スクリプトは実行されません。実行を停止します。

34. 拡張ライブラリを使用します いくつかの例:
>>PHPExcel -- Excel の読み取りと書き込み
> >PhpMailer -- 近くのアイテムを含む電子メールの送信を簡単に処理します
>> pChart - php を使用してレポートを生成します
オープンソース ライブラリを使用して、PDF、ms-excel ファイル、レポートなどの生成などの複雑なタスクを完了します
35. MVC フレームワークを使用する
codeigniter のような MVC フレームワークを使用する時が来ました。MVC フレームワークは、php コードを html から分離するだけです。デザイナーは、php コードと html コードを明確に区別します。とプログラマは同時に作業できます
>>オブジェクト指向に設計された関数によりメンテナンスが容易になります
>>組み込み関数により多くの作業が完了し、繰り返し記述する必要はありません。
>>開発 大規模なアプリケーションは必須です
>> 多くの提案、トリック、ハックがフレームワーク

36 によって実装されています 時々 phpbench をチェックしてください
phpbench は、基本的な PHP 操作のベンチマーク結果を提供します。
文法の変更がどのように大きな違いを生むのかを示しています。
PHP サイトのコメントを確認し、IRC で質問し、オープンソース コードをよく読み、Linux を使用して開発します。
OSCHINA によるオリジナルの翻訳。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/325847.html技術記事 1. 相対パスを使用しないでください: require_once('../../lib/some_class.php'); このメソッドには多くの欠点があります。最初に指定された php インクルード パスを検索し、次に現在のディレクトリです。