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 isinternet_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
FROMradacct
ASRadacct
WHEREInternetAccessCode
.code
=Radacct
.username
ANDInternetAccessCode
.fk_ship_id
=Radacct
.fk_ship_id
ANDRadacct
.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.
精彩评论