4

So I'm trying to return a find 'all' array using the id of a 'Product' as the index key for each Product.

Typically it returns:

array(
    (int) 0 => array(
        'Product' => array(
            'id' => '1232',
            'category_id' => '330',
            'name' => 'Product #1',
        )
    ),
    (int) 1 => array(
        'Product' => array(
            'id' => '1245',
            'category_id' => '310',
            'name' => 'Product #2',
        )
    ),
    (int) 2 => array(
        'Product' => array(
            'id' => '1248',
            'category_id' => '312',
            'name' => 'Product #3',
        )
    )
)

Whereas ideally I'd like it to return:

array(
    (int) 1232 => array(
        'Product' => array(
            'id' => '1232',
            'category_id' => '330',
            'name' => 'Product #1',
        )
    ),
    (int) 1245 => array(
        'Product' => array(
            'id' => '1245',
            'category_id' => '310',
            'name' => 'Product #2',
        )
    ),
    (int) 1248 => array(
        'Product' => array(
            'id' => '1248',
            'category_id' => '312',
            'name' => 'Product #3',
        )
    )
)

Is this possible? And how do I go about doing it?

I have an excel spreadsheet of records that I need to match ID's to, so currently I have it iterating each spreadsheet row and performing a 'first' find to get any results, then act upon them if they do.

It works, but the recordset has grown to over 28000 and so performing one find for each has noticeable overhead.

If I can do this simply in the 'find' operation it would be great, if not, any noticeable increase in performance would be appreciated.

1
  • What is the performance of this like? Commented Nov 26, 2014 at 11:13

3 Answers 3

6

You can get this result as after find all :

$result = Hash::combine($data, '{n}.Product.id', '{n}.Product');

Where $data is the result of find all.

Sign up to request clarification or add additional context in comments.

1 Comment

Alternative: indexBy()
6

You can have your find method extended in AppModel like this

public function find($type = 'first', $query = array()) {
    switch($type) {
        case 'keysid':

            if($results = parent::find('all', $query)){

                if(isset($results[0][$this->alias]['id'])){

                    return Hash::combine($results, '{n}.'.$this->alias.'.id', '{n}');
                }else{
                    return $results;
                }

            } 
        break;
        default:
            return parent::find($type, $query);
            break;
    }
}

And afterwards you can call your find method as follows:

$this->Product->find('keysid');

Then you will have a result array as you specified. However you can also do this with one line of code if you need it once. Say $products is your array from the find('all')

if($products = $this->Product->find('all')){
        $alteredProducts = Hash::combine($products, '{n}.Product.id', '{n}');
    }

Have a look at the Hash utility

1 Comment

Alternative: indexBy()
0

Use indexBy():

$articles = $this->Articles->find('all')
    // optional conditions etc.
    //->where(['Users.id' => $identity->get('id')])
    ->all()
    ->indexBy('id')
    ->toArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.