1

I have code working search related models using the Search Plugin, but it forces me to break the structure of my model associations. As a result, my save and edit functions do not work properly.

Here is the structure of my data.

Model:

public $belongsTo = array(
    'Movie' => array(
        'className' => 'Movie',
        'foreignKey' => 'movie_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
        'MovieStarRecurrance' => array(
        'className' => 'MovieStarRecurrance',
        'foreignKey' => 'movie_star_recurrance_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'MovieStarType' => array(
        'className' => 'MovieStarType',
        'foreignKey' => 'movie_star_type_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
);
public $hasMany = array(
    'MovieStarLine' => array(
    'className' => 'MovieStarLine',
    'foreignKey' => 'movie_star_id',
    'dependent' => false,
    'conditions' => '',
    'fields' => '',
    'order' => 'status_date',
    'limit' => '',
    'offset' => '',
    'exclusive' => '',
    'finderQuery' => '',
    'counterQuery' => ''
    ),
);

I am searching and filtering within the related model Movie and the User that Movie belongsTo.

public $filterArgs = array(
    'parent_user_id'     => array('type' => 'like', 'field' => 'User.parent_user_id'),
    'initials'   => array('type' => 'value', 'field' => 'User.id'),
    'trace'  => array('type' => 'like', 'field' => 'MovieStar.trace'),
    'movie'  => array('type' => 'query', 'method' => 'orConditionsMovie'),
    'star_type'  => array('type' => 'value', 'field' => 'MovieStar.movie_star_type_id'),
    'code'   => array('type' => 'value', 'field' => 'MovieStar.code'),
    'status'     => array('type' => 'value', 'field' => 'MovieStarLine.movie_star_status_id'),
    'open'   => array('type' => 'value', 'field' => 'MovieStar.open'),
    'from_date'  => array('type' => 'query', 'method' => 'orConditionsFromDate'),
    'end_date'   => array('type' => 'query', 'method' => 'orConditionsEndDate'),
);

In order to access these models at the top level of my search, I unbind the Movie model belongsTo association and rebind it as hasOne. I do the same for MovieStarLine and MovieStarStatus.

Controller:

    $this->MovieStar->recursive = 0;

    $this->MovieStar->unbindModel( array(
    'belongsTo' => array('Movie')
        )
    );

    // MovieStarStatus to be top level json element
    $this->MovieStar->bindModel( array(
        'hasOne' => array(
            'Movie' => array(
                'foreignKey' => false,
                'conditions' => array('Movie.id = MovieStar.movie_id'),
                'fields' => array('Movie.id', 'Movie.movie_id', 'Movie.user_id', 'Movie.movie_mid', 'Movie.movie_dba')
            ),
            'User' => array(
                'foreignKey' => false,
                'conditions' => array('Movie.user_id = User.id'),
                'fields' => array('User.id', 'User.initials', 'User.user_first_name', 'User.user_last_name', 'User.name', 'User.parent_user_id', 'User.secondary_parent_user_id')
            ),
            'MovieStarLine' => array(
                'foreignKey' => false,
                'conditions' => array('MovieStarLine.movie_star_id = MovieStar.id',
                            'MovieStarLine.id = (SELECT id FROM "public"."movie_star_lines" AS "MovieStarLine" WHERE movie_star_id = MovieStar.id ORDER BY status_date DESC NULLS LAST, id DESC LIMIT 1)'  // Get only most recent line     
                        ),
                'order' => array( 'MovieStarLine.status_date' => 'DESC  NULLS LAST')    
            ),
            'MovieStarStatus' => array(
                'foreignKey' => false,
                'conditions' => array('MovieStarLine.movie_star_status_id = MovieStarStatus.id'),
            ),
        ),
    ));

    $this->MovieStar->contain(array(
        'Movie', 
        'MovieStarLine' => array('MovieStarStatus'), 
        'MovieStarType', 
        'MovieStarRecurrance', 
        'User', 
        'MovieStarStatus'
    ));


    // This is where the search filter occurs
    $this->Prg->commonProcess();
    $this->paginate = array( 'conditions' => $this->MovieStar->parseCriteria($this->Prg->parsedParams()), 'limit' => 100);
    $movieStars = $this->paginate();
    $this->set(compact('movieStars'));

}

The problem is when I try to search by parent_user_id or initials, I get an ERROR: missing FROM-clause entry for table "User".

It seems like the dynamic binding doesn't work. I have to remove Movie from belongsTo

Model:

public $belongsTo = array(

    //'Movie' => array(
    //  'className' => 'Movie',
    //  'foreignKey' => 'movie_id',
    //  'conditions' => '',
    //  'fields' => '',
    //  'order' => ''
    //),
    'MovieStarRecurrance' => array(
        'className' => 'MovieStarRecurrance',
        'foreignKey' => 'movie_star_recurrance_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
    'MovieStarType' => array(
        'className' => 'MovieStarType',
        'foreignKey' => 'movie_star_type_id',
        'conditions' => '',
        'fields' => '',
        'order' => ''
    ),
);

and add hasOne for Movie and User for the search to work.

public $hasOne = array(
    'Movie' => array(
                'foreignKey' => false,
                'conditions' => array('Movie.id = MovieStar.movie_id'),
                'fields' => array('Movie.id', 'Movie.movie_id', 'Movie.user_id', 'Movie.movie_mid', 'Movie.movie_dba')
            ),
    'User' => array(
                'foreignKey' => false,
                'conditions' => array('Movie.user_id = User.id'),
                'fields' => array('User.id', 'User.initials', 'User.user_first_name', 'User.user_last_name', 'User.name', 'User.parent_user_id', 'User.secondary_parent_user_id')
            ),
    'MovieStarLine' => array(
                'foreignKey' => false,
                'conditions' => array('MovieStarLine.movie_star_id = MovieStar.id',
                            'MovieStarLine.id = (SELECT id FROM "public"."movie_star_lines" AS "MovieStarLine" WHERE movie_star_id = MovieStar.id ORDER BY status_date DESC NULLS LAST, id DESC LIMIT 1)'  // Get only most recent line     
                        ),
                //'order' => array( 'MovieStarLine.status_date' => 'DESC  NULLS LAST')  
            ),
);

I can't do this though because it breaks all of my save and edit functionality. Does anyone know how to properly rebind the associations?

##################### UPDATE

I found a partial solution that seemingly gets me past the User model not showing up.

"Passing false as a second parameter of your Model::bindModel call. This will make your on-the-fly binding last the duration of the request." from this answer..

This might have fixed my bindings, still not sure because now I have an error with count and group by.

ERROR: column "MovieStarLine.status_date" must appear in the GROUP BY clause or be used in an aggregate

SQL Query: SELECT COUNT(*) AS "count"

$this->MovieStar->unbindModel( array(
'belongsTo' => array('Movie')
    ), false
);

// MovieStarStatus to be top level json element
$this->MovieStar->bindModel( array(
    'hasOne' => array(
        'Movie' => array(
            'foreignKey' => false,
            'conditions' => array('Movie.id = MovieStar.movie_id'),
            'fields' => array('Movie.id', 'Movie.movie_id', 'Movie.user_id', 'Movie.movie_mid', 'Movie.movie_dba')
        ),
        'User' => array(
            'foreignKey' => false,
            'conditions' => array('Movie.user_id = User.id'),
            'fields' => array('User.id', 'User.initials', 'User.user_first_name', 'User.user_last_name', 'User.name', 'User.parent_user_id', 'User.secondary_parent_user_id')
        ),
        'MovieStarLine' => array(
            'foreignKey' => false,
            'conditions' => array('MovieStarLine.movie_star_id = MovieStar.id',
                        'MovieStarLine.id = (SELECT id FROM "public"."movie_star_lines" AS "MovieStarLine" WHERE movie_star_id = MovieStar.id ORDER BY status_date DESC NULLS LAST, id DESC LIMIT 1)'  // Get only most recent line     
                    ),
            'order' => array( 'MovieStarLine.status_date' => 'DESC  NULLS LAST')    
        ),
        'MovieStarStatus' => array(
            'foreignKey' => false,
            'conditions' => array('MovieStarLine.movie_star_status_id = MovieStarStatus.id'),
        ),
    ),
), false);
Community
  • 1
  • 1
Bryan
  • 17,201
  • 24
  • 97
  • 123

0 Answers0