読者対象
CakePHP 3.x や Laravel 5.x に移行したいと思いつつもなかなか脱却できずに古代のクソフレームワークを用いたプロジェクトの保守を強要されている哀れな開発者
CakePHPマニュアルに書いてある方法
クッソ冗長な配列の定義を要求される。なんでここフレームワークで吸収してくれないの?
$options['joins'] = array(
array('table' => 'books_tags',
'alias' => 'BooksTag',
'type' => 'inner',
'conditions' => array(
'Book.id = BooksTag.book_id'
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'inner',
'conditions' => array(
'BooksTag.tag_id = Tag.id'
)
)
);
$options['conditions'] = array(
'Tag.tag' => 'Novel'
);
$books = $Book->find('all', $options);
何がモダンじゃこの野郎。
オレオレ実装
こんなの毎回書いてられるわけがないので,全てのモデルの基底クラスであるAppModel
に拡張メソッドを実装する。
<?php
App::uses('Model', 'Model');
App::uses('Inflector', 'Utility');
class AppModel extends Model
{
/**
* INNER JOIN 補助
*
* @author @mpyw
* @param string $targetModelName JOINで取ってくるモデル
* @param array $conditions JOIN条件
* @return array
*/
public function belongsInnerJoin($targetModelName)
{
$foreignKey = Inflector::underscore($targetModelName) . '_id';
return $this->join('INNER', $targetModelName, [
"$this->name.$foreignKey = $targetModelName.id",
]);
}
public function hasInnerJoin($targetModelName)
{
$foreignKey = Inflector::underscore($this->name) . '_id';
return $this->join('INNER', $targetModelName, [
"$this->name.id = $targetModelName.$foreignKey",
]);
}
public function innerJoin($targetModelName, array $conditions)
{
return $this->join('INNER', $targetModelName, $conditions);
}
/**
* LEFT JOIN 補助
*
* @author @mpyw
* @param string $targetModelName JOINで取ってくるモデル
* @param array $conditions JOIN条件
* @return array
*/
public function belongsLeftJoin($targetModelName)
{
$foreignKey = Inflector::underscore($targetModelName) . '_id';
return $this->join('LEFT', $targetModelName, [
"$this->name.$foreignKey = $targetModelName.id",
]);
}
public function hasLeftJoin($targetModelName)
{
$foreignKey = Inflector::underscore($this->name) . '_id';
return $this->join('LEFT', $targetModelName, [
"$this->name.id = $targetModelName.$foreignKey",
]);
}
public function leftJoin($targetModelName, array $conditions)
{
return $this->join('LEFT', $targetModelName, $conditions);
}
/**
* JOIN 補助
*
* @author @mpyw
* @param string $type JOINの種類
* @param string $targetModelName JOINで取ってくるモデル
* @param array $conditions JOIN条件
* @return array
*/
public function join($type, $targetModelName, array $conditions)
{
return [
'type' => $type,
'table' => Inflector::tableize($targetModelName),
'alias' => $targetModelName,
'conditions' => $conditions,
];
}
}
これを使うとさっきの例はこのように書ける。
$books = $Book->find('all', [
'joins' => [
$Book->hasInnerJoin('BooksTag'),
$Book->belongsInnerJoin('Tag'),
],
'conditions' => [
'Tag.tag' => 'Novel',
],
]);
これでちょっとでも保守が楽になりますように…