PHPの知見がたまったので共有します
順不同です。
インスタンスメソッド内でのクラス変数取得
<?php class Hoge { public static $ids = array(123, 234, 345); public function from_static() { return static::$ids; // staticでも } public function from_self() { return self::$ids; // selfでも } } $hoge = new Hoge(); print_r( $hoge->from_static() ); //=> array(123, 234, 345) print_r( $hoge->from_self() ); //=> array(123, 234, 345)
- static::$idsでもself::$idsでもどっちでも呼べる
デフォルト引数に定数値を使う
<?php const FOO = "fooooo"; function f($w = FOO) { return $w; } print_r( f() ); //=> fooooo
<?php class Hoge { const ID = 123; public function get_id($id = self::ID) { return $id; } } $hoge = new Hoge(); print_r( $hoge->get_id(999) ); //=> 999 print_r( $hoge->get_id() ); //=> 123
- デフォルト引数には定数値が使える
- 式は無理
デフォルト引数のnullはタイプヒンティングと併用できる
<?php function h(array $arr = null) { return $arr; } print_r( h() ); //=> null
親クラスのメソッドが子クラスのメソッドを呼んでくれる
<?php class Hoge { public function h() { return $this->f(); } // どっちが public function f() { return "Hoge::f()"; } } class Fuga extends Hoge { // 呼ばれるの public function f() { return "Fuga::f()"; } } $fuga = new Fuga(); print_r( $fuga->h() ); //=> Fuga::f()
- まあそりゃそうだろとは思ったのだが念のため
子クラスのstatic変数を親が呼ぶ(遅延静的束縛)
<?php class Hoge { public static function h() { // このクラスにない$fを返す return static::$f; } } class Fuga extends Hoge { protected static $f = "fooooo"; public static function f() { return static::h(); } } print_r( Fuga::f() ); //=> fooooo
抽象クラスのクラスメソッドは呼べる
<?php class Hoge { public static function h() { return "hooooooooooo!"; } } print_r( Hoge::h() ); //=> hooooooooooo!
リファレンス渡し
<?php class Hoge { private $h; // リファレンス public function __construct(&$h) { $this->h =& $h; } // リファレンス... public function &ref_h() { return $this->h; } // リファレンス...... public function fff() { $h =& $this->ref_h(); $h["str"] = "changed"; } } $abc = array("str" => "hoooo!"); $h = new Hoge($abc); $h->fff(); print_r($abc); //=> Array( [str] => changed )
- 渡したいときには、コールする方ではなくて、定義する方に&をつける
- 返したいときには、関数名に&をつける
- 左辺で受け取るときは=の右に&をつける
インスタンスメソッド内でのインスタンスメソッドの呼び出し(複数)
<?php class Hoge { public function h1() { echo "h1\n"; } public function h2() { $this->h1(); //=> h1 self::h1(); //=> h1 h1(); //=> Fatal error: Call to undefined function h1() } } $hoge = new Hoge(); $hoge->h2();
- $thisかselfを省略しては呼べない
- selfあれば$this要らないのかな?
ジェネレータ(v5.5〜)
<?php function hoge() { foreach (range(1, 5) as $i) { yield $i; } } foreach (hoge() as $i) { echo "$i\n"; } //=> 1 //=> 2 //=> 3 //=> 4 //=> 5
インスタンスからクラスメソッドを呼ぶ
<?php class Hoge { public static function h() { return "h"; } } $hoge = new Hoge(); print_r( $hoge::h() ); //=> h
文字列扱いされたときは__toStringが呼ばれる
<?php class Hoge { public function __toString() { return "hoge object"; } } $hoge = new Hoge(); print_r( "$hoge" ); //=> hoge object
メソッドシグネチャ
<?php class Hoge { public function h() { return "h"; } } class Fuga extends Hoge { public function h($w) { return parent::h().$w; } } $fuga = new Fuga(); print_r( $fuga->h("f") ); //=> hf // E_STRICT レベルのエラー // Strict standards: Declaration of Fuga::h() should be compatible with Hoge::www()
- 引数の数と型を合わせないといけないようだ
arrayとforeachの&
<?php $a = array(1, 2, 3); $b = array(4, 5, 6); foreach (array($a, &$b) as &$c) { foreach ($c as &$d) { $d *= 100; } } print_r($a); //=> Array ( [0] => 1 [1] => 2 [2] => 3 ) print_r($b); //=> Array ( [0] => 400 [1] => 500 [2] => 600 )
- arrayの中でも&をつけることができる
無名関数にselfを入れて返却(v5.4〜)
<?php class Hoge { protected static function h($proc) { return $proc(); } protected static function aaa() { return "aaaaaaa"; } } class Fuga extends Hoge { public static function f() { $proc = function(){ return self::aaa(); }; return static::h($proc); } } print_r( Fuga::f() ); //=> "aaaaaaa"
無名関数に$thisを入れて返却(v5.4〜)
<?php class Hoge { protected function h($proc) { return $proc(); } protected function aaa() { return "aaaaaaa"; } } class Fuga extends Hoge { public function f() { $proc = function(){ return $this->aaa(); }; return $this->h($proc); } } $fuga = new Fuga(); print_r( $fuga->f() ); //=> "aaaaaaa"
インスタンスが親のstaticメソッドを呼び出し
<?php class Hoge { public static function h($w) { print_r( $w ); } } class Fuga extends Hoge { public function f() { parent::h('fooooo'); } } $fuga = new Fuga(); $fuga->f(); // fooooo
- parent::を使う
インスタンスメソッド内のstaticは各インスタンス間で共通
<?php class Hoge { public function h() { static $h = 100; $h++; return $h; } } $hoge1 = new Hoge(); print_r( $hoge1->h() ); //=> 101 $hoge2 = new Hoge(); print_r( $hoge2->h() ); //=> 102
メソッド内のstaticに式は書けない
<?php class Hoge { public function h() { static $h = 100 + 100; return $h; } } $hoge = new Hoge(); print_r( $hoge->h() ); // Parse error: syntax error, unexpected '+', expecting ',' or ';' in /tmp/i_AoXbiC__ on line 4
関数名を引数にとるときにstaticメソッドを渡したい
<?php class Hoge { public static function h() { $aaa = array( array('id' => 45), array('id' => 83), array('id' => 28), ); usort($aaa, array('Hoge', 'mysort')); // usortの第二引数をarrayにする return $aaa; } public static function mysort($a, $b) { return ($a['id'] < $b['id']) ? -1 : 1; } } print_r( Hoge::h() );
- クラス名を文字列にしてarrayで渡す
__getはprivateメンバ変数関係なく常に呼ばれる
<?php class Hoge { public function __get($name) { return $name; } } $hoge = new Hoge(); print_r( $hoge->foooo ); //=> foooo
メンバ変数やstatic変数に定数を使う
<?php class Hoge { const HHH = "hhh"; private static $h = self::HHH; private $w = self::HHH; public static function h() { return static::$h; } public function w() { return $this->w; } } print_r( Hoge::h() ); //=> hhh $hoge = new Hoge(); print_r( $hoge->w() ); //=> hhh
arrayの返り値を直接取り出せない(〜v5.3)
<?php function h() { return array('str' => 'h'); } print_r( h()['str'] ); //=> PHP Parse error print_r( array('str' => 'h')['str'] ); //=> PHP Parse error
メソッドチェインはできる
<?php class Hoge { public function h() { return "hhh"; } } class Fuga { public function f() { $hoge = new Hoge(); return $hoge; } } $fuga = new Fuga(); print_r( $fuga->f()->h() ); //=> hhh
||や&&はbooleanを返す
<?php function h() { return null; } function f() { return "fff"; } $a = h() || f(); print_r( $a ); //=> 1
<?php function s() { return "sss"; } function d() { return "ddd"; } $b = s() && d(); print_r( $b ); //=> 1
- andやorでも同様
- これはつらい
rangeはマイナスにも動く
<?php foreach (range(10, 5) as $i) { echo "$i\n"; } //=> 10 //=> 9 //=> 8 //=> 7 //=> 6 //=> 5