PHP ActiveRecord creates a child model through Has_Many association

I compile PHP Active Record and do associations. I have two related objects using "Has_Many" and "Belongs_to" (parent / child) and trying to create a child entry when creating a new parent record (in this case, a "skin" is created for my "unit").

class Unit extends ActiveRecord\Model { static $has_many = array( array('skins') ); } class Skin extends ActiveRecord\Model { static $belongs_to = array( array('unit') ); } 

I found both of these threads here: http://www.phpactiverecord.org/boards/4/topics/153 Activerecord-association: create a new object (find a class)

So now my code is as follows:

 $unit = new Unit(); $unit->name = 'somename'; $unit->description = 'somedescription'; $skinArray = array('name' => $unit->name.' Default Skin'); $unit->create_skins($skinArray); $unit->save(); 

The code above does not associate the new skin with a block in the database or in the code, although it / is / places the new skin record in the database (with the unit_NULL). Using build_skins does not put the Skin entry in the database.

I was hoping there was a way to add a β€œchild” to the parent model using the model itself, as some other ORM does. The only way to do this is to do it explicitly:

 $unit = new Unit(); $skin = new Skin(); $unit->name = 'somename'; $unit->description = 'somedescription'; $unit->save(); $skin->unit_id = $unit->id; $skin->name = $unit->name.' Default Skin'; $skin->save(); 

Perhaps this should be done in PHP ActiveRecord, and my expectations are wrong. But I was hoping to find a way to do this through objects that do not require saving the parent in the database with an explicit call. For example, in the PHP infrastructure "Recess" there would be a simple call on such a device: $ unit-> addSkin ($ skin);

+6
source share
4 answers

Are you setting up a database connection? Check out the gihub examples.

 <?php require_once __DIR__ . '/../../ActiveRecord.php'; class Book extends ActiveRecord\Model { // explicit table name since our table is not "books" static $table_name = 'simple_book'; // explicit pk since our pk is not "id" static $primary_key = 'book_id'; // explicit connection name since we always want production with this model static $connection = 'production'; // explicit database name will generate sql like so => db.table_name static $db = 'test'; } $connections = array( 'development' => 'mysql://invalid', 'production' => 'mysql://test: test@127.0.0.1 /test' ); // initialize ActiveRecord ActiveRecord\Config::initialize(function($cfg) use ($connections) { $cfg->set_model_directory('.'); $cfg->set_connections($connections); }); print_r(Book::first()->attributes()); ?> 

To do this, you need to run DB ActiveRecord\Config::initialize .

+1
source

Depending on your keys, you should not automatically increase (without a NULL value as the deafness value). I would look at the defvalt db key values ​​and adjust the auto increment or the default unit_id if it matches your schema. You said that the association works in two steps. Is unit_id saved correctly in two-step saving?

Documents are not very useful as they recommend preserving explicit ones that you are trying to avoid.

@outrightmental has something interesting about how to set unit-> id with hook, but if it doesn't need to be a callback before_create, you won’t want to insert records without associations. see this active record calls a callback .

 $after_create = array('validate association and assign unit_id if NULL'); 

or

 $before_create = array('explcitly assign unit_id'); 

? callbacks offer other suggestions

+1
source

I recommend implementing this method in afterSave() in the class of the parent model or in the user model method createChild($data) .

However (for example, Yii Framework CActiveRecord ) it looks something like the following:

 class Unit extends ActiveRecord\Model { ... public function afterSave() { if ($this->isNewRecord) { $firstSkin = new Skin(); $firstSkin->unitId = $this->id; $firstSkin->name = $this->name . ' Default Skin'; $firstSkin->save(); } } ... } 

If in fact the specific behavior is unique to the controller, then perhaps use the following alternative (data passed from the controller to create the child):

 class Unit extends ActiveRecord\Model { ... public function createSkin($data) { $firstSkin = new Skin(); $firstSkin->unitId = $this->id; $firstSkin->setAttributes($data); $firstSkin->save(); } ... } 

Hope this helps. I'm a fan of ActiveRecord for fast scaffolding, though beware not relying on it too magically for larger applications. Btw iz is very nice in Rails too;) where it came from.

+1
source

I am not very familiar with the active php record, but from my own experience (the same problem was when I used Doctrine and tried to add child views, and also was null before I saved the parent and child elements in the database). I think phpactiverecord does not have this functionality, so I propose a solution - manually create methods in models, for example Unit :: addSkin (Skin $ skin), which will have something like this inside:

 $skin->unit_id = $this->id; $skin->save(); 

In principle, this logic. But I can’t say that this approach is good or even neutral. That is how you can do such things in the Doctrine.

Also, have you tried Propel? If you like an active recording, I think you will find it quite interesting.

-2
source

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


All Articles