LoginSignup
11

More than 5 years have passed since last update.

PHPでLINQ

Last updated at Posted at 2014-06-20

Ginq / PHPLinq

PHPでLINQを再現するライブラリ、PHPLinqを試してみます。

そもそもLINQって何よ。
http://ja.wikipedia.org/wiki/%E7%B5%B1%E5%90%88%E8%A8%80%E8%AA%9E%E3%82%AF%E3%82%A8%E3%83%AA

データ集合に対して標準化された方法でデータを問い合わせることを可能にする

.NET Framework に汎用クエリ機能が追加され、リレーショナル データや XML データだけでなく、あらゆる情報ソースにクエリ機能が適用されます。

何のこっちゃ。
平たく言うと、配列やらオブジェクトやらその他諸々の集合に対してSQL(っぽいもの)でSELECTできちまうぜ、という代物らしい。
さっそく試してみましょう。

<?php
    // Linq include_path設定が必要
    set_include_path(get_include_path() . PATH_SEPARATOR . 'path/to/phplinq/Classes');
    require_once 'path/to/phplinq/Classes/PHPLinq/LinqToObjects.php';

    $sample1 = ['John', 'Peter', 'Joe', 'Patrick', 'Donald', 'Eric', 'Joe'];

    // SELECT name FROM sample1 WHERE LENGTH(name) < 5
    $result = from('$name')->in($sample1)
        ->where('strlen($name) < 5')
        ->select('$name');

    // SELECT DISTINCT name FROM sample1 ORDER BY id DESC
    $result = from('$name')->in($sample1)->reverse()->distinct('$name')->select();

    // Employee サンプルのコピペ
    class Employee {
        public $Id, $DepartmentId, $ManagerId, $Name, $Email, $Age;
        public function __construct($id = 0, $departmentId = 0, $managerId = 0, $name = '', $email = '', $age = '') {
            $this->Id               = $id;
            $this->DepartmentId     = $departmentId;
            $this->ManagerId        = $managerId;
            $this->Name             = $name;
            $this->Email            = $email;
            $this->Age              = $age;
        }
    }
    $employees = [
        new Employee(1, 1, 5, 'Maarten', 'maarten@example.com', 24),
        new Employee(2, 1, 5, 'Paul', 'paul@example.com', 30),
        new Employee(3, 2, 5, 'Bill', 'bill.a@example.com', 29),
        new Employee(4, 3, 5, 'Bill', 'bill.g@example.com', 28),
        new Employee(5, 2, 0, 'Xavier', 'xavier@example.com', 40)
    ];

    // SELECT Email, SUBSTR(Email, INSTR(Email,'@')+1) FROM employees WHERE LENGTH(Name) = 4 ORDER BY Age DESC LIMIT 2 OFFSET 1
    $result = from('$employee')->in($employees)
        ->where('$employee => strlen($employee->Name) === 4')
        ->orderByDescending('$employee->Age')
        ->skip(1)->take(2)
        ->select('new {
            "EmailAddress" => $employee->Email,
            "Domain" => substr($employee->Email, strpos($employee->Email, "@") + 1)
        }');

コメントで書かれているSQLとほぼ同じ処理を、メソッドチェーンでSQLっぽく書くことができるようになりました。
SQLそのものではありませんが、同じようなかんじで使えます。
いちいちarray_filter()してforeachで抽出して、といった面倒な処理を書かなくて済みます。

一見便利ですが、欠点としては、対応しているのが配列とZend_Dbだけという点です。
ソースにはAdapter/MysqliやAdapter/Pdo/Mysqlなんてものがあるので、PDOを突っ込めるのかと思いきや、何故かZend_Db_Adapterを要求されます。
またArrayObjectなんてほぼ配列なのですが、これも対応していません。
サンプルではRSSのXMLを処理している例も載っているのですが、単にSimpleXMLElement::xpath()で配列にしてから突っ込んでるだけでした。
対応がもっと広がればどんどん便利になるかと思われましたが、2009年あたりで開発が停止しています。
残念。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11