0
votes

How to create select/option html tag from find('threaded') data in CakePHP? Function find() return results like this:

Array

( [0] => Array ( [Forum] => Array ( [id] => 1 [name] => Forum

            )

        [children] => Array
            (
                [0] => Array
                    (
                        [Forum] => Array
                            (
                                [id] => 3
                                [name] => Programowanie
                                [parent_id] => 1
                            )
                    )

                [1] => Array
                    (
                        [Thread] => Array
                            (
                                [id] => 11
                                [name] => Nowe forumowisko
                                [parent_id] => 1
                            )
                    )
            )
    )

[1] => Array
    (
        [Forum] => Array
            (
                [id] => 4
                [name] => Nauka
                [parent_id] => 0
            )

        [children] => Array
            (
            )
     )
)

How?

4

4 Answers

4
votes

there is a build in method for tree like results to be made into a list for select option tags:

$this->Model->generateTreeList($conditions, null, null, ' - ', $recursive);

instead of using find(threaded)

that is if you attached the Tree behavior to it (which you probably should have since its obviously a tree like model).

But if you want to keep your find(threaded) method you need to manually transform it via recursive method.

2
votes

thanks DSkinner, very informative.. i have modified it to be more generic:

/**
 * Returns an indented html select based on children depth
 *
 * @param array $data_array - Array of data passed in from cake's find('threaded') feature
 * @param array $model - the model name
 * @param array $key - the key field on the model
 * @param array $value - the value field on the model
 * @param array $list - Used internally, contains array to be returned
 * @param int $counter - Used Internally, counter for depth
 * @return array
 */
public function threaded_to_list($data_array, $model=null, $key='id', $value='name', 
&$list = array(), $counter = 0, $separator='__')
{
    if ( ! is_array($data_array))
        return array();

    foreach ($data_array AS $data)
    {
        $list[$data[$model][$key]] = str_repeat($separator, $counter).$data[$model][$value];
        if ( ! empty($data['children']))
        {
            $this->threaded_to_list($data['children'], $model, $key, $value, $list, $counter + 1);
        }
    }
    return $list;
}
1
votes

Here's what worked for me.

Make sure you replace:

  • {SELECT_ID} with the value of the drop down
  • {SELECT_LABEL} with what is displayed as the option
  • {MODEL_NAME} with your model name
/**
 * Returns an indented html select based on children depth
 *
 * @param array $data_array - Array of data passed in from cake's find('threaded') feature
 * @param array $list - Used internally, contains array to be returned
 * @param int $counter - Used Internally, counter for depth
 * @return array
 */
public function drop_down_from_threaded($data_array, &$list = array(), $counter = 0)
{
    if ( ! is_array($data_array))
        return array();

    foreach ($data_array AS $data)
    {
        $list[$data[{SELECT_ID}]] = str_repeat('  ', $counter).$data[{SELECT_LABEL}];
        if ( ! empty($data['children']))
        {
            $this->drop_down_from_threaded($data['children'], $list, $counter + 1);
        }
    }
    return $list;
}

/**
 * Get the data from the find('threaded') and pass it to our new function
 */

$results = $this->{MODEL_NAME}->find('threaded');
$results = $this->drop_down_from_threaded($results);

This may not work 100% for everyone, it works for me, but it should help give you something to start with.

0
votes

What are "children"? Seems like your tree is spawned across one-to-many relations

It is not necessary to use the Tree behavior to use this method - but all desired results must be possible to be found in a single query.