cakephpindexingfindassociative-arraycontainable

Cakephp 2 use the id of the record as index when retrieving data


Is it possible to retrieve records where the index is the record id?

I have a model with a hasMany Relation. So my study can have multiple texts and questions etc.

The custom retrieve function looks like this:

    protected function _findStudyWithSequence($state, $query, $results=array()){
    if ($state === 'before') {
        $query['contain'] = array(
            'SubjectFilter'=>array('fields'=>'SubjectFilter.studyCode'),
            'Text'=>array('fields'=>'Text.position,Text.id,Text.text','order'=>array('position')),
            'Image'=>array('fields'=>'Image.position, Image.id','order'=>array('position')),
            'Video'=>array('fields'=>'Video.position, Video.id','order'=>array('position')),
            'Web'=>array('fields'=>'Web.position, Web.id','order'=>array('position')),
            'Likert'=>array('fields'=>'Likert.position, Likert.id','order'=>array('position')),
            'Question'=>array('fields'=>'Question.position, Question.id','order'=>array('position')),
            'Star'=>array('fields'=>'Star.position, Star.id','order'=>array('position')),
            'Multiple_choice'=>array('fields'=>'Multiple_choice.position, Multiple_choice.id','order'=>array('position'))
        );
        $query['recursive']=-1;
        $query['order']=array('Study.started DESC');
        $query['fields']=array(
                    'Study.id', 'Study.user_id','Study.title','Study.description','Study.numberParticipants','Study.state','Study.created','Study.modified','Study.started','Study.completed','Study.numberParticipants');

        return $query;
    }

    }
    return $results;
}

As you can see I am using containable The results look like this:

array(
'Study' => array(
    'id' => '1845346986',
    'user_id' => '1402402538',
    'title' => 'bla bla',
    'description' => '',
    'numberParticipants' => '10',
    'state' => 'active',
    'created' => '2017-08-21 14:06:11',
    'modified' => '2017-08-21 14:29:56',
    'started' => '2017-08-21 14:30:06',
    'completed' => '0000-00-00 00:00:00',
),
'SubjectFilter' => array(
    'studyCode' => null
),
'Text' => array(
    (int) 0 => array(
        'position' => '0',
        'id' => '1423909242',
        'text' => '<p>Bla <b>bla </b></p><p>blub</p><p><br /></p>',
        'study_id' => '1845346986'
    )
),
'Question' => array(
    (int) 0 => array(
        'position' => '4',
        'id' => '729521908',
        'study_id' => '1845346986'
    )
), etc

But I want the Text and Question index to be the ids. Like this:

'Text' => array(
    (int) 1423909242 => array(
        'position' => '0',
        'id' => '1423909242',
        'text' => '<p>Bla <b>bla </b></p><p>blub</p><p><br /></p>',
        'study_id' => '1845346986'
    )
),

How can i manage this?


Solution

  • You can use CakePHP's amazing Hash::combine() method.

    Something like:

    $results['Text'] = Hash::combine($results['Text'], '{n}.id', '{n}');
    $results['Question'] = Hash::combine($results['Question'], '{n}.id', '{n}');
    return $results;
    

    It's not tested code, but I believe it's correct (or at least close), and you should get the idea from here.

    Notes on Hash::combine:

    Creates an associative array using a $keyPath as the path to build its keys, and optionally $valuePath as path to get the values. If $valuePath is not specified, or doesn’t match anything, values will be initialized to null. You can optionally group the values by what is obtained when following the path specified in $groupPath.

    Hash::combine(array $data, $keyPath, $valuePath = null, $groupPath = null)