问题
I have the following related table objects:
SettingsTable
belongsTo SettingsHeadersTable
SettingsHeadersTable
hasMany SettingsTable
SettingsOptionsTable
belongsTo SettingsTable
SettingsTable
hasMany SettingsOptionsTable
For example:
- There is a header titled "General Site Settings".
- There is a setting under that header titled "Offline Status".
- There are 3 options under that setting for "Online", "Offline (restricted)" on "Offline (unrestricted)"
I have a controller that I would like to find all of the headers, contain all of the settings under those headers and further contain all of the options under those settings. Then in my view I can loop through each setting, divided into sections by header, and display the corresponding options for each setting for the admin to update.
Below, my original query shows exactly what is describe above, however, it is showing headers even if they have 0 visible settings. I want to hide the headers that have 0 visible settings.
$settings_headers = $this->Settings->SettingsHeaders->find()
->order([
'SettingsHeaders.number' => 'ASC'
])
->where([
'SettingsHeaders.module_id' => 1
])
->contain([
'Settings' => function ($q) {
return $q
->order(['Settings.number' => 'ASC'])
->where([
'Settings.hide' => 0
])
->contain([
'SettingsOptions' => function ($q) {
return $q
->order(['SettingsOptions.number' => 'ASC']);
}
]);
}
])
->toArray();
I made some tweaks and got to the headers with only visible settings to show along with their corresponding settings, but the options are not showing. I'm still very confused on contain vs matching. I'm not sure if the code I've written is redundant, I've been trying to follow example I've seen online.
$settings_headers = $this->Settings->SettingsHeaders->find()
->order([
'SettingsHeaders.number' => 'ASC'
])
->where([
'SettingsHeaders.module_id' => 1
])
->select([
'SettingsHeaders.id',
'SettingsHeaders.title',
'SettingsHeaders.number',
'SettingsHeaders.module_id',
'settings_count' => 'COUNT(Settings.id)',
])
->select($this->Settings)
->group('SettingsHeaders.id')
->contain([
'Settings' => function ($q) {
return $q
->order(['Settings.number' => 'ASC'])
->where([
'Settings.hide' => 0 // ONLY SHOW VISIBLE SETTINGS
])
->contain([
'SettingsOptions' => function ($q) {
return $q
->order(['SettingsOptions.number' => 'ASC']);
}
]);
}
])
->matching('Settings', function($q) {
return $q->where([
'Settings.hide' => 0 // ONLY COUNT THE VISIBLE SETTINGS
]);
})
->toArray();
I'm not quite sure how to put it all together (only showing the headers with visible options, and also containing all of the data in both Settings and SettingsOptions)
回答1:
Actually, I just figured this out. I had to remove the following line from my second example:
->select($this->Settings)
来源:https://stackoverflow.com/questions/33507686/cakephp-3-contain-deep-associated-model-with-count