LoginSignup
10
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-07-21

前提

  • 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;
    }

    
}

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

10
6
0

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
10
6