1

I have a category table with id, name, id_parent structure. I'm using atk4 and I like to show dropdown with indented subcategories. So:

home
---cat1
---cat2
------subcat2.1
------subcat2.2
---cat3 etc

I did build something working however like to see how this can be improved. Currently I have recursive sql queries based on the hasMany(). It feels like this can be done without re-quering. And main worry is that I now have the styling defined in the model but I don't know how to move out. I tried to learn myself controller functionality but didn't manage so far. My code so far:

The model

<?php
class Model_Category extends Model_Table {
  public $table='category';
  function init() {
    parent::init();
    $this->addField('id_parent');
    $this->addField('name');
    $this->hasMany('Category','id_parent');
  }

  function tree($prefix='') {
    $r=array();
    $childs=$this->ref('Category');
    foreach($childs as $child) {
      $r[$childs->id]=$prefix.$childs['name'];
      $r=array_merge($r,$childs->tree($prefix.'---'));
    }
    return $r;
  }
}

On the page:

$f=$this->add('Form');
$m=$this->add('Model_Category');
$m->load(1); // start recursive from home category
$f->addField('dropdown','category')->setValueList($m->tree());
romaninsh
  • 10,606
  • 4
  • 50
  • 70
Bob Siefkes
  • 1,133
  • 9
  • 11
  • also here: http://phpmagister.com/dropdown-with-indented-categories-in-agile-toolkit-16025/ – romaninsh May 07 '12 at 07:32
  • 1
    Actually this solution looks pretty good. I was investigating trees and if you want to a single-query tree you can use this: http://stackoverflow.com/questions/169817/is-it-possible-to-query-a-tree-structure-table-in-mysql-in-a-single-query-to-an. You can group queries for each level, but that increases memory consumption. In either way it's also difficult to paginate. Keep your solution, it's good. – romaninsh May 07 '12 at 08:17
  • ok great, tx for taking the time to review. I indeed also tried the category with lpos/rpos columns. However then it needs recursion to rebuild the lpos/rpos columns. I have the code working for this rebuild with hasMany() recursion, however for my situation described here it is not having these fields. – Bob Siefkes May 08 '12 at 17:23
  • For any database-intensive processing stored procedures is the fastest way to go. You can also create stored procedure which would do indentations for you. However if your tree is dynamically updated, then updating l/r on every update is way too expensive. SQL is not very suitable for this task. – romaninsh May 08 '12 at 19:36

2 Answers2

0

Create a class extending Form_Field_Dropdown which would implement what you have already built. Once you're done, add it to the forked atk4-addons and I'll adjust it to be universally usable. What you have here is a good recipe but a universal solution would help the community.

romaninsh
  • 10,606
  • 4
  • 50
  • 70
  • I got it working: https://github.com/si4dev/atk4-addons/blob/master/misc/lib/Form/Field/drilldown.php and the usage: in model Category: $this->hasMany('Category','id_parent'); and on page: $f->addField('drilldown','category')->setModel('Model_Category'); – Bob Siefkes May 11 '12 at 14:21
  • My next challenge is now how to use this in a CRUD/GRID? – Bob Siefkes May 11 '12 at 14:24
  • Thanks for putting up the addon. I've modified it to work properly. I'll add another answer. – romaninsh May 13 '12 at 20:47
0

Contributed by Bob, I've now added a new add-on into atk4-addons:

https://github.com/atk4/atk4-addons/blob/master/misc/lib/Form/Field/drilldown.php

As described in the file, the model would need both the parent and child fields set:

$this->hasMany('Category','id_parent');
$this->hasOne('Category','id_parent')->display(array('form'=>'misc/drilldown'));

The test-case and a good example of hierarchical dropdown can be seen here:

Lots of credit to Bob for actually writing this add-on. Keep it up!

romaninsh
  • 10,606
  • 4
  • 50
  • 70