开发者

CakePHP $hasMany not pulling the data from the $belongsTo model. Join is not created

I have two tables: internet_access_codes and radacct.

The internet_access_codes hasMany radacct records.

The join is internet_access_codes.code = radacct.username AND internet_access_codes.fk_ship_id = radacct.fk_ship_id

I created 2 models and wanted to use $hasMany and $belongsTo respectively so that the related radacct records would be pulled when getting and internet_access_codes record.

Here's the code:

class InternetAccessCode extends AppModel{
var $name = 'InternetAccessCode';
var $hasMany = array(
    'Radacct' => array(
        'className' => 'Radacct',
        'foreignKey'=> false,
        'conditions'=> array(
            'InternetAccessCode.code = Radacct.username',
            'InternetAccessCode.fk_ship_id = Radacct.fk_ship_id'
        ),
    )
);

}

class Radacct extends AppModel{
var $name = 'Radacct';
var $useTable = 'radacct';

var $belongsTo = array(
    'InternetAccessCode' => array(
        'className' => 'InternetAccessCode',
        'foreignKey' => false,
        'conditions'=> array(
            'InternetAccessCode.code = Radacct.username',
            'InternetAccessCode.fk_ship_id = Radacct.fk_ship_id'
        )
    ),
);

}

When I find() a record from internet_access_codes I expect it to give me all the relevant radacct records as well. However I got an error because it didnt开发者_如何学运维 do the join.

Here's the outcome and error:

Array
(
    [InternetAccessCode] => Array
        (
            [id] => 1
            [code] => 1344444440
            [bandwidth_allowed] => 20000
            [time_allowed] => 30000
            [expires_at] => 31536000
            [cost_price] => 0.00
            [sell_price] => 0.00
            [enabled] => 1
            [deleted] => 0
            [deleted_date] => 
            [fk_ship_id] => 1
            [downloaded_at] => 2011-09-10 22:18:14
        )

    [Radacct] => Array
        (
        )

)

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

Query: SELECT Radacct.id, Radacct.fk_ship_id, Radacct.radacctid, Radacct.acctsessionid, Radacct.acctuniqueid, Radacct.username, Radacct.groupname, Radacct.realm, Radacct.nasipaddress, Radacct.nasportid, Radacct.nasporttype, Radacct.acctstarttime, Radacct.acctstoptime, Radacct.acctsessiontime, Radacct.acctauthentic, Radacct.connectinfo_start, Radacct.connectinfo_stop, Radacct.acctinputoctets, Radacct.acctoutputoctets, Radacct.calledstationid, Radacct.callingstationid, Radacct.acctterminatecause, Radacct.servicetype, Radacct.framedprotocol, Radacct.framedipaddress, Radacct.acctstartdelay, Radacct.acctstopdelay, Radacct.xascendsessionsvrkey FROM radacct AS Radacct WHERE InternetAccessCode.code = Radacct.username AND InternetAccessCode.fk_ship_id = Radacct.fk_ship_id AND Radacct.deleted <> 1

In the app_model I also added the containable behaviour just in case but it made no difference.


Sadly cakephp doesn't work too well with the associations with foreign key =false and conditions. Conditions in associations are expected to be things like Model.field = 1 or any other constant.

The has many association first find all the current model results, then it finds all the other model results that have the current model results foreignKey... meaning it does 2 queries. If you put the conditions it will try to do it anyway but since it didn't do a join your query will not find a column of another table.

Solution

use joins instead of contain or association to force the join you can find more here

an example of how to use join

$options['joins'] = array(
    array(
        'table' => 'channels',
        'alias' => 'Channel',
        'type' => 'LEFT',
        'conditions' => array(
            'Channel.id = Item.channel_id',
        )
    ));
$this->Model->find('all', $options);

Possible solution #2

BelongsTo perform automatic joins (not always) and you could do a find from radaact, the bad thing of this solution, is that it will list all radacct and put its internetAccesCode asociated instead of the internetAccesCode and all the radaact associated.... The join solution will give you something similar though...

You will need to do a nice foreach that organizes your results :S it won't be to hard though....

Hope this solves your problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜