CakePHP 1.3 - Unknown column in where clause

淺唱寂寞╮ 提交于 2019-12-19 16:52:14

问题


I'm working on an already existing cakephp 1.3 project and I needed to add a new table to the database. I have this in my controller:

    $conditions = array('ShootingPlacement.person_id' => $id, 'Email.person_id' => $id, 'Email.shooting_placement_id' => 'ShootingPlacement.id');
    $shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions'));

And it's giving me this error:

  Warning (512): SQL Error: 1054: Unknown column 'Email.person_id' in 'where clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 684]

And ths is the query it's trying to create:

 SELECT `ShootingPlacement`.`id`, ... FROM `shooting_placements` AS `ShootingPlacement` 
 LEFT JOIN `people` AS `Person` ON (`ShootingPlacement`.`person_id` = `Person`.`id`) 
 LEFT JOIN `shootings` AS `Shooting` ON (`ShootingPlacement`.`shooting_id` = `Shooting`.`id`)  
 WHERE `ShootingPlacement`.`person_id` = 123688 AND `Email`.`person_id` = 123688 AND `Email`.`shooting_placement_id` = 'ShootingPlacement.id'   
 ORDER BY `lastname` ASC  

Obviously my controller code is wrong, but I'm not sure how to relate the Email table to the ShootingPlacement one. I think my models are correct. So far if I have this:

    $conditions = array('ShootingPlacement.person_id' => $id);
    $shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions'));

It will retrieve the rows from Shooting, ShootingPlacement and Person, I want Email to be there too. Email has 2 foreign keys: one from ShootinPlacement and one from Person.

These are the models, the only one I created is Email, the rest where working correctly.

class Email extends AppModel
{
    var $name = 'Email';


    var $belongsTo = array
    (
        'Person' => array
        (
            'className' => 'Person',
            'foreignKey' => 'person_id'
        ),
        'ShootingPlacement' => array
        (
            'className' => 'ShootingPlacement',
            'foreignKey' => 'shooting_placement_id'
        )
    );
}

class ShootingPlacement extends AppModel
{
    var $name = 'ShootingPlacement';


    var $belongsTo = array
    (
        'Person' => array
        (
            'className' => 'Person',
            'foreignKey' => 'person_id',
            'order' => 'lastname ASC'
        ),
        'Shooting' => array
        (
            'className' => 'Shooting',
            'foreignKey' => 'shooting_id'
        )
    );
}

class Person extends AppModel
{
    var $name = 'Person';

    var $belongsTo = array
    (
        'PersonOrigin' => array
        (
            'className' => 'PersonOrigin',
            'foreignKey' => 'person_origin_id'
        )
    );

    var $hasMany = array
    (
        'ShootingPlacement' => array
        (
            'className' => 'ShootingPlacement',
            'foreignKey' => 'person_id',
            'dependent' => false
        )
    );
}
class Shooting extends AppModel
{
    var $name = 'Shooting';

    var $belongsTo = array
    (
        'ShootingLocation' => array
        (
            'className' => 'ShootingLocation',
            'foreignKey' => 'shooting_location_id'
        ),
        'Emission' => array
        (
            'className' => 'Emission',
            'foreignKey' => 'emission_id'
        )
    );
}

What I need on the view is to loop through the ShootingPlacement variable and I need it to contain the Email table data for that specific id of ShootingPlacement and Person (As you see in the query, Person and ShootingPlacement are in a relationship already, I only need there to be Email too)


回答1:


You should be very careful with the relationship you're after. From a quick glance at some of these answers, they seem to suggest you simply add a join to the Email model into your Person model and rely on the conditions of your find to ensure your query doesn't ransack your server's memory.

I'm going to assume that first of all, you want this Email relationship to be implicit in all your queries on Person, otherwise you could simply specify the join on each query you wanted it for. In this case, you definitely want to link it using model relationships.

Your code shows that Shooting and ShootingPlacement (presume this is a model to model mapping relationship) both belong to two models. Incidentally, Shooting belongsTo Emission - which we haven't seen here yet. I assume this isn't applicable to the current scenario.

Now, let's assume off the bad that because your Email table has foreign keys, it will be a hasOne relationship, rather than a hasMany - so that's what you need to link it by. I'm going to link it to the ShootingPlacement model because this is the model you are querying, so it should be the central point at which models are joined around it. Structure wise, because everything seems to originate from your Person model, I would have to suggest you query that model instead. But the way it's set up so far will allow you to query from nearly anywhere and still retrieve mostly the same results bar a few model names and table aliases.

Purely because your foreign key between Email and ShootingPlacement has a different name, and CakePHP 1.3 doesn't handle this very well, I'm also going to suggest you don't use a foreign key, instead putting it into the relationship as conditions.

class ShootingPlacement extends AppModel
{
    var $name = 'ShootingPlacement';
    var $actsAs = array('Containable');

    var $hasOne = array(
        'Email' => array(
            'className' => 'Email',
            'foreignKey' => false,
            'conditions' => array(
                'Email.shooting_placement_id = ShootingPlacement.id',
                'Email.person_id = ShootingPlacement.person_id'
            )
        )
    );

    var $belongsTo = array (
        'Person' => array (
            'className' => 'Person',
            'foreignKey' => 'person_id',
            'order' => 'lastname ASC'
        ),
        'Shooting' => array (
            'className' => 'Shooting',
            'foreignKey' => 'shooting_id'
        )
    );
}

I've also added the containable behaviour in there. This allows you to control from each query which associated models you'd like to return with your primary model results. It will default to all, but can be handy when you only want something specific and/or for memory reasons (these kinds of queries can destroy your server memory pretty quickly if you don't limit them or specify only the field names you want to return).

Now when you create your Email model, I wouldn't suggest complicating this mess of entangled models any further by linking it back to ShootingPlacement again. As you've said, it also has a foreign key to the Person model. So you might want to do exactly the same thing as above for your Person model (changing the conditions to reflect the Person foreign key of course). This way your model is a little more flexible; it will still join to ShootingPlacement and Person, and will also allow you to query it seperately if required without the other associated models.

Documentation

  • CakePHP 1.3 Model Associations
  • CakePHP 1.3 Containable Behaviour

See also

  • This article on Stack



回答2:


In your model add containable behavior

class Email extends AppModel {
    var $name = 'Email';

    var $actsAs = array('Containable');

    var $belongsTo = array
    (
        'Person' => array
        (
            'className' => 'Person',
            'foreignKey' => 'person_id'
        ),
        'ShootingPlacement' => array
        (
            'className' => 'ShootingPlacement',
            'foreignKey' => 'shooting_placement_id'
        )
    );
}

Just write the below code in your controller.

$this->ShootingPlacement->recursive = 2;
$this->ShootingPlacement->contain = array(
    'Shooting',
    'Person' => array(
        'Email'
    )
);
$conditions = array(
  'ShootingPlacement.person_id' => $id,
  'Email.shooting_placement_id' => 'ShootingPlacement.id'
);
$shootingPlacements = $this->ShootingPlacement->find('all', compact('conditions'));

Hope this helps you.




回答3:


Add a $hasOne relation to Person model with Email like below

var $hasOne = array(
    'Email' => array(
             'className' => 'Email',
             'foreignKey' => 'person_id' // Column defined for person ids in Email table
             )
);

Then add

$this->ShootingPlacement->recursive = 2;

OR you can simply use joins in cakephp to join email model. Refer cakephp joining tables




回答4:


You need to link your model ShootingPlacement with "Email" with which you call it.

class ShootingPlacement extends AppModel

var $name = 'Shooting';

var $hasMany= array
(
    'Email' => array
    (
        'className' => 'Email',
        'foreignKey' => 'yourfk'
    ),
   );
}

And uses it s very powerful ContainableBehavior !

exemple :

$contain=array('Email'=>array('fields'=>array('id','...')));
$conditions=array('ShootingPlacement.id'=>$yourId);
$this->ShootingPlacement->attachBehaviros('Containable');
$this->ShootingPlacement->find('all',$conditions);// your will retrieve yoru SHootingItem + Emails linked 



回答5:


This would provide the required join:

$conditions = array('ShootingPlacement.person_id' => $id, 'Email.person_id' => $id, 'Email.shooting_placement_id' => 'ShootingPlacement.id');

$joins = array(
   array(
    'table' => 'emails', 
    'alias' => 'Email', 
    'type' => 'LEFT', 
    'conditions' => array('Email.shooting_placement_id = ShootingPlacement.id')
  )
); 



$shootingPlacements = $this->ShootingPlacement->find('all', 
   array(
      'conditions' => $conditions,
      'joins' => $joins
   )
);


来源:https://stackoverflow.com/questions/20262620/cakephp-1-3-unknown-column-in-where-clause

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!