顯示具有 程式-PHP 標籤的文章。 顯示所有文章
顯示具有 程式-PHP 標籤的文章。 顯示所有文章

2016年12月25日 星期日

從實例學設計模式 by jaceju



from : http://slides.com/jaceju/design-patterns-by-examples#/

2016年12月16日 星期五

phpstorm connection with xdebug was not established. validate installation

Another way to solve it - to change the port of xdebug in php.ini. For example to 9001:
xdebug.remote_port=9001
After that you need to change xdebug port in PhpStorm in Preferences->Languages & Frameworks -> PHP -> Debug. Xdebug port set to 9001.

from : http://stackoverflow.com/questions/31285486/connection-between-phpstorm-and-xdebug

Cannot tap homebrew/php: invalid syntax in tap!

Make sure you're not stuck behind the update bug as well.
cd $(brew --prefix) && git fetch && git reset --hard origin/master


from : https://github.com/Homebrew/homebrew-php/issues/3558

Mac OSX php7 curl error 35 fixed

I've seen this error happen when php is compiled with a version of cURL that uses Apple's Secure Transport under Yosemite and the target of the URL request doesn't support SSLv3 (which was probably disabled due to the POODLE vulnerability). What is the output of this command?
$ php -i | grep "SSL Version"
I suspect you'll see this:
SSL Version => SecureTransport
You can overcome this by installing a version of php which uses a version of cURL which uses OpenSSL instead of SecureTransport. This is most easily done with homebrew. So install that first if you don't already have it. If homebrew is installed but you haven't run brew update since upgrading to Yosemite, do that first. Also make sure you've installed XCode >= 6.1 and the latest XCode command line tools. brew doctor will tell you if you've done it all right.
Add the Homebrew taps below that you will need in order to get brewed php installed. Skip this step if these repos are already tapped. If you're unsure if these repos are already tapped, just run the commands below. Worst case scenario, you'll get a harmless Warning: Already tapped!
$ brew tap homebrew/dupes
$ brew tap homebrew/versions
$ brew tap homebrew/php
Then install curl with openssl:
$ brew install --with-openssl curl
Then install php using the curl you just installed and brewed openssl:
$ brew install --with-homebrew-curl php55
  • if using apache, make sure to add LoadModule php5_module /usr/local/opt/php55/libexec/apache2/libphp5.so to your /etc/apache2/httpd.confand restart apache.
  • if using nginx, follow the caveat instuctions for starting fpm:
    To launch php-fpm on startup:
    mkdir -p ~/Library/LaunchAgents
    cp /usr/local/opt/php55/homebrew.mxcl.php55.plist ~/Library/LaunchAgents/
    launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.php55.plist
Install any php extensions you're going to need eg. mcrypt.
$ brew install php55-mcrypt
After you're done, run this again:
$ php -i | grep "SSL Version"
And you should see:
SSL Version => OpenSSL/1.0.2h
And now, re-test your application

from : http://stackoverflow.com/questions/26461966/osx-10-10-curl-post-to-https-url-gives-sslread-error

2016年12月11日 星期日

Use Schema::hasTable outside laravel

use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Schema\Blueprint;

Capsule::schema()->hasTable

2016年11月22日 星期二

PHP写的一个轻量级的DI容器类

摘要: 理解什么是Di/IoC,依赖注入/控制反转。两者说的是一个东西,是当下流行的一种设计模式。大致的意思就是,准备一个盒子(容器),事先将项目中可能用到的类扔进去,在项目中直接从容器中拿,也就是避免了直接在项目中到处new,造成大量耦合。取而代之的是在项目类里面增设 setDi()和getDi()方法,通过Di同一管理类。 当然,以上内容并不是重点,详细的概念推荐参考这篇文章: http://docs.phalconphp.com/en/latest/reference/di.html 中文版: http://phalcon.5iunix.net/reference/di.html
直接上代码吧.
Di容器类:

class Di implements \ArrayAccess{
    private $_bindings = array();//服务列表
    private $_instances = array();//已经实例化的服务
    
    //获取服务
    public function get($name,$params=array()){
        //先从已经实例化的列表中查找
        if(isset($this->_instances[$name])){
            return $this->_instances[$name];
        }
        
        //检测有没有注册该服务
        if(!isset($this->_bindings[$name])){
            return null;
        }
        
        $concrete = $this->_bindings[$name]['class'];//对象具体注册内容
        
        $obj = null;
        //匿名函数方式
        if($concrete instanceof \Closure){
            $obj = call_user_func_array($concrete,$params);
        }
        //字符串方式
        elseif(is_string($concrete)){
            if(empty($params)){
                $obj = new $concrete;
            }else{
                //带参数的类实例化,使用反射
                $class = new \ReflectionClass($concrete);
                $obj = $class->newInstanceArgs($params);
            }
        }
        //如果是共享服务,则写入_instances列表,下次直接取回
        if($this->_bindings[$name]['shared'] == true && $obj){
            $this->_instances[$name] = $obj;
        }
        
        return $obj;
    }
    
    //检测是否已经绑定
    public function has($name){
        return isset($this->_bindings[$name]) or isset($this->_instances[$name]);
    }
    
    //卸载服务
    public function remove($name){
        unset($this->_bindings[$name],$this->_instances[$name]);
    }
    
    //设置服务
    public function set($name,$class){
        $this->_registerService($name, $class);
    }
    
    //设置共享服务
    public function setShared($name,$class){
        $this->_registerService($name, $class, true);
    }
    
    //注册服务
    private function _registerService($name,$class,$shared=false){
        $this->remove($name);
        if(!($class instanceof \Closure) && is_object($class)){
            $this->_instances[$name] = $class;
        }else{
            $this->_bindings[$name] = array("class"=>$class,"shared"=>$shared);
        }
    }
    
    //ArrayAccess接口,检测服务是否存在
    public function offsetExists($offset) {
        return $this->has($offset);
    }
    
    //ArrayAccess接口,以$di[$name]方式获取服务
    public function offsetGet($offset) {
        return $this->get($offset);
    }
    
    //ArrayAccess接口,以$di[$name]=$value方式注册服务,非共享
    public function offsetSet($offset, $value) {
        return $this->set($offset,$value);
    }
    
    //ArrayAccess接口,以unset($di[$name])方式卸载服务
    public function offsetUnset($offset) {
        return $this->remove($offset);
    }
}


演示:



header("Content-Type:text/html;charset=utf8");
class A{
    public $name;
    public $age;
    public function __construct($name=""){
        $this->name = $name;
    }
}

include "Di.class.php";
$di = new Di();
//匿名函数方式注册一个名为a1的服务
$di->setShared('a1',function($name=""){
    return new A($name);
});
//直接以类名方式注册
$di->set('a2','A');
//直接传入实例化的对象
$di->set('a3',new A("小唐"));

$a1 = $di->get('a1',array("小李"));
echo $a1->name."
";//小李
$a1_1 = $di->get('a1',array("小王"));
echo $a1->name."
";//小李
echo $a1_1->name."
";//小李

$a2 = $di->get('a2',array("小张"));
echo $a2->name."
";//小张
$a2_1 = $di->get('a2',array("小徐"));
echo $a2->name."
";//小张
echo $a2_1->name."
";//小徐

$a3 = $di['a3'];//可以直接通过数组方式获取服务对象
echo $a3->name."
";//小唐
通过set和setShared方式注册服务,支持 匿名函数,类名字符串,已经实例化的对象,两者的区别是:
set方式注册的,每次获取的时候都会重新实例化
setShared方式的,则只实例化一次,也就是所谓的单例模式
当然,对于直接注册已经实例化的对象,如上代码中的a3服务,set和setShared效果是一样的。
通过$di->get()获取服务,可接受两个参数,第一个参数是服务名,比如a1,a2,a3是必须的,第二个参数是一个数组,第二个参数会被当作匿名函数中的参数或者类构造函数里的参数传进去,参考call_user_func_array()。
删除服务则可以通过
unset($di['a1']);
or
$di->remove('a1');

判断是否包含一个服务可以通过
isset($di['a1']);
or
$di->has('a1');
就这么多了。

from : https://my.oschina.net/cxz001/blog/227482

2016年11月17日 星期四

PHP Mockery - mock protected properties and methods


$myMock = Mockery::mock('myClass')->shouldAllowMockingProtectedMethods();

from : http://stackoverflow.com/questions/31978749/is-it-possible-to-mock-protected-properties-and-methods

PSR-2 PHP Coding Style

相較於其他Web後端技術,PHP的一大特色是有眾多framework支援,有macro framework如Symfony與Laravel,也有micro framework如Silex與Slim,更有較早期的CodeIgniter。
PHP的各framework蓬勃發展是一種良性競爭,但也導致各framework一直在重新製造輪子。若能讓PHP的framework各展所長,彼此互相合作,就必須大家遵守一個共同的標準,這就是PHP-FIG的PSR。

PHP-FIG


為了解決這個問題,PHP各framework代表在2009年建立了PHP-FIG (PHP Framework Interop Group),目的在建立各framework所遵守得共同標準,讓彼此可以互相合作。

Framework之間互相合作


各framework要能互相合作使用,有3個前提必須遵守。

Interface

各framework藉由使用相同的interface,達成互相合作。因為只要該framework實作相同的interface,別的framework就可拿來使用。
如寫log的功能,各大framework都需要,為了不讓每個framework重新製造輪子,只要有人實踐emergency(), alert(), critical(), error(), warning(), notice(), info(), 與debug()這樣interface的物件,其他framework都可以拿來用,而不用在乎它是哪個framework所提供的或如何實作。11事實上這就是PSR-3。

Autoloading

各framework藉由使用相同的方法載入物件,達成互相合作。因為各framework底層載入物件的方式相同,只要同一套autoloader就能載入各framework的物件。
在此之前,各framework各自實作自己的autoloader,有的使用\_autoload(),有的使用spl_autoload_register(),導致每用一套framework,就必須去熟悉其autoloader。22事實上這就是PSR-4。

Coding Style

各framework藉由使用相同的coding style,達成互相合作。因為大家使用相同的coding style,可以更容易的去trace其他framwork的code,而不用去學習新的coding style。
相同的coding style對於一個團隊也是很有幫助,假如每個成員都有自己的coding style,要去trace或了解其他成員的code將更花時間,也更難達成code review的目的。這也是本文希望藉由PHP-FIG的PSR-2來統一團隊成員中的coding style的原因。

PSR


PSR是PHP Standard Recommendation的縮寫,對於各framework都會遇到的問題,PSR提出建議的解決方案,而非各framework不斷各自解決相同的問題。
目前已經正式提出的PSR如下 :
  1. PSR-1: Basic coding style
  2. PSR-2: Strict coding style
  3. PSR-3: Logger interface
  4. PSR-4: Autoloading
  5. PSR-7: HTTP message interface

PSR-2 Coding Style


PSR-1定義出PHP應該遵守的最基本coding style,PSR-2則以PSR-1為基礎定義出更嚴格的建議。以下整理出PSR-1與PSR-2所建議的coding style。

縮排

使用4個space,不要使用tab。

每行字數

建議在每行80個字左右,最多不要超過120個字。

PHP標籤

  • PHP必須使用或,不可以使用其他標籤。
  • 若PHP不包含HTML,則不用使用結束標籤?>。

字元編碼

PHP必須使用無BOM的UTF-8編碼。33雖然看起來很複雜,但不用擔心,一般文字編輯器或IDE會幫你處理。

Function

1
2
3
4
5
6
7
8
9
10
11
function sayHello($arg1, $arg2 = 'Hi')
{
    echo($arg1 . $arg2);
}

function sayHello(
    $arg1,
    $arg2 = 'Hi'
) {
    echo($arg1 . $arg2)
}
  • 使用camelCase。
  • {必須換行。
  • Function名稱與(之間不要留空白。
  • 參數的,之前 不可以有空白,而,之後需留一個空白。
  • 參數列若提供預設值,則必須放在最後一個參數。
  • 參數列允許多行寫法,第一個參數要在新的一行,且每一行只有一個參數。
  • 參數列的結束)要在新的一行,且與)與{同行,之間要留一個空白。

Namespace

1
2
3
4
5
6
7
8
9
10
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class SimpleClass 
{
    ...
}
  • 使用CamelCase命名。
  • namespace與之間需空一行。
  • namespace宣告與use之間需空一行,use與class之間再空一行。
  • 最上層namespace使用公司名稱。
  • 每個class都要使用namespace,最少搭配一層namespace。

Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class SimpleClass
{
    ...
}

class ChildClass extends ParentClass
{
    ...
}

class ImplClass implements ContractInterface
{
    ...
}

class ImpClass implements 
    FirstInterface,
    SecondInterface,
    ThirdInterface
{
    ...
}
  • 使用CamelCase命名。
  • 一個class一個檔案。
  • extends與implements需與class同一行。
  • 括號{必須換新的一行。
  • implements的interface允許多行寫法,第一個interface要在新的一行,且每一行只有一個interface。

Interface

1
2
3
4
interface PostRepositoryInterface
{
    public function getLatest3Posts();
}
  • 使用CamelCase命名。
  • 一個interface一個檔案。
  • 括號{必須換新的一行。

Trait

1
2
3
4
5
6
7
8
9
10
11
12
trait LogTrait
{
    public function startLog()
    {
        (略)
    }

    public function stopLog()
    {
        (略)
    }
}
  • 使用CamelCase命名。
  • 一個trait一個檔案。
  • 括號{必須換新的一行。

Constant

1
2
3
4
5
6
7
namespace Vendor\Model;

class Foo
{
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}
  • 使用全大寫命名。
  • 單字間以_隔開。

Property

1
2
3
4
5
6
7
class SimpleClass
{
    public $userName;
    public static $userCountry;
    private $userPassword;
    protected $userAddr;
}
  • 使用camelCase命名。44PSR-1並沒有對property做明確規定要使用camelCase,只要求整個project或package風格統一即可,Laravel使用的是camelCase,若只有一個單字則使用小寫。
  • 必須加上visibility (public, protected, private)。
  • static必須加在visibility之後。
  • 不要再使用var宣告public property。
  • 不要再使用_宣告protected或private property。

Method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class SimpleClass
{
    public function displayName() 
    {
        ...
    }

    abstract protected function sendMessage()
    {
        ... 
    }


    final public function sendEmail()
    {
     ...
    }

    public static function sendSMS()
    {
     ...
    }

    final public static function sendJson()
    {
     ...
    }

    public function singleLineArgument($arg1, &$arg2, array $arg3 = [])
    {
        ...
    }

    public function multiLineArgument(
        $arg1,
        &$arg2,
        array $arg3 = []
    ) {
       ...
    }
}
  • 使用camelCase命名。
  • {必須換新的一行。
  • 必須加上visibility (public, protected, private)。
  • abstract與final必須加在visibility之前。
  • static必須加在visibility之後。
  • 不要再使用_宣告protected或private method。
  • Method名稱與(之間不要留空白。
  • 第一個(之後 不可以有空白,最後一個)之前 不可以有空白。
  • 參數的,之前 不可以有空白,而,之後需留一個空白。
  • 參數列若提供預設值,則必須放在最後一個參數。
  • 參數列允許多行寫法,第一個參數要在新的一行,且每一行只有一個參數。
  • 參數列的結束)要在新的一行,且與)與{同行,之間要留一個空白。

Method and Function Calls

1
2
3
4
5
6
7
8
9
func();
$foo->method1($arg1);
Foo::method2($arg2, $arg3);

$foo->method3(
    $arg1,
    $arg2,
    $arg3
);
  • Method或function名稱與(之間不可以有空白。
  • 第一個(之後 不可以有空白,最後一個)之前 不可以有空白。
  • 每個,之前不可以有空白,每個,之後需留一個空白。
  • 引數列允許多列寫法,第一個引數要在新的一行,且每一行只有一個引數。
  • 參數列的結束)要在新的一行。

Closure

1
2
3
4
5
6
7
$closureWithArgs = function ($arg1, $arg2) {
    // body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // body
};
  • function與(之間需留一個空白。
  • use前後都需要留一個空白。
  • {必須與function 同一行。55Function與method是要求{必須換新的一行,但closure要求{與function在同一行。
  • 第一個(之後 不可以有空白,最後一個)之前 不可以有空白。
  • 參數的,之前不可以有空白,而,之後需留一個空白。
  • 參數列若提供預設值,則必須放在最後一個參數。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
$cl1 = function (
    $arg1,
    $arg2,
    $arg3
) {
    ...
};

$cl2 = function () use (
    $var1,
    $var2,
    $var3
) {
    ...
};


$cl3 = function (
    $arg1,
    $arg2,
    $arg3
) use ($var1) {
    ...
};

$cl4 = function ($arg1) use (
    $var1,
    $var2,
    $var3
) {
   ...
};

$cl5 = function (
    $arg1,
    $arg2,
    $arg3
) use (
    $var1,
    $var2,
    $var3
) {
    ...
};
  • 參數列允許多行寫法,第一個參數要在新的一行,且每一行只有一個參數。
  • 參數列的結束括號要在新的一行,且與)與{同行,之間要留一個空白。

if else elseif

1
2
3
4
5
6
7
if ($expr1) {
    // if body
} elseif ($expr2) {
    // elseif body
} else {
    // else body;
}
  • {與if, elseif, else要在同一行,不用換行。
  • }與elseif要在同一行,不用換行。
  • }與else要在同一行,不用換行。

switch case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}
  • {與switch在同一行。
  • case後的條件與:之間不可以有空白。
  • case必須縮排於switch,而break必須縮排於case。
  • PHP允許case內沒有break,但需在第一個case 加上//no break註解。

while

1
2
3
while ($expr) {
    ...
}
  • {與while在同一行。

do while

1
2
3
do {
    ...
} while ($expr);
  • do與{在同一行。
  • }與while在同一行.

for

1
2
3
for ($i = 0; $i < 10; $i++) {
    ...
}
  • {與for在同一行。
  • =、<或>前後要留一個空白。
  • ;之前不可以有空白,之後要留一個空白。
  • 第一個(之後 不可以有空白,最後一個)之前 不可以有空白。

foreach

1
2
3
foreach ($iterable as $key => $value) {
    ...
}
  • {與foreach在同一行。
  • =>前後要留一個空白。
  • 第一個(之後 不可以有空白,最後一個)之前 不可以有空白。

try catch

1
2
3
4
5
6
7
8
9
try {
    ...
} catch (FirstExceptionType $e) {
    ...
} catch (OtherExceptionType $e) {
    ...
} finally {
    ...
}
  • {與try, catch要在同一行,不用換行。
  • }與catch要在同一行,不用換行。
  • }與finally要在同一行,不用換行。

輔助工具


PSR-2只是個標準,但實務上還是要搭配好用的工具來完成。

phpcs

PHP Code Sniffer簡稱 phpcs,用來檢查你寫的PHP是否符合PSR-2,若完全符合則沒有任何結果,若有任何錯誤將顯示錯誤報告。這適合幫我們檢查Legacy PHP是否符合PSR-2。66將PHP Code Sniffer安裝到Homestead或Mac本機都可以,安裝方式都一樣,若要搭配PhpStorm就要一定要安裝在Mac本機。
安裝
1
$ composer global require 'squizlabs/php_codesniffer=*'
1
Changed current directory to /home/vagrant/.composer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing squizlabs/php_codesniffer (2.3.4)
    Downloading: 100%

Writing lock file
Generating autoload files
測試
1
$ phpcs --version
1
PHP_CodeSniffer version 2.3.4 (stable) by Squiz (http://www.squiz.net)
檢查PSR-2
1
$ phpcs --standard=PSR2 Laravel/app
  • Laravel為你的專案名稱,因為我們寫的code都在app目錄下,所以直接指定PHP Code Sniffer幫我們檢查app目錄下所有的.php檔案。
  • PHP Code Sniffer預設的coding style為PEAR,因為我們用的是PSR-2,所以要特別使用加上--standard=PSR2。
1
FILE: /home/vagrant/php-cs-test/app/User.php
----------------------------------------------------------------------
FOUND 3 ERRORS AFFECTING 3 LINES
----------------------------------------------------------------------
 13 | ERROR | [x] The first item in a multi-line implements list must
    |       |     be on the line following the implements keyword
 14 | ERROR | [x] Expected 4 spaces before interface name; 36 found
 15 | ERROR | [x] Expected 4 spaces before interface name; 36 found
----------------------------------------------------------------------
PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 255ms; Memory: 5.25Mb
  • 若沒有任何違反PSR-2之處,將無任何回應,否則將出現類似如上的報表,告訴你哪個檔案有問題,錯在哪些地方。其中FOUND為行數。

php-cs-fixer

PHP Coding Standards Fixer簡稱 php-cs-fixer。雖然PHP Code Sniffer可以幫我們找出哪些code不符合PSR-2,若只有幾個檔案,我們手動改就可以,若檔案太多,就得依賴 php-cs-fixer 幫我們修正。77將PHP Code Standrads Fixer安裝到Homestead或Mac本機都可以,安裝方式都一樣,若要搭配PhpStorm就要一定要安裝在Mac本機。
安裝
1
$ composer global require fabpot/php-cs-fixer
1
Changed current directory to /home/vagrant/.composer
Using version ^1.10 for fabpot/php-cs-fixer
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing sebastian/diff (1.3.0)
    Downloading: 100%

  - Installing symfony/stopwatch (v2.7.4)
    Downloading: 100%

  - Installing symfony/finder (v2.7.4)
    Downloading: 100%

  - Installing symfony/filesystem (v2.7.4)
    Downloading: 100%

  - Installing symfony/event-dispatcher (v2.7.4)
    Downloading: 100%

  - Installing fabpot/php-cs-fixer (v1.10)
    Downloading: 100%

symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
Writing lock file
Generating autoload files
測試
1
$ php-cs-fixer  --version
1
PHP CS Fixer version 1.10 by Fabien Potencier
修正PSR-2
1
$ php-cs-fixer fix Laravel/app/ --level=psr2 --verbose
  • Laravel為你的專案名稱,因為我們寫的code都在app目錄下,所以直接指定PHP-CS-Fixer幫我們檢查app目錄下所有的.php檔案。
  • --level=psr2指定使用PSR-2標準來修正我們的code。
  • --verbose表示PHP-CS-Fixer在執行時,會顯示出詳細的結果。
1
......F......F......
Legend: ?-unknown, I-invalid file syntax, file ignored, .-no changes, F-fixed, E-error
   1) Http/Controllers/Controller.php (single_line_after_imports)
   2) Http/routes.php (braces)
Fixed all files in 1.066 seconds, 6.500 MB memory used
  • Lengend表示在執行時,所執行過的動作。
  • 如上圖所示,表示修正過Controller.php與routes.php。

PhpStorm

PhpStorm對於PSR-2有以下支援 :
  1. 內建支援PSR-2。
  2. 可外掛PHP Code Sniffer,讓我在寫code的同時就可提醒我們是否符合PSR-2。
  3. 可外掛PHP Coding Standards Fixer,將code修正為PSR-2。
支援PSR-2
Preferences -> Editor -> Code Style -> PHP : Set from… -> Predefined Style : PSR1/PSR2
設定 PSR-2 所沒規定的 Code Style
如下圖所示,你可能會希望array的key與value能對齊,但這並不是PSR-2所規定的style,你可以自行設定。
phpcs
Preferences -> Languages & Frameworks -> PHP -> Code Sniffer
指定phpcs路徑 : /Users/oomusou/.composer/vendor/bin/phpcs。8 8其中/Users/oomusou/為你的home directory。
Preferences -> Editor -> Inspections
  • 將PHP Code Sniffer validation打勾。
  • 將Coding standard選PSR2。
php-cs-fixer
Preferences -> Tools -> External Tools
按+新增External Tools。
Name : php-cs-fixer
Description : Run php-cs on current file
Program : /Users/oomusou/.composer/vendor/bin/php-cs-fixer9 9其中/Users/oomusou/為你的home directory。
Parameters : --level=psr2 --verbose fix $FileDir$/$FileName$
Working Directory : $ProjectFileDir$
測試
測試內建的Reformat Code
⌃ + ⌥ + L : 重新整理Coding Style。
⌃ + ⌥ + ⇧+ L : 設定重新整理Coding Style方式。
  • Optimize imports : 沒用到的namespace,use會自動移除。
  • Rearrange code : 會自動依據Code Style的Arrangement規格將code重新排序。
測試PHP Code Sniffer
{與class同一行,並不符合PSR-2建議,PhpStorm馬上在該行下方顯示波浪紋,並提示phpcs: Openning brace of a class must be on the line after the definition。
測試PHP Coding Standards Fixer
Tools -> External Tools -> php-cs-fixer
PHP Code Standards會幫我們的code修正成PSR-2所要求,並同時在下方顯示報告。

Conclusion



  • Function/Method與Class的{是否要換行比較爭議,不過既然PSR-2已經規定,建議遵循PSR-2。
  • 經過實測結果,PHP Code Sniffer的要求會比PHP Coding Standards Fixer還嚴格,所以儘管跑過PHP Coding Standards Fixer之後,可能還需要手動修改一些地方才能通過PHP Code Sniffer。
  • PhpStorm內建的coding style已經支援PSR-2,與PHP Coding Standards Fixer的差異在於 : PhpStorm允許你微調自己的coding style,甚至可以加入PSR-2沒有規定的規則,而PHP Coding Standards Fixer則完全遵循PSR-2標準。
  • PhpStorm除了內建PSR-2外,還完美整合了PHP Code Sniffer與PHP Coding Standards Fixer,建議使用PhpStorm開發PHP。

from : http://oomusou.io/php/php-psr2/

wibiya widget