Activerecord-association: create a new object (find a class)

I have a model with a relationship, and I want to instantiate a new relationship type object.

Example: a person has a company, and I have a person-object: now I want to create a company-object.

The companyobject class is defined in relation, so I don’t think I need to “know” this class, but should I ask the personal object to provide me with a new instance of the Company type? But I dont know how.

This - I think - is the same question as the New Model Object through association , but I use PHPActiveRecord , not ruby.

<h / "> The reason for this: I have an abstract superclass person , and two children have their own attitude to the type of corporate object. I need to be able to create an instance of the correct class in an abstract person.

The workaround is to get it directly from the static $has_one :

 $class = $this::$has_one[1]['class_name']; $company = new $class; 

a hard-coded number, of course, can be eliminated by looking for the association name in the array, but it's still pretty ugly.


If someone knows how this is implemented in Ruby, and how is the implementation of phpactiverecord different, can I get some ideas from there?


Some tests showed that although “searching for my class name in an array” looks strange, it has no effect on performance and is quite functional in use.
+2
source share
3 answers

You can also use build_association() in relationship classes.
The simplest way to use it is through Model __call, i.e. If your relationship is like $person->company , you can create an instance of the company with
$company = $person->build_company()

Please note that this will NOT make a “connection” between your objects $person->company ( $person->company will not be established).
Alternatively, instead of build_company() you can use create_company() , which will save the new entry and associate it with $ person

+4
source

I am currently using the solution below. This is the actual solution, instead of the $has_one[1] hack I mentioned in the question. If there is a method in phpactiverecord I will feel very silly exposing msyelf. But please prove me stupid, so I do not need to use this solution: D

I am stupid. The functionality below is implemented by calling create_associationname, as @Bogdan_D answers


Two features added. You should probably add them to the \ActiveRecord\Model class. In my case, there is a class between our classes and this model that contains additional functions like this, so I posted it there.

These are 2 functions:

  • public function findClassByAssociation($associationName)
    • Called with the name of the association you are looking for.
    • Checks three static vars ( has_many , belongs_to and has_one ) for association
    • calls findClassFromArray if an association is found.
    • from person / company: $person->findClassByAssociation('company');
  • private function findClassFromArray($associationName,$associationArray)
    • Just a working function that tries to match a name.

A 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; } 
0
source

In PHPActiveRecord, you have access to an array of relationships. The relationship must have a name that YOU NEED TO KNOW THE LINK / ASSOCIATION NAME WHAT YOU WANT . This should not be the name of the class, but the class name of the model you are talking about should be explicitly referenced. Just a basic example without checking errors or detailing db relationships such as table reference 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 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 the object defined by the company relationship to use:

 $className = $person::getClassNameFromRelationship('company'); $company = new $className(); 
0
source

Source: https://habr.com/ru/post/921903/


All Articles