atk4

ATK4 CRUD: Lookup reference table for data insertion


I have elements of certain types. I have bins of certain types. An element only belongs in the bin of the same type.

One table in the DB contains the elements. Another table contains the bins. They each have a "type_id".

As far as the elements are concerned there are a few models, each of which sets ->addCondition('type', '=', 'x') in addition to the abstract base model.

Now when instantiating a CRUD of element of type X, when adding or editing items, how do I prevent bins with type Y from being shown in the dropdowns?

In essence I would like to impose an additional condition on hasOne() which restricts the foreign values shown.

class AbstractElement extends \atk4\data\Model {
  public $table = 'element';
  public $id_field = 'element_id';
  public $title_field = 'element_data';

  function init() {
    parent::init();

    $this->hasOne('Bin', [Bin::class, 'our_field'=>'element_bin_id', 'caption'=>'Bin', 'required'=>true])->addTitle(['caption'=>'Bin']);
    $this->addField('element_data', ['required'=>true]);
    $this->hasOne('Type', [Type::class, 'our_field'=>'type_id']);
  }
}
class Element extends AbstractElement {
  function init() {
    parent::init();
    $this->addCondition('type_id', '=', '1');
  }
}

class Bin extends \atk4\data\Model {
  public $table = 'bin';
  public $id_field = 'bin_id';
  public $title_field = 'bin_name';

  function init() {
    parent::init();

    $this->addField('bin_name', ['caption'=>'Name']);
    $this->hasOne('Type', [Type::class, 'our_field'=>'bin_type_id']);
  }
}

class Type extends \atk4\data\Model {
  public $table = 'type';
  public $id_field = 'type_id';
  public $title_field = 'type_name';

  function init() {
    parent::init();

    $this->addField('type_name');
  }
}

Solution

  • I think this should work.

    In Type class add:

    $this->hasMany('Bins', [Bin::class, 'their_field'=>'bin_type_id']);
    

    In AbstractElement class use callback to define Bin hasOne relation:

    $this->hasOne('Bin', [
        function($m){
            return $m->ref('Type')->ref('Bins');
        },
        'our_field' => 'element_bin_id',
        'caption' => 'Bin',
        'required' => true,
    ])->addTitle(['caption'=>'Bin']);