LINQ(Language Integrated Query) for PHP
すみません。LINQって初めて見ました(多分)。C#方面の機能(?)みたいです。で、これをPHPで部分的に実装してみた方(ベルギーの方ですかね)がいらっしゃるようです。
Perhaps you have already heard of C# 3.5's "LINQ" component. LINQ, or Language Integrated Query, is a component inside the .NET framework which enables you to perform queries on a variety of data sources like arrays, XML, SQL server, ... These queries are defined using a syntax which is very similar to SQL.There is a problem with LINQ though... If you start using this, you don't want to access data sources differently anymore. Since I'm also a PHP developer, I thought of creating a similar concept for PHP.
LINQとは「リレーショナルデータベースや XML に対する操作をプログラミング言語に統合するもの」だそうです。
要は、DBやXMLなどのデータソースから同じ構文でを使ってデータを抽出するためのもの、という事でしょうかね。上のURLで「LINQの全体像」にある図が分かりやすいです。
と、ここまで前置き。
で、さっくり試してみました。まずは配列からデータを抽出する例。
<?php ini_set('include_path', ini_get('include_path') . ':./Classes/'); require_once 'PHPLinq/LinqToObjects.php'; // Create data source $names = array("John", "Peter", "Joe", "Patrick", "Donald", "Eric"); $result = from('$name')->in($names) ->where('$name => strlen($name) < 5') ->select('$name'); var_dump($result);
fromのところからがLINQの部分ですが、何となくSQLっぽい感じです。さしずめ、
SELECT $name FROM $names WHERE strlen($name) < 5;
といったところでしょうか。で、これを実行すると、
$ php phplinq01.php array(3) { [0]=> string(4) "John" [1]=> string(3) "Joe" [2]=> string(4) "Eric" } $
のように出力されます。分かりますかね?LINQの部分を素直に書けば、
<?php : $result = array(); foreach ($names as $name) { if (strlen($name) < 5) { $result[] = $name; } } :
な感じになるところです。
もう一つの例は、オブジェクト。
<?php ini_set('include_path', ini_get('include_path') . ':./Classes/'); require_once 'PHPLinq/LinqToObjects.php'; class Employee { public $Name; public $Email; public $Age; public function __construct($name, $email, $age) { $this->Name = $name; $this->Email = $email; $this->Age = $age; } } $employees = array( new Employee('Maarten', 'maarten@example.com', 24), new Employee('Paul', 'paul@example.com', 30), new Employee('Bill', 'bill.a@example.com', 29), new Employee('Bill', 'bill.g@example.com', 28), new Employee('Xavier', 'xavier@example.com', 40) ); $result = from('$employee')->in($employees) ->where('$employee => strlen($employee->Name) == 4') ->orderBy('$employee => $employee->Name') ->thenByDescending('$employee => $employee->Age') ->select('new { "EmailAddress" => $employee->Email, "Domain" => substr($employee->Email, strpos($employee->Email, "@") + 1) }'); var_dump($result);
今度はorderByとかthenByDescendingが出てきてます。SQLっぽく書くと
SELECT $employee FROM $employees WHERE $employee->name == 4 ORDER BY $employee->name, $employee->age DESC
の感じです。LINQの最後の「new」で、新しいオブジェクト(PHPの場合はstdClass)を生成するようです。つまり、
上の疑似SQLを実行して得られた結果から、新しいオブジェクトを作って配列でまとめて返す
といった動きになるようです。
実行結果は次の通りです。
$ php phplinq01_obj.php array(3) { [0]=> object(stdClass)#19 (2) { ["EmailAddress"]=> string(18) "bill.a@example.com" ["Domain"]=> string(11) "example.com" } [1]=> object(stdClass)#20 (2) { ["EmailAddress"]=> string(18) "bill.g@example.com" ["Domain"]=> string(11) "example.com" } [2]=> object(stdClass)#21 (2) { ["EmailAddress"]=> string(16) "paul@example.com" ["Domain"]=> string(11) "example.com" } } $
これも素直に書き直してみると。。。面倒なので割愛w
ちなみに、PHPLinqのソースを見てみると、from以外のinやwhereなどはメソッドになっていて、受け取った引数(文字列)から動的に関数を作成(create_function)して呼び出し(call_user_func)たりしているようです。
in()に指定する配列が巨大な場合とかは、パフォーマンス的に目も当てられない感じもしなくもないですが、これ便利だなぁ。