tags:

views:

215

answers:

5

I am a beginning Cake user but well versed in php and frame works in general (I used to use Code Igniter). How can I call the model below and only return the Artist records and the related ArtistImage records, not the Album records.

class Artist extends AppModel {

 var $name  = 'Artist';
 var $hasMany  = array('Album', 'ArtistImage');

}

Also, can you clarify what the values for $this-Artist->recursive do?

Thanks for the help

+1  A: 

The Containable behavior (book.cakephp.org/view/474/Containable) is what you're looking for.

The recursive property (book.cakephp.org/view/439/recursive) tells how deep CakePHP should go relationship-wise when fetching records.

mscdex
Having problems getting this to work, I posted a description fo the error I am getting below:
Louis W
+3  A: 
    // Artist /app/models/artist.php
    class Artist extends AppModel {

        var $name       = 'Artist';
        var $hasMany    = array('Album', 'ArtistImage');
        var $actAs      = array('Containable');
    }


    // ArtistsController /app/controllers/artists_controller.php
    class ArtistsController extends AppController {

       var $name        = 'Artists';

       public function example() {

           debug( $this->Artist->find( 'all' );

           debug( $this->Artist->find( 'all', array(
               'recursive' => 0,
           ));

           debug( $this->Artist->find( 'all', array(
               'contain' => array(
                  'ArtistImage' => array(
                      // artist find options here i.e. fields, conditions, order etc
                  ),
               );
           ));
       }
    }

    // results
    // with just find( 'all' )
    Array
    (
        [0] => Array
            (
                [Artist] => Array
                    (
                        [id] => 1,
                        [name] => Wumpscut
                    ),
                [Album] => Array
                    (
                        [0] => Array
                            (
                                [id] => 1,
                                [artist_id] => 1,
                                [name] => Bunker Gate Seven
                            ),
                        [1] => Array
                            (
                                [id] => 2,
                                [artist_id] => 1,
                                [name] => Born Again
                            )
                    ),
                [ArtistImage] => Array
                    (
                        [0] => Array
                            (
                                [id] => 1,
                                [artist_id] => 1,
                                [file] => Bunker-Gate-Seven-Cover.jpg
                            ),
                        [1] => Array
                            (
                                [id] => 2,
                                [artist_id] => 1,
                                [file] => Born-Again-Cover.jpg
                            )
                    )
            ),
        [1] => Array
            (
                [Artist] => Array
                    (
                        [id] => 2,
                        [name] => Oneriod Psychosis
                    ),
                [Album] => Array
                    (
                        [0] => Array
                            (
                                [id] => 3,
                                [artist_id] => 2,
                                [name] => Fantasies About Illness
                            ),
                    ),
                [ArtistImage] => Array
                    (
                        [0] => Array
                            (
                                [id] => 3,
                                [artist_id] => 2,
                                [file] => Fantasies-About-Illness-Cover.jpg
                            ),
                    )
            )
    )


    // results
    // with recursive 0
    Array
    (
        [0] => Array
            (
                [Artist] => Array
                    (
                        [id] => 1,
                        [name] => Wumpscut
                    ),

            ),
        [1] => Array
            (
                [Artist] => Array
                    (
                        [id] => 2,
                        [name] => Oneriod Psychosis
                    )
            )
    )


    // results
    // with find( 'all', array( 'contain' => array( 'ArtistImage' ))

    Array
    (
        [0] => Array
            (
                [Artist] => Array
                    (
                        [id] => 1,
                        [name] => Wumpscut
                    ),
                [ArtistImage] => Array
                    (
                        [0] => Array
                            (
                                [id] => 1,
                                [artist_id] => 1,
                                [file] => Bunker-Gate-Seven-Cover.jpg
                            ),
                        [1] => Array
                            (
                                [id] => 2,
                                [artist_id] => 1,
                                [file] => Born-Again-Cover.jpg
                            )
                    )
            ),
        [1] => Array
            (
                [Artist] => Array
                    (
                        [id] => 2,
                        [name] => Oneriod Psychosis
                    ),
                [ArtistImage] => Array
                    (
                        [0] => Array
                            (
                                [id] => 3,
                                [artist_id] => 2,
                                [file] => Fantasies-About-Illness-Cover.jpg
                            ),
                    )
            )
    )

Hope that helps to explain it

Abba Bryant
Having problems getting this to work, I posted a description fo the error I am getting below:
Louis W
A: 

Can you post your controller and model into pastebin? Post those links here when you're done.

In your pastebin entry you are using...

if( $images ) {
    echo( "Loading Artist Images" );
    $this->Artists->recursive = 1;
    $this->Artists->contains( 'ArtistImage' );
} else { ...

This wont work for a few reasons.

First - the Model names need to be Singular. I.E. Artists = Artist Second - the Containable behavior does not have a function "contains", the correct function name is also singular. I.E contains( 'ArtistImage' ) = contain( 'ArtistImage' )

So I FTFY, here ya go.

if( $images ) {
    echo( "Loading Artist Images" );
    $this->Artist->contain( 'ArtistImage' );
} else { ...

Hope this clarifies things for you. http://book.cakephp.org/view/474/Containable http://book.cakephp.org/view/22/CakePHP-Conventions

Also, depending on which version of Cake you are using I believe calling a model function that doesn't exist ( i.e. Model->contains( ... ) ) will try and call a stored procedure from mysql if the Model file doesn't have a function of that name.

Abba Bryant
BTW Here is the error:// ErrorWarning (512): SQL Error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'contain' at line 1 [CORE/cake/libs/model/datasources/dbo_source.php, line 514]// In the list of queries executed it lists:2 contain 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'contain' at line 1
Louis W
the line $this->Artist->recursive = 1;Isn't needed, the Containable behavior will sort that out for you. I don't have a dev env here to play on but I think it might be what is causing you to fetch more info than you are asking for.
Abba Bryant
do me a favor, do a mysql show create on the tables involved, poste one table per pastebin along with a pastebin for each model and the controller.I will recreate the structure here and take a look.
Abba Bryant
Sorry man I never saw this comment it was buried below a "read more" link. Here are the links, might be easier over email feel free to shoot me a mail me a-t louiswalch d-o-t c*mmodels/artist.phphttp://pastebin.com/m27921633models/album.phphttp://pastebin.com/d27f35391models/artist_image.phphttp://pastebin.com/d7d5e7bbdcontrollers/store_controller.phphttp://pastebin.com/d4b06f35dMySQLhttp://pastebin.com/m21efaf84
Louis W
A: 

The model is Album, so it should be $this->Album instead of $this->Albums

App::import('Model', 'Album');

$this->Album->contain('Song'); $items = $this->Album->findAllByArtistId($artist_id);

KienPham.com
I tried this change and it still gives the error. $this->Artist->contains('ArtistImage'); however it does return the related items, but all of them, not the ones I picked as contains. Also please refer to my pastebin example code in comment below, this is the most current.
Louis W
try $this->Artist->contain('ArtistImage') with no s at the contain. You use s inside the conditions.
KienPham.com
+1  A: 

I think the problem is your Artist Model. The correct way to add the behavior is

<?php
    Class Artist extends AppModel
    {
        public $name = "Artist";
        public $actsAs = array( 'Containable' );
    }
?>

Notice the actsAs variable is plural, your model has it as $actAs = array( .. ) with the variable as a singular.

Abba Bryant
YES! That was it. Thanks again for all your help. Total oversight on my behalf.
Louis W