Bonjour,
j'ai un petit problème en utilisant le paginator::sort();
Je souhaite trier avec le sort donc je créé mon paginate, le truc c'est que j'ai 3 niveau de profondeur avec des comportement containable.

'contain' => 
    array('Version' =>
                array('Project'=>array('fields'=>array('Project.id', 'Project.title')))

C'est cette partie là qui est intéressante, j'ai Des versions sont liés à des projets via le comportement containable.
Je veux trier avec sorte mais par par project_id mais par Version.Project.title
Le truc c'est que ça marche super bien pour le premier niveau de profondeur c'est à dire pour trier par Version.title par exemple ou par Version.project_id mais ça ne fonctionne plus pour Version.Project.title.

Ceci fonctionne:

$this->Paginator->sort('Version.title', 'Version');

Ceci ne fonctionne pas (ne tri tout simplement rien quand on clique sur le lien):

$this->Paginator->sort('Version.Project.title', 'Project');

Si quelqu'un à une idée je suis preneur !

J'ai déjà pas mal cherché sur le net mais bon souvent c'était carrement le premier niveau qui marchait pas... et souvent c'était des actAs qui était oublié dans les modèles.

Merci d'avance

Cordialement

5 réponses


Nightbringer
Auteur
Réponse acceptée

... Justement: **évidement sans à avoir à taper la query à la main, en utilisant les outils cakePHP.** Le but étant de garder la syntaxe de cake qui permet d'avoir des choses claires et organisées. Enfin on voit ici une des limites de cake (qui n'est pas une limite finalement car il y a des solutions ^^). La première utiliser un autre behavior qui lui fait les LEFT JOIN jusqu'au bout et ne s'arrête pas au niveau 1. - LinkableBehavior (search on gitHub) en est un. Mais finalement j'ai otpé pour une autre solution qui est de créer **une vue mySQL.** [code]CREATE VIEW defects_view AS SELECT ... [/code] dans mon controller dès que j'ai besoin de ma vue : [code]//we use the view table here! $this->Defect->useTable = 'defects_view';[/code] Et j'ai LEFT JOIN à la main toute mes tables y compris celle de profondeurs multiples. Voilà Merci à tous ! Cordialement

utilises "order" dans ton containable à l'intérieur de l'array/model que tu veux classer, genre tu envoi par post le champ à classer
un truc qui ressemble à ca mais je pense en plus compliquer ici tu récupère le champs à classer et la direction (asc ou desc) ensuite tu rajoutes dans ton cas quel model tu veux classer

if ($this->request->is('post')) {
$this->Project->contain(array(
    'Fields' => array(
        'conditions' => // tes conditions.....
                'fields' =>> // tes champs à mettre a afficher
        'order' => 'Fields.'.$this->request-data'champ'].' '.$this->request-data'direction'] // direction c'est asc ou desc
    ),
));
}

si ca fonctionne ce qui reste c'est l'utilisation des cookies et de sauvegarder ca pour qu'il puisse sauvegarder ca comme uen sortes de préférences (pas besoin à chaque chargement de page de refaire le chargement, c'est le dernier sort/order qui est appliquer :)

Tente la méthode de BenFarhat.

Sinon:
remplace:

echo $this->Paginator->sort('Version.Project.title', 'Project');

Par:

echo $this->Paginator->sort(array('Version' => 'Project.title'));

Pas sure que ca marche mais tente toujours. J'avais vus un truc dans le genre il me semble y a pas très longtemps.

Sinon il me semble que cela ne soit pas possible. A reflechir si tu regardes le log sql tu verras qu'il fait plusieurs requêtes pour récupérer ton contain. Donc la seule méthode que je vois serait de faire ta requête manuellement en faisant des jointures

EDIT:
C'est la que j avais vu

Merci à vous deux,
Déjà Mikachu, ce n'est pas le lien qui pose problème, mais le traitement derrière (et de plus sort requière des strings et non un array enfin bref...)
BenFarhat, merci pour cette solution, mais je ne comprends pas pourquoi le contain fonctionne bien à partir d'un niveau et qu'au deuxième niveau cela ne fonctionne plus.
Je viens de voir pourquoi ça ne fonctionne pas...
Au lieu de me faire une seule requête, il me fait la requête principale et ensuite plusieurs requêtes pour aller chercher mes projets liés au version:

SELECT `Defect`.`id`, `Defect`.`severity_id`, `Defect`.`found_by_user_id`, `Defect`.`assigned_to_user_id`,
 `Defect`.`version_id`, `Defect`.`found_in_build`, `Defect`.`fixed_in_build`, `Defect`.`title`, `Defect`.`content`, 
`Defect`.`status_id`, `Defect`.`location_id`, `Defect`.`show_stopper`, `Defect`.`fixed_date`, `Defect`.`modified`, 
`Defect`.`created`, `Severity`.`id`, `Severity`.`title`, `Severity`.`content`, `found_user`.`id`, 
`found_user`.`username`, `found_user`.`is_admin`, `found_user`.`is_manager`, `found_user`.`is_active`, 
`found_user`.`is_dev`, `found_user`.`is_qa`, `assigned_user`.`id`, `assigned_user`.`username`, 
`assigned_user`.`is_admin`, `assigned_user`.`is_manager`, `assigned_user`.`is_active`, `assigned_user`.`is_dev`, 
`assigned_user`.`is_qa`, `Version`.`id`, `Version`.`title`, `Version`.`project_id`, `Status`.`id`, `Status`.`title`,
 `Status`.`is_open`, `Location`.`id`, `Location`.`content`, `Location`.`project_id` FROM `defects_dbo`.`defects` AS 
`Defect` LEFT JOIN `defects_dbo`.`severities` AS `Severity` ON (`Defect`.`severity_id` = `Severity`.`id`) LEFT JOIN 
`defects_dbo`.`users` AS `found_user` ON (`Defect`.`found_by_user_id` = `found_user`.`id`) LEFT JOIN 
`defects_dbo`.`users` AS `assigned_user` ON (`Defect`.`assigned_to_user_id` = `assigned_user`.`id`) LEFT JOIN 
`defects_dbo`.`versions` AS `Version` ON (`Defect`.`version_id` = `Version`.`id`) LEFT JOIN `defects_dbo`.`stati` AS
 `Status` ON (`Defect`.`status_id` = `Status`.`id`) LEFT JOIN `defects_dbo`.`locations` AS `Location` ON 
(`Defect`.`location_id` = `Location`.`id`) WHERE 1 ORDER BY `Defect`.`id` DESC LIMIT 10 
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 25
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 29
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 29
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 29
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 24
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 35
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 24
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 24
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 35
SELECT `Project`.`id`, `Project`.`title` FROM `defects_dbo`.`projects` AS `Project` WHERE `Project`.`id` = 21

Si quelqu'un sait comment inclure la sous requête des projets liés à la version dans la requête du haut, cela fonctionnera !
J'ai cherché et cela pourrait être possible avec <u>les JOINS</u>.
Je continue mes recherches !

<u>Notes importantes :</u> quand je fais un simple 'order'=>'Version.Project.title' il retourne une erreur sql comme quoi la clé n'existe pas, normal !! Car il sépare les requêtes des projets...

Donc la solution de se problème réside dans la suppression de ces sous-requête sur les projets et les mettres dans la requête principale , et évidement sans à avoir à taper la query à la main, en utilisant les outils cakePHP.

Merci d'avance
Et merci à tous ceux qui m'ont déjà bien aidé à deblayer le problème.

Cordialement

Donc, c est bien ce que je disais a mon avis la seule solution serait de faire ta requête manuellement avec query() tu n'auras pas trop le choix ... Citation: - Sinon il me semble que cela ne soit pas possible. A reflechir si **tu regardes le log sql tu verras qu'il fait plusieurs requêtes pour récupérer ton contain**. Donc la **seule méthode** que je vois serait de **faire ta requête manuellement** en faisant des jointures [url=http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query]Regarde ICI pour Model::query()[/url] Bonne chance