CakePHP 3: Contain Deep Associated Model with COUNT()

邮差的信 提交于 2019-12-23 04:52:20

问题


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

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