81
PHP5.4 おいしさつまみぐい @tanakahisateru

関西PHP勉強会 php5.4つまみぐい

Embed Size (px)

DESCRIPTION

2011/11/24の関西PHP勉強会で発表したPHP5.4ネタです。

Citation preview

Page 1: 関西PHP勉強会 php5.4つまみぐい

PHP5.4おいしさつまみぐい

@tanakahisateru

Page 2: 関西PHP勉強会 php5.4つまみぐい

ABOUT ME

•田中久輝 (たなかひさてる)

• @tanakahisateru

• https://github.com/tanakahisateru

• Firebug, FireCookie, jEdit

• ...and Pinoco

Page 3: 関西PHP勉強会 php5.4つまみぐい

今回はオチなしです。

Page 4: 関西PHP勉強会 php5.4つまみぐい

今日やること

• PHP5.4をすぐに使ってみる

• Array Short Syntax

• Built-in Server

• Trait

• Closure

•その他

Page 5: 関西PHP勉強会 php5.4つまみぐい

注: 全機能はやりません。僕がやりたいところだけします。

Page 7: 関西PHP勉強会 php5.4つまみぐい

PHP5.4をすぐに使ってみる

Page 8: 関西PHP勉強会 php5.4つまみぐい

祝 PHP 5.4 RC1 (2011/11/11)

• http://www.php.net/archive/2011.php#id2011-11-11-1

Page 10: 関西PHP勉強会 php5.4つまみぐい

要るもの

• Windows

• http://windows.php.net/qa/ にバイナリがあるのでいけると思う。自力ビルドは茨の道すぎるのでやめたほうがいいよ。

• Mac

• XCode + MacPorts or Homebrew

• Linux

• とくに何も

Page 11: 関西PHP勉強会 php5.4つまみぐい

% curl -o php-5.4.0RC1.tar.gz http://downloads.php.net/stas/php-5.4.0RC1.tar.gz% tar xzf php-5.4.0RC1.tar.gz% cd php-5.4.0RC1% ./configure \--prefix=/opt/local/php/5.4 \--bindir=/opt/local/bin \--with-config-file-path=/opt/local/php/5.4/etc \--with-config-file-scan-dir=/opt/local/php/5.4/var/db \--mandir=/opt/local/php/5.4/share/man \--infodir=/opt/local/php/5.4/share/info \--program-suffix=-5.4 \--with-apxs2=/opt/local/apache2/bin/apxs \(あとは https://gist.github.com/1344162 に書いてます)% make

なんか大量に進行状況出るのでお菓子でも食べて待ちましょう。

Page 12: 関西PHP勉強会 php5.4つまみぐい

できあがりインストール(make install)しなくても

sapi/cli/phpを使ってだいぶ遊べます。

うまくいかない人はconfigureオプションを減らしていくといいです。無指定だと拡張機能がないだけで動くPHPにはなります。

Page 13: 関西PHP勉強会 php5.4つまみぐい

% sapi/cli/php -vPHP 5.4.0RC1 (cli) (built: Nov 23 2011 23:08:40) Copyright (c) 1997-2011 The PHP GroupZend Engine v2.4.0, Copyright (c) 1998-2011 Zend Technologies

% sapi/cli/php -aInteractive shell

php >

バージョンを確認

さっそく遊んでみる

Page 14: 関西PHP勉強会 php5.4つまみぐい

php > echo “Hello World\n”;Hello World

php > print_r(array_map(function($x){ return $x * 2; }, range(0,9)));Array( [0] => 0 [1] => 2 [2] => 4 [3] => 6 [4] => 8 [5] => 10 [6] => 12 [7] => 14 [8] => 16 [9] => 18)

php > echo 0xff == 0b11111111, "\n";1

新機能: 2進数リテラル

Page 15: 関西PHP勉強会 php5.4つまみぐい

ARRAY SHORT SYNTAX

Page 16: 関西PHP勉強会 php5.4つまみぐい

array(1, 2, 3)

[1, 2, 3]

Page 17: 関西PHP勉強会 php5.4つまみぐい

array(‘a’=>1, ‘b’=>2)

[‘a’=>1, ‘b’=>2]

Page 19: 関西PHP勉強会 php5.4つまみぐい

var $belongsTo = array(! 'User');var $hasMany = array( 'Photo' => array( 'order' => 'number' ));

var $belongsTo = [! 'User']; var $hasMany = [ 'Photo' => [ 'order' => 'number' ]];

Page 20: 関西PHP勉強会 php5.4つまみぐい

$this->render('list', array( 'posts' => Post::find(array( 'limit' => Config::get('postsPerPage', array('context'=>'blog', 'default'=>10)), ))));

$this->render('list', [ 'posts' => Post::find([ 'limit' => Config::get('postsPerPage', ['context'=>'blog', 'default'=>10]), ])]);

どっちが読みやすい?

Page 21: 関西PHP勉強会 php5.4つまみぐい

「どっちも読みにくいわ」

「すんません」

Page 22: 関西PHP勉強会 php5.4つまみぐい

$this->render('list', array( 'posts' => Post::find(array( 'limit' => Config::get('postsPerPage', array('context'=>'blog', 'default'=>10)), ))));

$this->render('list', [ 'posts' => Post::find([ 'limit' => Config::get('postsPerPage', ['context'=>'blog', 'default'=>10]), ])]);

気をとり直して

Page 23: 関西PHP勉強会 php5.4つまみぐい

$this->render('list', array( 'posts' => Post::find(array( 'limit' => Config::get('postsPerPage', array('context'=>'blog', 'default'=>10)), ))));

$this->render('list', [ 'posts' => Post::find([ 'limit' => Config::get('postsPerPage', ['context'=>'blog', 'default'=>10]), ])]);

関数のネストではなくArrayを引数にしてるって見た目でわかる。

Page 24: 関西PHP勉強会 php5.4つまみぐい

$this->render('list', array( 'posts' => Post::find(array( 'limit' => Config::get('postsPerPage', array('context'=>'blog', 'default'=>10)), ))));

$this->render('list', [ 'posts' => Post::find([ 'limit' => Config::get('postsPerPage', ['context'=>'blog', 'default'=>10]), ])]);

[ ... ] という囲みのまとまりの良さ

Page 25: 関西PHP勉強会 php5.4つまみぐい

ARRAY SHORT SYNTAX

•右手だけの2キーストローク→楽チン

•関数の引数の括弧とは明らかに違うように見える。

• PHP以外の言語の人にもわかってもらえる。

•最後の引数にArrayで動作オプションを渡す関数がもっと使いやすくなる。

Page 26: 関西PHP勉強会 php5.4つまみぐい

ARRAY SHORT SYNTAX

•「PHPのarrayはダサいから設定ファイルみんなYAMLにしようぜ」なんて言わないでね。

•とPHPの中の人が言ってるような気がします。

Page 27: 関西PHP勉強会 php5.4つまみぐい

BUILT-IN SERVER

Page 28: 関西PHP勉強会 php5.4つまみぐい

コマンドラインのPHPがローカルテスト用のWebサーバになる

Page 29: 関西PHP勉強会 php5.4つまみぐい

% sapi/cli/php -S localhost:8080

デモ

Page 30: 関西PHP勉強会 php5.4つまみぐい

どこがおいしいのか

• JavascriptやFlashには、file:// では期待どおり動かないAPIがある。→ フロントの人がPHP5.4でダミーサーバを書ける。

•手元のApacheにいちいちバーチャルホストを立てるのが面倒なぐらいのスポット仕事に。

•ダウンロードしたPHPのアプリケーションをすぐその場で動かせ、要らなければ捨てるだけ。インストールの残骸がシステムに残る心配がない。

Page 31: 関西PHP勉強会 php5.4つまみぐい

いまどき .htaccess に mod_rewrite 書けないと

Page 32: 関西PHP勉強会 php5.4つまみぐい

% sapi/cli/php -S localhost:8080 builtin-server.php

PHPのプログラムコードでそれ再現できるよ

Page 33: 関西PHP勉強会 php5.4つまみぐい

ビルトインサーバ用スクリプトlist($path, $param) = array_merge( preg_split('/\?/', $_SERVER['REQUEST_URI'], 2), ['', '']);if($path != '/' && (file_exists('app/webroot' . $path))){ header(sprintf('Location: http://%s/app/webroot%s', $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'])); exit;}else if($path != '/' && (file_exists('./' . $path))){ return false;}else{ $_SERVER['PATH_INFO'] = $path; require 'app/webroot/index.php';}

Page 34: 関西PHP勉強会 php5.4つまみぐい

% ~/php54/php-5.4.0RC1/sapi/cli/php -S localhost:8080 builtin-server.php

Page 35: 関西PHP勉強会 php5.4つまみぐい
Page 36: 関西PHP勉強会 php5.4つまみぐい

PHP 5.4.0RC1 Development Server started at Thu Nov 24 02:11:37 2011Listening on localhost:8080Document root is /Users/tanakahisateru/Sites/cakephp2Press Ctrl-C to quit.[Thu Nov 24 02:11:42 2011] ::1:63556 [200]: /app/webroot/css/cake.generic.css[Thu Nov 24 02:11:42 2011] ::1:63557 [200]: /app/webroot/img/cake.power.gif[Thu Nov 24 02:11:42 2011] ::1:63558 [200]: /app/webroot/img/cake.icon.png[Thu Nov 24 02:11:42 2011] ::1:63564 [200]: /app/webroot/favicon.ico

Page 37: 関西PHP勉強会 php5.4つまみぐい

% ~/php54/php-5.4.0RC1/ sapi/cli/php -c ~/php54/php-5.4.0RC1/ -S localhost:8080 builtin-server.php

[Pdo_mysql]pdo_mysql.default_socket=/opt/local/var/run/mysql5/mysqld.sock

~/php54/php-5.4.0RC1/php.ini

厳密には MacPorts の MySQL との相性が問題で実行時に php.ini を指定しました。

でMySQLがやっと動いたんだけどね。

Page 38: 関西PHP勉強会 php5.4つまみぐい

BUILT-IN SERVER

•ビルトインサーバ用のスクリプトを書ければ、URLリライトするフレームワークでもOK。

• Apacheの設定なしでもブラウザで動かして試せる。

•手持ちの開発環境がPHP5.3以下準拠でも、ビルトインサーバを意識したプロジェクトなら、Apacheのmod_phpを書き換えずにPHP5.4を試せる。

Page 39: 関西PHP勉強会 php5.4つまみぐい

TRAIT

Page 40: 関西PHP勉強会 php5.4つまみぐい

おまたせしました注目度NO.1の新機能

Page 41: 関西PHP勉強会 php5.4つまみぐい

TRAIT

•親クラス以外からもメソッド実装を持ってこれる。

• Rubyでいうとmixinに相当する。

•ただしPHPのトレイトは、型階層(instanceofの結果)には影響しない。

•型の追加はインターフェースに任せる。実装の追加はトレイトが担う。

Page 42: 関西PHP勉強会 php5.4つまみぐい

つまりどういうこと?

Page 43: 関西PHP勉強会 php5.4つまみぐい

コード分割その1

INCLUDE / REQUIRE

•外部ファイルに関数やクラスを分けて書ける。

• HTMLを分けて書き、外部ファイルで出力処理。

•ただし使える場所は「クラスの外」と「関数/メソッドの中」のみ。

Page 44: 関西PHP勉強会 php5.4つまみぐい

コード分割その2

継承• ある程度基本的な機能を持ったクラスをもとにして、足りない部分だけ実装する。

• 実用性を意識するとすぐに、オブジェクト指向の「~は~の一種」モデルが実際のありさまに準拠せず、システム主導になってしまう。

• class AppModel extends Modelclass GuestUser extends AppModelclass AdminUser extends AppModelって、これ本当は抽象的なUserに汎化されるべきだよね。

Page 45: 関西PHP勉強会 php5.4つまみぐい

class AppModel extends Model {}

class GuestUser extends AppModel { public function getDisplayLabel() { ...; }}

class AdminUser extends AppModel { public function getDisplayLabel() { ...; } public function getAdminRioleType() { ...; }}

コピペ実装だめーっ!!

Page 46: 関西PHP勉強会 php5.4つまみぐい

class AppModel extends Model { public function getDisplayLabel() { ...; }}

class GuestUser extends AppModel {}

class AdminUser extends AppModel { public function getAdminRioleType() { ...; }}

これでいいのかな

Page 47: 関西PHP勉強会 php5.4つまみぐい

class AppModel extends Model { public function getDisplayLabel() { return $this->username . “さん”; }}

class GuestUser extends AppModel {}

class AdminUser extends AppModel { public function getAdminRoleType() { ...; }}

class Comment extends AppModel { // username フィールド持ってないよ。}

←だめじゃん

Page 48: 関西PHP勉強会 php5.4つまみぐい

public function getDisplayLabel() { return $this->username . “さん”; }

class GuestUser extends AppModel { require ‘UserModel.inc’;}

class AdminUser extends AppModel { require ‘UserModel.inc’; public function getAdminRoleType() { ...; }}

class Comment extends AppModel {}

UserModel.inc

こういうことがしたいんだけどなぁ...

require書ける場所 =「クラスの外」orz

Page 49: 関西PHP勉強会 php5.4つまみぐい

trait UserModel { public function getDisplayLabel() { return $this->username . “さん”; }}

class GuestUser extends AppModel { use UserModel;}

class AdminUser extends AppModel { use UserModel; public function getAdminRoleType() { ...; }}

class Comment extends AppModel {}

できるようになりました!

Page 50: 関西PHP勉強会 php5.4つまみぐい

トレイトの継承や名前の変更なんかもできるんだけど今日は説明省略。

Page 51: 関西PHP勉強会 php5.4つまみぐい

trait PersistentModel { public function save() { }}

abstract class User { public function getDisplayLabel() { return $this->username . “さん”; }}

class GuestUser extends User inplements Persistence { use PersistentModel;}

class AdminUser extends User inplements Persistence { use PersistentModel; public function getAdminRoleType() { ...; }}

本来はオブジェクト指向ってこうだよね

主=意味従=機能

Page 52: 関西PHP勉強会 php5.4つまみぐい

PHP5.4世代になって、そんなO/Rマッパーが登場したらいいなあ

Page 53: 関西PHP勉強会 php5.4つまみぐい

既存のフレームワークでもたぶん有効。少なくとも、似たモデル間、似たコントローラ間でコピペプログラミングせざるをえない状況を

だいぶ減らしてくれるはず。

Page 54: 関西PHP勉強会 php5.4つまみぐい

CLOSURE

Page 55: 関西PHP勉強会 php5.4つまみぐい

密かに超強化されてます

Page 56: 関西PHP勉強会 php5.4つまみぐい

CALLABLEの整合性

Page 57: 関西PHP勉強会 php5.4つまみぐい

これまで

php > $fun = 'intval';php > echo call_user_func($fun, "0001abc"), "\n";1php > echo is_callable($fun), "\n";1php > echo is_string($fun), "\n";1

php > echo $fun("0001abc"), "\n";1

call_user_funcしなくても関数を名前で呼べた

Page 58: 関西PHP勉強会 php5.4つまみぐい

これからはさらに

php > $obj = new Exception('hoge');php > $msg = [$obj, 'getMessage'];php > echo call_user_func($msg), "\n";hogephp > echo is_callable($msg), "\n";1php > echo is_array($msg), "\n";1

php > echo $msg(), "\n";hoge

call_user_funcしなくてもメソッドをarrayで呼べる

Page 59: 関西PHP勉強会 php5.4つまみぐい

stringもarrayも見た目はクロージャとそっくり。↓

is_callableでありさえすれば同じように扱える。クロージャがなければ関数名やArrayでも代替可能。

php > echo $closure(), "\n"; // クロージャの使い方

Page 60: 関西PHP勉強会 php5.4つまみぐい

$THIS IN CLOSURE

Page 61: 関西PHP勉強会 php5.4つまみぐい

PHP5.3ではこれエラー<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; return function() use(&$c) { return $this->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();$c2 = $fact->createCounter();echo "c1:", $c1(), "\n"; echo "c1:", $c1(), "\n";echo "c2:", $c2(), "\n"; echo "c2:", $c2(), "\n";echo "c2:", $c2(), "\n"; echo "c1:", $c1(), "\n";

Page 62: 関西PHP勉強会 php5.4つまみぐい

PHP5.3での回避策<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; $self = $this; return function() use($self, &$c) { return $self->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();$c2 = $fact->createCounter();echo "c1:", $c1(), "\n"; echo "c1:", $c1(), "\n";echo "c2:", $c2(), "\n"; echo "c2:", $c2(), "\n";echo "c2:", $c2(), "\n"; echo "c1:", $c1(), "\n";

Page 63: 関西PHP勉強会 php5.4つまみぐい

明示的なself → Pythonかと

Page 64: 関西PHP勉強会 php5.4つまみぐい

だがPHP5.4ではこれOK!<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; return function() use(&$c) { return $this->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();$c2 = $fact->createCounter();echo "c1:", $c1(), "\n"; echo "c1:", $c1(), "\n";echo "c2:", $c2(), "\n"; echo "c2:", $c2(), "\n";echo "c2:", $c2(), "\n"; echo "c1:", $c1(), "\n";

Page 65: 関西PHP勉強会 php5.4つまみぐい

<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; return function() use(&$c) { return $this->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();$c2 = $fact->createCounter();echo "c1:", $c1(), "\n"; echo "c1:", $c1(), "\n";echo "c2:", $c2(), "\n"; echo "c2:", $c2(), "\n";echo "c2:", $c2(), "\n"; echo "c1:", $c1(), "\n";

c1:100 <-- init=100 + c=0c1:101 <-- init=100 + c=1c2:100 <-- init=100 + c=0c2:101 <-- init=100 + c=1c2:102 <-- init=100 + c=2c1:102 <-- init=100 + c=2

Page 66: 関西PHP勉強会 php5.4つまみぐい

もっとJavascriptみたいなことができる

Page 67: 関西PHP勉強会 php5.4つまみぐい

クロージャの$THISすり替え<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; return function() use(&$c) { return $this->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();echo "c1:", $c1(), "\n";echo "c1:", $c1(), "\n";$c1 = $c1->bindTo(new CounterFactory(1000));echo "c1:", $c1(), "\n";

Page 68: 関西PHP勉強会 php5.4つまみぐい

<?phpclass CounterFactory { function __construct($init) { $this->init = $init; } function createCounter() { $c = 0; return function() use(&$c) { return $this->init + ($c++); }; }}$fact = new CounterFactory(100);$c1 = $fact->createCounter();echo "c1:", $c1(), "\n";echo "c1:", $c1(), "\n";$c1 = $c1->bindTo(new CounterFactory(1000));echo "c1:", $c1(), "\n";

c1:100 <-- init=100 + c=0c1:101 <-- init=100 + c=1c1:1002 <-- init=1000 + c=2

Page 69: 関西PHP勉強会 php5.4つまみぐい

CLOSURE

• PHP5.4のクロージャはもうcreate_functionの代わりではない。

• Javascriptのようにthisが文脈によって変化しうる。

• クロージャの$thisは生成されたとき$thisだったものを引き継ぐ。 これはあくまで自然な挙動をデフォルトにしているにすぎない。

• それでも、束縛しているローカル変数は再定義できない。→なのでPHP5.3の$selfによる回避策はbindToに対応できない。PHP5.4

ではむしろ、クロージャの中で積極的に$thisを使っておくべき。

Page 70: 関西PHP勉強会 php5.4つまみぐい

ぶっちゃけ<?phpclass Hoge { function __construct($init) { $this->init = $init; } function x($n) { $tmp = []; for($i=0; $i<$n; $i++) { $tmp[] = $this->init; } return $tmp; }}

print_r((new Hoge(100))->x(3));

<?phpclass Hoge { function __construct($init) { $this->init = $init; } function x($n) { return array_map( function() { return $this->init; }, range(0,$n-1) ); }}

print_r((new Hoge(100))->x(3));

どっちの方法でも、やりたいことの本質にまったく同じコードを書けるのが嬉しい。

Page 71: 関西PHP勉強会 php5.4つまみぐい

その他

Page 72: 関西PHP勉強会 php5.4つまみぐい

より言語っぽくなった

• newしたインスタンスのメソッドを呼べる

•関数が返したarrayの要素を取り出せる

Page 73: 関西PHP勉強会 php5.4つまみぐい

当たり前なんじゃ?

Page 74: 関西PHP勉強会 php5.4つまみぐい

echo (new Exception("hoge"))->getMessage(), "\n";

PHP5.3以下でエラーPHP5.4ではOK

Page 75: 関西PHP勉強会 php5.4つまみぐい

echo range(0, 9)[5], “\n”;

PHP5.3以下でエラーPHP5.4ではOK

Page 76: 関西PHP勉強会 php5.4つまみぐい

php > echo (array(1, 2, 3))[0], "\n";Parse error: syntax error, unexpected '[', expecting ',' or ';' in php shell code on line 1

php > echo (function($x){ return $x * 2; })(10), "\n";Parse error: syntax error, unexpected '(', expecting ',' or ';' in php shell code on line 1

PHP5.4.0RC1でもやっぱりエラー

Page 77: 関西PHP勉強会 php5.4つまみぐい

期待どおりじゃない点はいつもご期待通りだぜ。

Page 78: 関西PHP勉強会 php5.4つまみぐい

<?= が常にオンいえね、だいぶ古い話なんですけど

「<?= これ使っていいのは小学生までだよね」

的な、はてブコメント食らったことがありまして。 敵は討ったぞざまあみろ。

Page 79: 関西PHP勉強会 php5.4つまみぐい

PHP5.4はゆるやかな変更

• PHP5.3の目玉新機能は、使うか使わないかで別世界になってしまう。5.2以前に戻る方法がない。

•名前空間

• Phar

• PHP5.4の新機能は、便利なところからちょっとづつ使えばいいものばかり。

Page 80: 関西PHP勉強会 php5.4つまみぐい

以上、自分がやりたいことだけ

やりました。

Page 81: 関西PHP勉強会 php5.4つまみぐい

皆さんも既存の環境は変えず、PHP5.4のコマンドラインとビルトインサーバで

「自分のやりたいことだけ」をつまみ食いしてください。