Skip to content

Instantly share code, notes, and snippets.

@n00ge
Last active December 24, 2015 12:09
Show Gist options
  • Save n00ge/6795818 to your computer and use it in GitHub Desktop.
Save n00ge/6795818 to your computer and use it in GitHub Desktop.
Laravel 4 dynamic relation definitions
/// SampleModel
class SampleModel extends BaseEloquent
{
protected $table = 'sample_models';
protected $associations = array(
'publishingRule' => array(
'belongsTo' => 'PublishingRule'
),
'previewImage' => array(
'belongsTo' => 'PreviewImage'
),
);
}
/// BaseEloquent
abstract class BaseEloquent extends Eloquent
{
public function __call($method, $args)
{
if($this->isAssociationMethod($method)) {
return $this->getAssociation($method);
}
return parent::__call($method, $args);
}
private function isAssociationMethod($method)
{
$hasAssociations = is_array($this->associations);
return $hasAssociations && array_key_exists($method, $this->associations);
}
private function getAssociation($association)
{
$associationDetails = $this->getAssociationDetails($association);
$associationType = $this->getAssociationType($associationDetails);
$typeDetails = $this->getAssociationTypeDetails(
$association,
$associationType,
$associationDetails[$associationType]
);
$association = $this->getAssociationWithDetails(
$associationType,
$typeDetails
);
return $association;
}
private function getAssociationDetails($association)
{
return $this->associations[$association];
}
private function getAssociationType($details)
{
$keys = array_keys($details);
return $keys[0];
}
private function getAssociationTypeDetails($association, $type, $details)
{
switch ($type) {
case 'belongsTo':
return $this->getBelongsToDetails($association, $details);
break;
case 'belongsToMany':
return $this->getBelongsToManyDetails($association, $details);
break;
case 'morphTo':
return $this->getMorphToDetails($association, $details);
break;
default:
return (array) $details;
break;
}
}
private function getBelongsToDetails($association, $details)
{
if(is_array($details) && count($details) > 2) return $details;
$foreignKey = snake_case($association) . '_id';
$related = $this->fetchKeyValue(0, (array) $details);
return array($related, $foreignKey, $association);
}
private function getBelongsToManyDetails($association, $details)
{
$details = (array) $details;
$related = $this->fetchKeyValue(0, $details);
$table = $this->fetchKeyValue(1, $details);
$foreignKey = $this->fetchKeyValue(2, $details);
$otherKey = $this->fetchKeyValue(3, $details);
return array(
$related,
$table,
$foreignKey,
$otherKey,
$association
);
}
private function getMorphToDetails($association, $details)
{
if(is_array($details) && count($details) >= 1) return $details;
$details = (array) $details;
$name = snake_case($association);
$type = $this->fetchKeyValue(1, $details);
$id = $this->fetchKeyValue(2, $details);
return array($name, $type, $id);
}
private function fetchKeyValue($key, $array)
{
return array_key_exists($key, $array) ? $array[$key] : null;
}
private function getAssociationWithDetails($type, $details)
{
return call_user_func_array(
array($this, $type),
$details
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment