Bonjour.
Tout d'abord, merci pour les tutos et formations. J'ai pu m'approprié tout ce que j'ai entrepris de découvrir avec les ressources du site. C'est un régal à chaque fois. J'ai d'ailleurs trouvé la première étape de ce que j'avais à faire dans la vidéo de création d'un système de tag avec CakePHP.

Mon problème est le suivant. J'ai un système extérieur de gestion de photo dont la bdd ne peux être changée (notamment le nom des tables/champs). Il y a des images dans des albums, les images peuvent appartenir à plusieurs albums et les albums peuvent contenir plusieurs images. Les cardinalités sont donc 0,n-0,n.

Je dois donc à la fois utiliser les alias nom de table->controller et des associations.
J'ai défini les modèles Album(id) et Picture(id) comme il suit :

class Album extends AppModel{
    public $useDbConfig = 'kdb';
    public $useTable = 'k_albums';
    public $hasAndBelongsToMany = array(
        'Picture' => array(
            'className' => 'Picture',
            'joinTable' => 'k_join_albums_content',
            'foreignkey' => 'albums_id',
            'associationForeignKey' => 'content_id'
        )
    );
}

class Picture extends AppModel{
    public $useDbConfig = 'kdb';
    public $useTable = 'k_content';
    public $hasAndBelongsToMany = array(
        'Album' => array(
            'className' => 'Album',
            'joinTable' => 'k_join_albums_content',
            'foreignkey' => 'content_id',
            'associationForeignKey' => 'album_id'
        )
    );
}

La table de liaison est définie comme ceci : k_join_albums_content(id, albums_id, content_id).
L'appel depuis l'AlbumController est réalisé comme ceci :

class AlbumsController extends AppController{
    public $paginate = array(
        'limit' => 6,
        'order' => array('Album.published_on' => 'DESC')
    );
    public function index(){
        $albums = $this->paginate('Album', array('Album.listed' => 'true'));
        $this->set(compact('albums'));
    }
}

La première requête, permettant de récupérer les albums fonctionne bien (vérification en debug). Par contre, quand il s'agit d'aller chercher les images, l'erreur qui m'est sortie est la suivante :

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'KJoinAlbumsContent.k_album_id' in 'on clause'
SQL Query: SELECT `Picture`.`id`, `Picture`.`title`, `Picture`.`slug`, `Picture`.`old_slug`, `Picture`.`filename`, `Picture`.`caption`, `Picture`.`visibility`, `Picture`.`max_download`, `Picture`.`license`, `Picture`.`deleted`, `Picture`.`featured`, `Picture`.`featured_order`, `Picture`.`favorite_order`, `Picture`.`favorite`, `Picture`.`favorited_on`, `Picture`.`featured_on`, `Picture`.`uploaded_on`, `Picture`.`captured_on`, `Picture`.`published_on`, `Picture`.`modified_on`, `Picture`.`file_modified_on`, `Picture`.`focal_point`, `Picture`.`filesize`, `Picture`.`width`, `Picture`.`height`, `Picture`.`aspect_ratio`, `Picture`.`duration`, `Picture`.`tags`, `Picture`.`file_type`, `Picture`.`lg_preview`, `Picture`.`internal_id`, `Picture`.`iptc`, `Picture`.`exif`, `Picture`.`exif_make`, `Picture`.`exif_model`, `Picture`.`exif_iso`, `Picture`.`exif_camera_serial`, `Picture`.`exif_camera_lens`, `Picture`.`source`, `Picture`.`source_url`, `Picture`.`html`, `KJoinAlbumsContent`.`id`, `KJoinAlbumsContent`.`album_id`, `KJoinAlbumsContent`.`content_id`, `KJoinAlbumsContent`.`order` FROM `k`.`k_content` AS `Picture` JOIN `k`.`k_join_albums_content` AS `KJoinAlbumsContent` ON (`KJoinAlbumsContent`.`k_album_id` IN (71, 35, 38, 50, 69, 59) AND `KJoinAlbumsContent`.`content_id` = `Picture`.`id`)

On voit bien sur la fin de la requête qu'il me transforme la table k_join_albums_content en KJoinAlbumsContent. Naïvement, j'ai essayé de créer un modèle intermédiaire comme ci dessous, mais cela ne m'a pas fait avancer d'un iota :

class AlbumPicture extends AppModel{
    public $useDbConfig = 'kdb';
    public $useTable = 'k_join_albums_content';
    public $belongTo = array('Album', 'Picture');
}

Qu'ai-je fait de travers ?
Merci d'avance.

3 réponses


Xeta
Réponse acceptée

Hello,

Tes associations ne sont pas bonne car :
Un Album a plusieurs (hasMany) Pictures
Et les Pictures ont et appartiennent à plusieurs (hasAndBelongsToMany) Albums.

D'ailleurs, toi même tu l'a dit :

les images peuvent appartenir à plusieurs albums et les albums peuvent contenir plusieurs images.

En fait il crée un alias pour ta table
k_join_albums_content` AS KJoinAlbumsContent
Donc il tape bien ta table k_join_albums_content mais il ne trouve pas k_album_id

DrSnake
Auteur

Merci pour vos réponses.

@Grafikart : Ok pour l'alias, j'avais juste noté qu'il remappait le nom en CamelCase mais je n'avais pas bien regardé pourquoi. Mais justement, moi je lui spécifie avec le foreignkey et les associationForeignKey :

  • Album.id=k_join_albums_content.album_id

  • Picture.id=k_join_albums_content.content_id

Là, il essaie de taper sur k_join_albums_content.k_album_id et non pas album_id. Je ne sais pas d'où vient ce prefix **k\** _album_id.

@Xeta : En effet, j'ai mal imaginé la transcription des liaisons avec CakePHP.

Du coup, je ne vois pas trop comment utiliser le hasMany mais avec une table intermédiaire. Je me remets dessus et je reviens un peu plus tard.