Skip to content

Commit

Permalink
Added 3 new ways of using where/order_by with relations. Fixes fuel#3
Browse files Browse the repository at this point in the history
  • Loading branch information
Jelmer Schreuder committed Apr 25, 2011
1 parent 422cf5c commit fc0be87
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 22 deletions.
11 changes: 8 additions & 3 deletions classes/belongsto.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function __construct($from, $name, array $config)
$this->model_to = array_key_exists('model_to', $config) ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
$this->key_from = array_key_exists('key_from', $config) ? (array) $config['key_from'] : (array) \Inflector::foreign_key($this->model_to);
$this->key_to = array_key_exists('key_to', $config) ? (array) $config['key_to'] : $this->key_to;
$this->conditions = array_key_exists('conditions', $config) ? (array) $config['conditions'] : array();

$this->cascade_save = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_save;
$this->cascade_delete = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_delete;
Expand All @@ -49,8 +50,10 @@ public function get(Model $from)
return $query->get_one();
}

public function join($alias_from, $rel_name, $alias_to_nr)
public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
{
$conditions = array_merge($this->conditions, $conditions);

$alias_to = 't'.$alias_to_nr;
$model = array(
'model' => $this->model_to,
Expand All @@ -59,7 +62,9 @@ public function join($alias_from, $rel_name, $alias_to_nr)
'join_on' => array(),
'columns' => $this->select($alias_to),
'rel_name' => $rel_name,
'relation' => $this
'relation' => $this,
'where' => array_key_exists('where', $conditions) ? $conditions['where'] : array(),
'order_by' => array_key_exists('order_by', $conditions) ? $conditions['order_by'] : array(),
);

reset($this->key_to);
Expand All @@ -69,7 +74,7 @@ public function join($alias_from, $rel_name, $alias_to_nr)
next($this->key_to);
}

return array($model);
return array($rel_name => $model);
}

public function save($model_from, $model_to, $original_model_id, $parent_saved, $cascade)
Expand Down
11 changes: 8 additions & 3 deletions classes/hasmany.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function __construct($from, $name, array $config)
$this->model_to = array_key_exists('model_to', $config) ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
$this->key_from = array_key_exists('key_from', $config) ? (array) $config['key_from'] : $this->key_from;
$this->key_to = array_key_exists('key_to', $config) ? (array) $config['key_to'] : (array) \Inflector::foreign_key($this->model_from);
$this->conditions = array_key_exists('conditions', $config) ? (array) $config['conditions'] : array();

$this->cascade_save = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_save;
$this->cascade_delete = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_delete;
Expand All @@ -43,8 +44,10 @@ public function get(Model $from)
return $query->get();
}

public function join($alias_from, $rel_name, $alias_to_nr)
public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
{
$conditions = array_merge($this->conditions, $conditions);

$alias_to = 't'.$alias_to_nr;
$model = array(
'model' => $this->model_to,
Expand All @@ -53,7 +56,9 @@ public function join($alias_from, $rel_name, $alias_to_nr)
'join_on' => array(),
'columns' => $this->select($alias_to),
'rel_name' => $rel_name,
'relation' => $this
'relation' => $this,
'where' => array_key_exists('where', $conditions) ? $conditions['where'] : array(),
'order_by' => array_key_exists('order_by', $conditions) ? $conditions['order_by'] : array(),
);

reset($this->key_to);
Expand All @@ -63,7 +68,7 @@ public function join($alias_from, $rel_name, $alias_to_nr)
next($this->key_to);
}

return array($model);
return array($rel_name => $model);
}

public function save($model_from, $models_to, $original_model_ids, $parent_saved, $cascade)
Expand Down
11 changes: 8 additions & 3 deletions classes/hasone.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function __construct($from, $name, array $config)
$this->model_to = array_key_exists('model_to', $config) ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
$this->key_from = array_key_exists('key_from', $config) ? (array) $config['key_from'] : $this->key_from;
$this->key_to = array_key_exists('key_to', $config) ? (array) $config['key_to'] : (array) \Inflector::foreign_key($this->model_from);
$this->conditions = array_key_exists('conditions', $config) ? (array) $config['conditions'] : array();

$this->cascade_save = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_save;
$this->cascade_delete = array_key_exists('cascade_save', $config) ? $config['cascade_save'] : $this->cascade_delete;
Expand All @@ -45,8 +46,10 @@ public function get(Model $from)
return $query->get_one();
}

public function join($alias_from, $rel_name, $alias_to_nr)
public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
{
$conditions = array_merge($this->conditions, $conditions);

$alias_to = 't'.$alias_to_nr;
$model = array(
'model' => $this->model_to,
Expand All @@ -55,7 +58,9 @@ public function join($alias_from, $rel_name, $alias_to_nr)
'join_on' => array(),
'columns' => $this->select($alias_to),
'rel_name' => $rel_name,
'relation' => $this
'relation' => $this,
'where' => array_key_exists('where', $conditions) ? $conditions['where'] : array(),
'order_by' => array_key_exists('order_by', $conditions) ? $conditions['order_by'] : array(),
);

reset($this->key_to);
Expand All @@ -65,7 +70,7 @@ public function join($alias_from, $rel_name, $alias_to_nr)
next($this->key_to);
}

return array($model);
return array($rel_name => $model);
}

public function save($model_from, $model_to, $original_model_id, $parent_saved, $cascade)
Expand Down
15 changes: 10 additions & 5 deletions classes/manymany.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function __construct($from, $name, array $config)
$this->model_to = array_key_exists('model_to', $config) ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
$this->key_from = array_key_exists('key_from', $config) ? (array) $config['key_from'] : $this->key_from;
$this->key_to = array_key_exists('key_to', $config) ? (array) $config['key_to'] : $this->key_to;
$this->conditions = array_key_exists('conditions', $config) ? (array) $config['conditions'] : array();

if ( ! empty($config['table_through']))
{
Expand Down Expand Up @@ -117,12 +118,14 @@ public function select_through($table)
return $properties;
}

public function join($alias_from, $rel_name, $alias_to_nr)
public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
{
$conditions = array_merge($this->conditions, $conditions);

$alias_to = 't'.$alias_to_nr;

$models = array(
array(
$rel_name.'_through' => array(
'model' => null,
'table' => array($this->table_through, $alias_to.'_through'),
'join_type' => 'left',
Expand All @@ -131,14 +134,16 @@ public function join($alias_from, $rel_name, $alias_to_nr)
'rel_name' => $this->model_through,
'relation' => $this
),
array(
$rel_name => array(
'model' => $this->model_to,
'table' => array(call_user_func(array($this->model_to, 'table')), $alias_to),
'join_type' => 'left',
'join_on' => array(),
'columns' => $this->select($alias_to),
'rel_name' => $rel_name,
'relation' => $this
'relation' => $this,
'where' => array_key_exists('where', $conditions) ? $conditions['where'] : array(),
'order_by' => array_key_exists('order_by', $conditions) ? $conditions['order_by'] : array(),
)
);

Expand Down Expand Up @@ -284,7 +289,7 @@ public function delete($model_from, $models_to, $parent_deleted, $cascade)
$query->where($key, '=', $model_from->{current($this->key_from)});
next($this->key_from);
}
$query->delete();
$query->execute();

$cascade = is_null($cascade) ? $this->cascade_delete : (bool) $cascade;
if ($cascade and ! empty($model_to))
Expand Down
15 changes: 10 additions & 5 deletions classes/manythrough.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function __construct($from, $name, array $config)
$this->model_to = array_key_exists('model_to', $config) ? $config['model_to'] : \Inflector::get_namespace($from).'Model_'.\Inflector::classify($name);
$this->key_from = array_key_exists('key_from', $config) ? (array) $config['key_from'] : $this->key_from;
$this->key_to = array_key_exists('key_to', $config) ? (array) $config['key_to'] : $this->key_to;
$this->conditions = array_key_exists('conditions', $config) ? (array) $config['conditions'] : array();

if ( ! empty($config['model_through']))
{
Expand Down Expand Up @@ -112,15 +113,17 @@ public function select_through($table)
return $properties;
}

public function join($alias_from, $rel_name, $alias_to_nr)
public function join($alias_from, $rel_name, $alias_to_nr, $conditions = array())
{
$conditions = array_merge($this->conditions, $conditions);

$alias_to = 't'.$alias_to_nr;

$rel = call_user_func(array($this->model_from, 'relations'), $this->model_through);
$through_table = call_user_func(array($rel->model_to, 'table'));

$models = array(
array(
$rel_name.'_through' => array(
'model' => $rel->model_to,
'table' => array($through_table, $alias_to.'_through'),
'join_type' => 'left',
Expand All @@ -129,14 +132,16 @@ public function join($alias_from, $rel_name, $alias_to_nr)
'rel_name' => $this->model_through,
'relation' => $this
),
array(
$rel_name => array(
'model' => $this->model_to,
'table' => array(call_user_func(array($this->model_to, 'table')), $alias_to),
'join_type' => 'left',
'join_on' => array(),
'columns' => $this->select($alias_to),
'rel_name' => $rel_name,
'relation' => $this
'relation' => $this,
'where' => array_key_exists('where', $conditions) ? $conditions['where'] : array(),
'order_by' => array_key_exists('order_by', $conditions) ? $conditions['order_by'] : array(),
)
);

Expand Down Expand Up @@ -206,4 +211,4 @@ public function delete($model_from, $models_to, $parent_deleted, $cascade)
}
}

///* End of file manymany.php */
///* End of file manymany.php */
54 changes: 51 additions & 3 deletions classes/query.php
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public function order_by($property, $direction = 'ASC')
*
* @param string
*/
public function related($relation)
public function related($relation, $conditions = array())
{
if (is_array($relation))
{
Expand All @@ -346,7 +346,7 @@ public function related($relation)
throw new UndefinedRelation('Relation "'.$relation.'" was not found in the model.');
}

$this->relations[$relation] = $rel;
$this->relations[$relation] = array($rel, $conditions);

return $this;
}
Expand Down Expand Up @@ -449,7 +449,7 @@ public function build_query($query, $columns = array(), $type = 'select')
$models = array();
foreach ($this->relations as $name => $rel)
{
$models = array_merge($models, $rel->join($this->alias, $name, $i++));
$models = array_merge($models, $rel[0]->join($this->alias, $name, $i++, $rel[1]));
}

if ($this->use_subquery())
Expand Down Expand Up @@ -497,21 +497,69 @@ public function build_query($query, $columns = array(), $type = 'select')
}
}

// Add any additional order_by clauses from the relation
foreach ($models as $m)
{
if ( ! empty($m['order_by']))
{
foreach ((array) $m['order_by'] as $k_ob => $v_ob)
{
is_int($k_ob) ? $this->order_by($m['table'][1].'.'.$v_ob) : $this->order_by($m['table'][1].'.'.$k_ob, $v_ob);
}
}
}
// Get the order
if ( ! empty($this->order_by))
{
foreach ($this->order_by as $column => $direction)
{
// try to rewrite conditions on the relations to their table alias
$dotpos = strpos($column, '.');
$relation = substr($column, 0, $dotpos);
if ($dotpos > 0 and array_key_exists($relation, $models))
{
$column = $models[$relation]['table'][1].substr($column, $dotpos);
}

$query->order_by($column, $direction);
}
}

// Add any additional where clauses from the relation
foreach ($models as $m)
{
if ( ! empty($m['where']))
{
foreach ((array) $m['where'] as $k_w => $v_w)
{
if (is_int($k_w))
{
$v_w[0] = $m['table'][1].'.'.$v_w[0];
call_user_func_array(array($this, 'where'), $v_w);
}
else
{
$this->where($m['table'][1].'.'.$k_w, $v_w);
}
}
}
}

// put omitted where conditions back
if ( ! empty($this->where))
{
foreach ($this->where as $where)
{
list($method, $conditional) = $where;

// try to rewrite conditions on the relations to their table alias
$dotpos = strpos($conditional[0], '.');
$relation = substr($conditional[0], 0, $dotpos);
if ($dotpos > 0 and array_key_exists($relation, $models))
{
$conditional[0] = $models[$relation]['table'][1].substr($conditional[0], $dotpos);
}

call_user_func_array(array($query, $method), $conditional);
}
}
Expand Down
5 changes: 5 additions & 0 deletions classes/relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ abstract class Relation {
*/
protected $key_to = array();

/**
* @var array where & order_by conditions for loading this relation
*/
protected $conditions = array();

/**
* @var bool whether it's a single object or multiple
*/
Expand Down

0 comments on commit fc0be87

Please sign in to comment.