by shigemk2

当面は技術的なことしか書かない

第2回関西PHP勉強会(2011年11月24日)あらためてPHP5.3

とりあえずリアクションをとるのが大切です。

ブログに書くまでが勉強会

PHP5.2から大きな機能追加
PHP6からバックポートしているから

5.3
namespaceが使える
定数定義に、defineだけではなくconstも使えるようになった。

クロージャの書き方が出来るようになった。

namespace
名前空間のこと(すったもんだあって5.3から導入された)
クラス名や関数名をパッケージ化
名前の衝突を防ぐ

それ以前はグローバル空間しか使えなかった。
名前が競合した場合、「再定義」のエラーが出る

名前空間が使えるようになり同じ名前のものが複数使えるようになった。

使い方
namespace文で定義
バックスラッシュで階層化(C++だとダブルコロンで階層化される)
namespaceは定義したファイルだけに影響(エラーが出やすい部分なので注意)
クラス、インターフェイス、関数、定数(const)
defineは名前空間の影響を受けない

namespace OneByOne\lib;

interface IBar {
} // OneByOne\lib\IBar

namespaceの利用
同じ名前空間ならクラス名のみ
同じ名前空間ならクラス名のみ

別の名前空間なら名前空間を指定

use文で、名前空間の名前を指定出来る

use OneByOne\lib\Foo as libFoo;

で、

$foo1 = new \OneByOne\lib\Foo();
$foo2 = new libFoo();
$foo3 = new Foo();

上記は全て同じ意味である。

namespace OneByOne\lib;
$obj = new stdclass();

'OneByOne\lib\stdclass' not found

というエラーが出る

namespace OneByOne\lib;
$obj = new \stdclass();

これでグローバル空間のstdclassが使える。

当たり前ですが、組み込み関数は名前空間を指定しなくても
よびだせる。

クラス、インターフェイス
1. 指定された名前空間で探す

関数、定数
1. 指定された名前空間で探す
2. グローバル空間で探す

組み込み関数はグローバル空間内にある。

名前空間を指定したときに、
先頭にバックスラッシュをつける必要があるのか?

namespaceでの指定は絶対つけない(エラーになる)。
useのときはつけても良いし、つけなくても良い。

フルで呼び出すときは絶対つける。

変数に入れるときは、つけなくても良いし、つけても良い。

バックスラッシュをつけないといけないときはつけるが、
つける必要がないときは、つけない。
名前空間を指定するときは、同名のコンストラクタが動かないようになった。


名前空間の名前をどうつけるのか?
(名前空間そのものがバッティングすることがある)

規約PSR-0

\Doctrine\Common\IsolatedClassLoader
=> /path/to/project/lib/vender/Doctrine/Common

namespaceの特徴

  • 名前の特徴を防ぐ。
  • 5.3フレームワークでは必須なので、最低限使いかたを押さえておく。
  • autoload

別ファイルのクラスを使えるようになった。

クロージャ

  • 無名関数、ラムダ関数
  • オンザフライで関数定義
  • create_functionを書きやすく

create_functionとの比較

$func = create_function('$a, $b', 'return $a + $b;');
var_dump($func(1, 2));
$func = function($a, $b) {
  return $a + $b;
};
var_dump($func(1, 2));

useで値をカプセル化

__invoke()を使うことで、
変数にカッコをつけるだけでクラスを呼ぶ事が出来るようになる。

メソッド内でコード共有
クラス内でクロージャにまとめることで、
似たような処理をまとめる

class Foo() {
  public function something() {
    $func = function() {
      // 処理
    }
    $func();
    $func();
  } 
}

コールバック関数を簡潔に書ける
useでクロージャ内に値をカプセル化

LSB
Late Static Bindings
遅延静的束縛
参照するクラス定数、クラスメソッドを実行時に
決定する。

class Foo {
  const TABLE_NAME = 'Foo';

  public static function something() {
    return self::TABLE_NAME;
  }
}

class Bar extends Foo {
  const TABLE_NAME = 'BAR';
}

var_dump(Bar::Something()); // Bar ではなくFooが返る
class Foo {
  const TABLE_NAME = 'Foo';

  public static function something() {
    return static::TABLE_NAME; // selfをstaticにする。
  }
}

class Bar extends Foo {
  const TABLE_NAME = 'BAR';
}

var_dump(Bar::Something()); // Fooが返る

selfではなくstaticを使うのが重要
(それまではインスタンス化を使っていた)

  • 対象クラスのクラス定数、クラス変数、クラスメソッドを参照する
  • インスタンス化せずにクラスを利用する用途が広がる

PHPマニュアルを見よ!!


まとめ

  • PHP5.3がいよいよ本番になる。
  • 新機能を活用しよう
  • 5.3フレームワークを触って学ぶ(Silex)