PHP
FuelPHP
誰得

FuelPHPのORMが使いづらいから少しだけ便利にするtrait

More than 1 year has passed since last update.

前提

  • Rails(ActiveRecord)に慣れている
  • なんらかの深遠なる理由でFuelPHPを使う事になった

という感じの人間にとっては頭の整理&少し便利になると思われるtips。

FuelPHPのORM

ActiveRecordと比較して書いてみる

User.where(name: 'hoge').first

User::find('first', ['where' => [['name', 'hoge']]]);

User.where(enabled: true).all

User::find('all', ['where' => [['enabled', 1]]]);

※ 正確には User.where(enabled: true).all.index_by(&:id) で得られるハッシュのような形になっている

User.where(enabled: true).limit(10).offset(30).all

User::find('all', ['where' => [['enabled', 1]], 'limit' => 10, 'offset' => 30]);

使いづらいと思った点

と言うわけで、ここを改善するメソッドを生やす。

<?php

trait OrmFindMethods
{
    public static function find_by($conditions)
    {
        $options = static::build_options($conditions);
        return static::find('first', $options);
    }

    public static function find_all($conditions = [], $limit = null, $offset = null)
    {
        $options = static::build_options($conditions, $limit, $offset);
        return static::find('all', $options);
    }

    protected static function build_options($conditions, $limit = null, $offset = null)
    {
        $where = [];
        foreach ($conditions as $key => $value) {
            if (is_array($value)) {
                $where[] = [$key, 'IN', $value];
            } else {
                $where[] = [$key, $value];
            }
        }

        $options = [
            'where' => $where,
            'from_cache' => false,
        ];

        if (isset($limit) && is_numeric($limit) && $limit > 0) {
            $options['limit'] = (int)$limit;
        }

        if (isset($offset) && is_numeric($offset) && $offset >= 0) {
            $options['offset'] = (int)$offset;
        }

        return $options;
    }
}

というtraitを用意して

<?php

class User extends \Orm\Model {
  use OrmFindMethods;

  
}

とかやってやる。

このtraitを使うと

User::find_by(['name' => 'hoge']);
User::find_all(['enabled' => 1])
User::find_all(['enabled' => 1], 10, 30);

という感じになる。

ついでに、Railsだと

User.where(id: [1, 2, 3]).all

と書いていた奴は

User::find_all('id' => [1, 2, 3])

と書けるようになる。

おまけ

trait OrmFindMethods
{
    

    public static function find_or_initialize_by($conditions)
    {
        $obj = static::find_by($conditions);
        if (!static::is_present($obj)) {
            return $obj;
        }

        $obj = new static();

        foreach ($conditions as $key => $value) {
            $obj->$key = $value;
        }

        return $obj;
    }

    public static function find_or_create_by($conditions, \Closure $block = null)
    {
        $obj = static::find_by($conditions);
        if (!static::is_present($obj)) {
            return $obj;
        }

        $obj = new static();

        foreach ($conditions as $key => $value) {
            $obj->$key = $value;
        }

        if (isset($block)) {
            $obj->tap($block);
        }

        $obj->save();

        return $obj;
    }

    public static function is_present($obj)
    {
        return isset($obj) && !empty($obj);
    }

    public function tap(\Closure $block)
    {
        $block($this);
        return $this;
    }

    
}

までお膳立てするとさらに便利。