Adding temporary field in CRUD -> ADD


Time for another tip. This time i’ll explain how you can add a “temporary” field on the CRUD’s default “Add” form and after record is added use the value of this form to perform further action.

In my scenario I have the following models:





and finally Model_Syndicate_Manager:


This sets you up for a classical many-to-many relation. Normally if you build admin, you would add something like this:

$crud = $this->add('CRUD');

Now you have a simple CRUD, where you can add a Syndicate, then use expander to add a manager. In my business logic, however, syndicate without manager does not make any sense, and my client asked to make it possible to select first manager right away by having a dropdown at the Add form:

Here are the steps how you can implement this functionality:

Step1: create model before assigning it to CRUD

$crud = $this->add('CRUD');
$m = $this->add('Model_Syndicate');

// More code to tweak model here


Step2: Come up with a plan

To implement what we want, I’ll have to add a new field into the model, but then I need to remove the data and the field before it hits the database. I’ll have to use hooks beforeInsert and afterSave. I also will have to copy the field value into a model property so that’s it’s not lost.

Before I add the hooks, however, I want to make sure the field is added, so I’m creating a big IF block:

    $m->addHook('beforeInsert',function($m,$dsql){   // 1
        unset( $dsql->args['set']['manager_id']);    // 2
        $m->getElement('manager_id')->destroy();     // 3
        $m->first_manager= $m['manager_id'];         // 4

    $m->addHook('afterSave',function($m){    // 5
        if(!$m->first_manager)return;        // 6
        $sm = $m->ref('Syndicate_Manager');  // 7
        $sm['user_id'] = $m->first_manager;  // 8
        $sm->save();                         // 9

Next I describe what each line do:

  1. beforeInsert hook will be triggered after model decides which fields needs saving. I’m working with $m and $dsql
  2. I need to prevent $dsql from attempting to insert manager_id because that field does not actually existing in syndicate table.
  3. I will not need the field anymore, otherwise model will attempt to select data from this field.
  4. I copy value of manager_id which would be acquired from the form into a model property, where it would be safe until the next hook.
  5. afterSave will be executed after model is saved and re-loaded. At this moment $m['manager_id'] will be gone, but the property will remain.
  6. If save() was triggered by modify action the first_manager property will not be present, therefore no need for us to do anything.
  7. Traverse into Syndicate_Manager entity
  8. set user_id of our first manager to saved value
  9. save our many-to-many entity.

I hope you will find this useful. Remember that if you need to further modify your “ADD” form, often it’s better to disable default “add” action and add a custom action to the CRUD instead of trying to tweak the default functionality. Also you can look at extending CRUD and overriding its configureAdd method.


Once we also required this so we approached in different style

$m = $this->add('Model_Lead');

$crud = $this->add('CRUD');

    $assos_j = $m->join('lead_category_assos.lead_id');


and it was done.

Is it okey or can result in any breaks in any situation???


That’s a good solution too, however you simply adding record into database, if lead_category_assos has any hooks, you might be loosing them out, but I don’t think it’s a case with many-to-many relations, so great addition Gowrav.

1 Like