I have an model with a relation, and I want to instantiate a new object of the relations type.
Example: A person has a company, and I have a person-obje
In PHPActiveRecord, you have access to the relations array. The relation should have a name an you NEED TO KNOW THE NAME OF THE RELATIONSHIP/ASSOCIATION YOU WANT. It doesn't need to be the classname, but the classname of the Model you're relating to should be explicitly indicated in the relation. Just a basic example without error checking or gritty relationship db details like linking table or foreign key column name:
class Person extends ActiveRecord\Model {
static $belongs_to = array(
array('company',
'class_name' => 'SomeCompanyClass')
);
//general function get a classname from a relationship
public static function getClassNameFromRelationship($relationshipName)
foreach(self::$belongs_to as $relationship){
//the first element in all relationships is it's name
if($relationship[0] == $relationshipName){
$className = null;
if(isset($relationship['class_name'])){
$className = $relationship['class_name'];
}else{
// if no classname specified explicitly,
// assume the clasename is the relationship name
// with first letter capitalized
$className = ucfirst($relationship);
}
return $className
}
}
return null;
}
}
To with this function, if you have a person object and want an object defined by the 'company' relationship use:
$className = $person::getClassNameFromRelationship('company');
$company = new $className();
I'm currently using below solution. It's an actual solution, instead of the$has_one[1]
hack I mentioned in the question. If there is a method in phpactiverecord I'm going to feel very silly exposing msyelf. But please, prove me silly so I don't need to use this solution :DI am silly. Below functionality is implemented by the create_associationname call, as answered by @Bogdan_D
\ActiveRecord\Model
class. In my case there is a class between our classes and that model that contains extra functionality like this, so I put it there.
These are the 2 functions:
public function findClassByAssociation($associationName)
has_many
,belongs_to
and has_one
) for the associationfindClassFromArray
if an association is found.$person->findClassByAssociation('company');
private function findClassFromArray($associationName,$associationArray)
Source:
/**
* Find the classname of an explicitly defined
* association (has_one, has_many, belongs_to).
* Unsure if this works for standard associations
* without specific mention of the class_name, but I suppose it doesn't!
* @todo Check if works without an explicitly set 'class_name', if not: is this even possible (namespacing?)
* @todo Support for 'through' associations.
* @param String $associationName the association you want to find the class for
* @return mixed String|false if an association is found, return the class name (with namespace!), else return false
* @see findClassFromArray
*/
public function findClassByAssociation($associationName){
//$class = $this::$has_one[1]['class_name'];
$that = get_called_class();
if(isset($that::$has_many)){
$cl = $this->findClassFromArray($associationName,$that::$has_many);
if($cl){return $cl;}
}
if(isset($that::$belongs_to)){
$cl = $this->findClassFromArray($associationName,$that::$belongs_to);
if($cl){return $cl;}
}
if(isset($that::$has_one)){
$cl = $this->findClassFromArray($associationName,$that::$has_one);
if($cl){return $cl;}
}
return false;
}
/**
* Find a class in a php-activerecord "association-array". It probably should have a specifically defined class name!
* @todo check if works without explicitly set 'class_name', and if not find it like standard
* @param String $associationName
* @param Array[] $associationArray phpactiverecord array with associations (like has_many)
* @return mixed String|false if an association is found, return the class name, else return false
* @see findClassFromArray
*/
private function findClassFromArray($associationName,$associationArray){
if(is_array($associationArray)){
foreach($associationArray as $association){
if($association['0'] === $associationName){
return $association['class_name'];
}
}
}
return false;
}
You can also use build_association()
in the relationship classes.
Simplest way to use it is through the Model's __call, i.e. if your relation is something like $person->company
, then you could instantiate the company with $company = $person->build_company()
Note that this will NOT also make the "connection" between your objects ($person->company
will not be set).
Alternatively, instead of build_company()
, you can use create_company()
, which will save a new record and link it to $person