ホームページ >バックエンド開発 >PHPチュートリアル >PHP の PSR 仕様とは何ですか?
PHP における PSR 仕様とは、PHP Standard Recommendations の略で、PHP FIG 団体によって策定された PHP 開発の実用的な標準仕様です。
PSR は、PHP Standard Recommendations の略で、PHP FIG 団体によって策定された PHP の仕様であり、PHP 開発のための実用的な標準です。
PHP FIG は、Framework Interoperability Group の略称で、2009 年に数人のオープンソース フレームワーク開発者によって設立されました。 Laravel、Joomla、Drupal、Composer、Phalcon、Slim、Symfony、Zend Framework など)、「公式」組織ではありませんが、PHP コミュニティの大部分を代表しています。
プロジェクトの目的は、フレームワークの作成者またはフレームワークの代表者間の議論を通じて、最小限の制限レベルのコラボレーション標準を開発することです。各フレームワークは、各社独自の開発を妨げないよう、統一されたコーディング標準に従います。 PHP の開発は、プログラマーにとってのこの長年の問題を解決します。
これまでに、php-fig は 5 つの仕様をリリースしました:
PSR-0: 自動ロード標準、2014-10-21 標準廃止され、PSR-4 に置き換えられました。詳細は不明です。コーディング スタイル (より厳密)
PSR-3: ロガー インターフェイス
PSR -4:
PHP タグ:
エンコーディング: PHP ファイルは BOM フリーの UTF-8 エンコーディングを使用する必要があります。
副作用:
PHP ファイルでは、シンボル (クラス、関数、定数など) を定義したり、固有の副作用 (出力結果、プロセス データなど) のみを使用して操作を実行したりできます。 、など)、しかし同時にはできません。これら 2 つのことを行うには、PHP ファイルの単一の関数を持たせるようにしてください。運用する際は、変数、クラス、関数の宣言を分離し、include ファイルや require ファイルを通じて使用するようにしてください。
以下は仕様に準拠しません:
以下は仕様に準拠します:名前空間とクラス:
名前空間とクラスは、PSR-4 オートローダー標準に従う必要があります。
<?php // 改变设置 ini_set('error_reporting', E_ALL); // 加载文件 include "file.php"; // 打印输出 echo "<html>\n"; // 声明 function foo() { // function body }クラス名: 各クラスには独自の名前空間があり、最上位の名前空間の下にあります。クラス名には CamelCase を使用する必要があります。
<?php // 声明 function foo() { // function body } // 条件判断 if (! function_exists('bar')) { function bar() { // function body } }
PHP 5.3 以降では、正式な名前空間を使用する必要があります。例:
PHP 5.3 以降では、Vendor_ で始まる疑似名前空間規則を使用する必要があります。例:定数:
定数はすべて大文字で、アンダースコア (_) で区切る必要があります。例:
<?php // PHP 5.3 及以后 namespace Vendor\Model; class Foo { }
クラスのメソッド:
<?php // PHP 5.3以下 class Vendor_Model_Foo { }クラスのメソッドは、小文字で始まるキャメルケースで名前を付ける必要があります。
PSR-2
<?php namespace Vendor\Model; class Foo { const VERSION = '1.0'; const DATE_APPROVED = '2012-06-01'; }
PSR-2 は PSR-1 の PHP 拡張機能です。
PSR-1 の実装:PSR-2 コード標準を使用する前に、まず PSR-1 コード標準を実装する必要があります。
ファイルとコード行:
PHP ファイルは Unix スタイルの改行 (LF、ラインフィード) を使用し、最後に空白行を含める必要があります。ファイルには PHP コードのみが含まれているため、閉じることはできません。 PHP Tag?> を使用する場合、コードの各行は 80 文字を超えてはならず、各行の末尾にスペースを入れてはならず、1 行に 1 つのステートメントのみを含めることができ、適切な場所に空白行を追加して改善することができます。コードの読みやすさ。 終了タグを追加しないと、予期しない出力エラーを回避できます。終了タグが追加され、終了タグの後に空白行がある場合、その空白行が出力とみなされ、予期しない出力が発生します。 。 エラー。
インデント:
は 4 つのスペースでインデントする必要があり、インデントにタブ文字 (Tab キー) は使用できません。
異なるエディターでも、スペースのレンダリング効果は基本的に同じですが、タブ文字の幅は異なります。
キーワード:
PHP キーワードは小文字である必要があり、true、false、および null も小文字である必要があります。
名前空間と use 宣言:
ここで、名前空間宣言の後には空行が必要であり、use 宣言は名前空間の後に配置する必要があり、名前空間を個別に導入するために use を使用する必要があります。 、使用後 空行が必要です。例:
クラスの継承と実装: extends およびimplements キーワードはクラス名と同じ行になければなりません、クラス、インターフェイス、および特性の定義本体の先頭にあります。左括弧はクラス名の後の新しい行で開始する必要があり、閉じ括弧も新しい行で開始する必要があります。例:実装後に実装されるインターフェースが多く、行が非常に長い場合は、次のように、必要なクラスを 1 つずつ開始し、スペースを 4 つインデントします。
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; // ... additional PHP code ...
Visibility:
クラス内のすべての属性とメソッドは、public、private、protected を含めて可視性を宣言する必要があります。古いバージョンの PHP では、宣言できる属性は 1 つだけです。行、例:
<?php namespace Vendor\Package; use FooClass; use BarClass as Bar; use OtherVendor\OtherPackage\BazClass; class ClassName extends ParentClass implements \ArrayAccess, \Countable { // constants, properties, methods }
メソッド:
类中的所有方法也应该定义可见性,方法名后面不能有空格,方法体的括号位置和类定义体的括号位置一样,都要新起一行,结束括号也要新起一行。方法参数的起始圆括号之后没有空格,结束括号之前也没有空格,有多个参数是,每个参数的逗号后面加一个空格,例如:
<?php namespace Vendor\Package; class ClassName { public function fooBarBaz($arg1, &$arg2, $arg3 = []) { // method body } }
如果参数比较多,需要换行时,可以如下:
<?php namespace Vendor\Package; class ClassName { public function aVeryLongMethodName( ClassTypeHint $arg1, &$arg2, array $arg3 = [] ) { // method body } }
abstract、final和static:
现在,abstract、final必须在可见性修饰符之前,static声明必须放在可见性修饰符之后,例如:
<?php namespace Vendor\Package; abstract class ClassName { protected static $foo; abstract protected function zim(); final public static function bar() { // method body } }
方法和函数的调用:
在调用方法和函数时,圆括号必须跟在函数名之后,函数的参数之间有一个空格:
<?php bar(); $foo->bar($arg1); Foo::bar($arg2, $arg3);
如果参数比较多,一行放不下时,如下处理:
<?php $foo->bar( $longArgument, $longerArgument, $muchLongerArgument );
PHP的控制结构:
PHP的控制结构包括if、else、elseif、switch、case、while、do while、for、foreach、try和catch。如果这些关键词后面有一对原括号,开始括号前必须有一个空格,与方法和类的定义体不同,控制结构关键词后面的起始括号应该和控制结构关键词写在同一行,例如:
<?php $gorilla = new \Animals\Gorilla; $ibis = new \Animals\StrawNeckedIbis; if ($gorilla->isWake() === true) { do { $gorilla->beatChest(); } while ($ibis->isAsleep() === true); $ibis->flyAway(); }
PHP闭包函数:
闭包函数在声明时,function关键词后必须有一个空格,同时use关键词前后也必须有一个空格。起始大括号不需要另起新行,详细的如下代码:
<?php $closureWithArgs = function ($arg1, $arg2) { // body }; $closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) { // body };
闭包函数有多个参数时,处理方式和方法的参数一样:
<?php $longArgs_noVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) { // body }; $noArgs_longVars = function () use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_longVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body }; $longArgs_shortVars = function ( $longArgument, $longerArgument, $muchLongerArgument ) use ($var1) { // body }; $shortArgs_longVars = function ($arg) use ( $longVar1, $longerVar2, $muchLongerVar3 ) { // body };
注意:以上规则同样适用于将闭包作为函数或方法的参数,如下:
<?php $foo->bar( $arg1, function ($arg2) use ($var1) { // body }, $arg3 );
到2019-08-10,PSR-2已被官方废弃
PSR-3
与PSR-1和PSR-2不同,PSR-3规定了一套通用的日志记录器接口(Psr\Log\LoggerInterface),为了符合PSR-3规范,框架必须实现该规范中的接口,这样可以更多的兼容第三方应用。PSR-3规范中包含了9个方法,每个方法都对应了RFC 5424协议的一个日志级别,而且都接受两个参数$message和$context,如下:
<?php namespace Psr\Log; /** * Describes a logger instance * * The message MUST be a string or object implementing __toString(). * * The message MAY contain placeholders in the form: {foo} where foo * will be replaced by the context data in key "foo". * * The context array can contain arbitrary data, the only assumption that * can be made by implementors is that if an Exception instance is given * to produce a stack trace, it MUST be in a key named "exception". * * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md * for the full interface specification. */ interface LoggerInterface { /** * System is unusable. * * @param string $message * @param array $context * @return void */ public function emergency($message, array $context = array()); /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return void */ public function alert($message, array $context = array()); /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return void */ public function critical($message, array $context = array()); /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return void */ public function error($message, array $context = array()); /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return void */ public function warning($message, array $context = array()); /** * Normal but significant events. * * @param string $message * @param array $context * @return void */ public function notice($message, array $context = array()); /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return void */ public function info($message, array $context = array()); /** * Detailed debug information. * * @param string $message * @param array $context * @return void */ public function debug($message, array $context = array()); /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return void */ public function log($level, $message, array $context = array()); }
关于message参数:
$message必须是一个字符串或者是含有__toString()方法的对象,$message应该包含占位符,例如{placeholder_name},占位符由{、占位符名称和}组成,不能包含空格,占位符名称可以由A-Z, a-z, 0-9, _组成,第三方实现可以用$context参数来替换占位符,占位符名称必须和$context数组的key对应。如下例子是使用$context中的值替换$message中的占位符:
<?php /** * Interpolates context values into the message placeholders. */ function interpolate($message, array $context = array()) { // build a replacement array with braces around the context keys $replace = array(); foreach ($context as $key => $val) { // check that the value can be casted to string if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { $replace['{' . $key . '}'] = $val; } } // interpolate replacement values into the message and return return strtr($message, $replace); } // a message with brace-delimited placeholder names $message = "User {username} created"; // a context array of placeholder names => replacement values $context = array('username' => 'Bolivar'); // echoes "User Bolivar created" echo interpolate($message, $context);
关于context参数:
$context是一个数组参数,用于构造复杂的日志消息,$context中的值不能抛出任何PHP异常或错误。如果$context中包含Exception对象,则该对象的key必须为exception。
PSR-3日志记录器的使用
推荐使用monolog/monolog,这样可以让我们不需要浪费更多的时间在编写一个日志记录器了。Monolog组建完全实现了PSR-3接口,而且便于使用自定义的消息格式化程序和处理程序扩展功能,通过Monolog可以把日志消息写入文本文件、系统日志和数据库中,还能通过电子邮件发送,并且还支持Slack和远程服务器。如下展示了如何设置Monolog,并把日志消息写入文本文件:
use Monolog/Logger; use Monolog/Handler/StreamHandler; // 创建日志记录器 $log = new Logger('myApp'); $log->pushHandler(new StreamHandler('logs/development.log, Logger::DEBUG)); $log->pushHandler(new StreamHandler('logs/production.log', Logger::WARNING)); // 使用日志记录器 $log->debug("This is a debug message"); $log->warning("This is a warning message");
PSR-4
PSR-4规范描述了一个标准的自动加载器策略,指在运行时按需查找PHP类、接口或Traits。支持PSR-4自动加载器标准的PHP组建和框架,使用同一个自动加载器就能找到相关代码,然后将其载入PHP解释器。有了这个功能,就可以把现代PHP生态系统中很多客户操作的组件联系起来。
编写一个PSR-4自动加载器
PSR-4规范不要求改变代码的实现方式,只建议如何使用文件系统目录结构和PHP命名空间组织代码,PSR-4规范以来PHP命名空间和文件系统目录结构查找并加载PHP类、接口和Traits,这正是PSR-4的精髓所在。下面我们来自己手动实现一个PSR-4自动加载器:
<?php /** * 使用SPL组册这个自动加载函数后,遇到下述代码时这个函数会尝试 从/path/to/project/src/Baz/Qux.php文件中加载\Foo\Bar\Baz\Qux类: * new \Foo\Bar\Baz\Qux; * @param string $class 完全限定的类名。 * @return void **/ spl_autoload_register(function ($class) { // 项目的命名空间前缀 $prefix = 'Foo\\Bar\\'; // 目录前缀对应的根目录 $base_dir = __DIR__ . '/src/'; // 判断传入的类是否使用了这个命名空间前缀 $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // 没有使用,交给注册的下一个自动加载器处理 return; } // 获取去掉前缀后的类名 $relative_class = substr($class, $len); // 把命名空间前缀替换成根目录, // 在去掉前缀的类名中,把命名空间分隔符替换成目录分隔符, // 然后在后面加上.php $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // 如果该文件存在,就将其导入 if (file_exists($file)) { require $file; } });
更多相关知识,请访问 PHP中文网!!