2015-04-21 16 views
8

Il Codice

Dire che ho due modelli, denominati Product e Image, che sono collegati da Product hasMany Image e Image belongsTo Product.Utilizzando limite() del modello contenuta

Ora, dire che voglio recuperare tutti i prodotti con la prima immagine ciascuno. Vorrei usare questo codice:

$this->Products->find('all') 
    ->contain([ 
     'Images' => function($q) { 
      return $q 
       ->order('created ASC') 
       ->limit(1); 
     } 
    ]); 

Sembra giusto, giusto? Tranne ora solo uno dei prodotti contiene un'immagine, anche se in realtà ogni prodotto contiene almeno un'immagine (se interrogata senza il limite).

La risultante Query

Il problema sembra essere con il limite, dal momento che questo produce i seguenti due query (per esempio):

SELECT 
    Products.id AS `Products__id`, 
FROM 
    products Products 

e

SELECT 
    Images.id AS `Images__id`, 
    Images.product_id AS `Images__product_id`, 
    Images.created AS `Images__created` 
FROM 
    images Images 
WHERE 
    Images.product_id in (1,2,3,4,5) 
ORDER BY 
    created ASC 
LIMIT 1 

Guardando la seconda query, è abbastanza ovvio come ciò comporterà sempre una sola immagine.

Il problema

Tuttavia, mi sarei aspettato la torta ORM per limitare le immagini da 1 per prodotto quando ho chiamato limit(1).

La mia domanda: si tratta di un errore nel modo in cui utilizzo l'ORM? In tal caso, come deve limitare il numero di immagini a una per immagine?

+0

di riferimento futuro: ho finito semplicemente omettendo la 'limit()' e basta usare la prima immagine dell'array. Tutte le risposte, mentre si lavora, sembrano una soluzione alternativa. The Cake ORM ** always ** utilizza una singola query per contiene, anche se questo non è desiderato (come quando si aggiunge un limite alla query). –

risposta

14

Il modo più pulito si può fare questo è attraverso la creazione di un'altra associazione:

$this->hasOne('FirstImage', [ 
    'className' => 'Images', 
    'foreignKey' => 'image_id', 
    'strategy' => 'select', 
    'sort' => ['FirstImage.created' => 'DESC'], 
    'conditions' => function ($e, $query) { 
     $query->limit(1); 
     return []; 
    } 
]) 
+1

ma non sto ottenendo l'ultima riga, sto ottenendo il primo. Potete suggerirvi di più? – sradha

+0

Grazie. Ho capito. Funziona davvero. Vorrei invogliarti. – sradha

+0

@sradha: come hai risolto? Non riesco a ordinare nell'array primario di hasOne e l'ordine non funziona nella query sulle condizioni. Posso solo sembrare di ottenere il primo risultato. – MiDri

0

Se il motivo per cui lo si limita a un'immagine è che si desidera avere un'immagine predefinita. Si potrebbe considerare l'aggiunta di un campo default nella tabella immagine e facendo un alias come questo:

var $hasOne = array(
    'CoverImage' => array(
     'className' => 'Image', 
     'conditions' => array('CoverImage.default' => true), 
    ), 

Sembra che si sta utilizzando torta v3 così si può semplicemente aggiungere l'associazione equivalente quanto sopra è un esempio 2.x .

2

verificarle, questo è il mio codice

$this->Orders->hasOne('Collections', [ 
        'className' => 'Collections', 
        'foreignKey' => 'order_id', 
        'strategy' => 'select', 
        'conditions' => function (\Cake\Database\Expression\QueryExpression $exp, \Cake\ORM\Query $query) { 
        $query->order(['Collections.id' => 'ASC']); 
        return []; 
                                 } 
        ]); 


        $Lists = $this->Orders->find('all')->where($condition)->contain(['Collections'])->order(['Orders.due_date DESC']); 
        $this->set(compact('Lists')); 
Problemi correlati