0
votes

I'm new to cakePHP and MVC development and trying to create something with cakePHP but can't figure out how to do this :

I'm creating a simple CRUD application which takes in Albums and Songs through simple data entry forms. I created the DB and used the Cake console app to create all the models / controllers etc and it works well. I can CRUD both albums and songs no problem, and the song table in the DB is connected to the album table with a foreign key so all the links and associations are there in the model.

What I want to do is be able to click on an album and see the songs associated with that album, ,but I'm not sure how to go about it. Do I need to add a query in the model, or does that functionality go into the Controller ?

My take is : in the album list make the album names links, which call a |viewAlbum| function in the Songs Controller with the albumID. Not sure where to go from here though ......

Can anyone point me in the right direction ?

Cheers, Colm


@JohnP Thank you for your reply. How do you create a link to call that function in the controller though ? I have :

echo $html->link(__($album['Album']['title'], true), array('controller'=>'Songs', 'action'=>'viewAlbum', $album['Album']['id']));

Where viewAlbum is the name of the function in the songs controller. Any ideas on why this doesn't work ?

2

2 Answers

0
votes

Cake's native ORM already does this for you. If you actually go into the view page for an album, it should be showing you all the related songs there it self. This works only if you have setup the relationships properly.

If you want to code this behavior yourself, you could put a viewSongs action in your AlbumController. This method would look at the album ID passed to it, and call a method (e.g. getSongsByAlbum($aid)) in your Song model. Inside that method in your song model would be a call that looks something like

$opts = array(
   'conditions' => array(
       'album_id' => $aid
   )
);
return $this->find('all', $opts);
0
votes

Protos -

If I understand correctly -- you're using John's example, and you need to fix the link in your view that calls his controller?

<?
echo $this->Html->link(__($album['Album']['title'], true), array('controller'=>'Album', 'action'=>'viewSongs', $id));

?>

John's example explained how to create a method in the Albums controller, suggested hitting a method in the Songs model that returned the desired results.

So your link would target the Album controller, and its action should be the controller method.

This method makes less sense in the Songs controller, because it requires an Album id. You just want the Album controller to pull associated data from the Songs model / table. John's answer is exactly correct but maybe too complicated if you're just getting started with Cake. John split the needed functionality by putting a method in the Song model, called by a method in the Albums controller, which pulls results for your view to display.

I'm switching this to "fat controller," which is easier to follow for short code but less MVC.

You need a hasMany relationship from Albums to Songs - each Album hasMany Songs:

// ../models/album.php

class Album extends AppModel {

    var $name = 'Album';

    var $hasMany = array(
        'Song' => array(
            'className' => 'Song',
            'foreignKey' => 'album_id'
        )
    );

Your controller action will look like this:

// ../controllers/albums_controller.php

function viewSongs($id = null) {
    if(isset($id) && $id != null) {
        $albums = $this->Album->find('first',       
            array('conditions'=>array('Album.id'=>$id));
        $songs = $this->Album->Song->find('all', 
            array('conditions'=>array('Song.album_id'=>$id)));
        // This returns variables to the view to use
        $this->set(compact('albums', 'songs'));
    }
}

Your view will be called viewSongs.ctp, and it'll look something like this:

// ../views/albums/viewSongs.ctp

<?php 
foreach($albums as $album) {
    echo "<h2>{$album['name']}</h2>";
    echo "<ul>";
    foreach ($songs as $song) {
       echo "<li>{$song['Song']['name']}</li>"
    }
    echo "</ul>";
}

And your link in ../views/albums/view.ctp would be like:

<?php
echo $this->Html->link('View Songs', array('controller'=>'albums',
    'action'=>'viewSongs', $id));
?>