【问题标题】:CakePHP3 filtering based on custom rulesCakePHP3 基于自定义规则的过滤
【发布时间】:2017-02-25 18:38:05
【问题描述】:

我有以下架构:

用户 hasMany 注册状态 RegistrationState belongsTo 用户

到其经典的 1->M 关系,其中 user_id 在 RegistrationState 表中。

RegistrationState 具有以下属性

id, user_id, state, created_at ... ( others are not relevant )

用户可以有更多的注册状态,例如:

Registration state -> 1, created -> 01-02-2017
Registration state -> 2, created -> 01-03-2017
Registration state -> 3, created -> 01-04-2017
Registration state -> 4, created -> 01-05-2017
Registration state -> 2, created -> 01-06-2017
Registration state -> 3, created -> 01-07-2017

我需要根据这个“状态属性”进行过滤,其中有效状态是最后一个创建的状态。

此示例的有效状态为 3,因为它的最新状态。

现在,我有了控制器和 index 方法

    // push custom query for filtering to finder method
    $this->paginate['finder'] = [
        'clients' => ['q' => $this->request->query]
    ];

    try {
        $clients = $this->paginate( $this->Users );
    } catch (\Exception $e) {
        // redirect on main
        return $this->redirect($this->here);
    }

我的 finder 方法如下所示

public function findClients($query, array $options)
{
    $opts = $query->getOptions()['q'];

    if (!empty($opts['email'])) {
        $query->andWhere(['email LIKE' => '%' . trim($opts['email']) . '%']);
    }

    if (!empty($opts['identity_num'])) {
        $cn = $opts['identity_num'];
        $query->matching('Identities', function ($query) use ($cn) {
            $query->andWhere(['Identities.number' => $cn]);
        });
    }

    // registration state
    if (!empty($opts['reg_state'])) {
        // WHAT SHOULD BE HERE???
    }

    return $query;
}

还有另一个 1->M 关系用户 -> 身份,但是(匹配方法)但它工作正常,因为数字总是唯一的。

我无法解决注册状态的问题,如何在 CakePHP3 中实现这种搜索? (我不想打破分页,所以我想在finder方法中解决这个问题)

【问题讨论】:

  • 您想将状态传递给查询并根据最新的关联状态(与任何关联状态相比)是否与提供的值匹配来过滤用户?这听起来像是greatest-n-per-group 问题,类似于this,但有一个额外的条件。现在没时间详细回答,抱歉。
  • @ndm 感谢您的回复。你说得对,this 非常有用,但我无法实现它,因为我会破坏现有代码:/ 我已经用子查询解决了它

标签: orm cakephp-3.0 relationship greatest-n-per-group


【解决方案1】:

子查询(RegistrationState 上的 INNER JOIN)是一种可能的(肮脏的?)解决方案

    // registration state
    if (!empty($opts['reg_state'])) {

        $conn = ConnectionManager::get('default');


        $subquery = $conn->execute(
                'SELECT uir.user_id ' .
                'FROM registration_state uir ' .
                'INNER JOIN ( ' . 
                    'SELECT user_id, max(created) as m_created ' .
                    'FROM registration_state ' .
                    'GROUP BY user_id ' .
                ') muir ON uir.user_id = muir.user_id AND uir.created = muir.m_created AND uir.status = '
                . intval( $opts['reg_state'])
        );

        $usersInStateIds = [];
        // transform result of subquery to usable array
        foreach( $subquery->fetchAll('assoc') as $r ) {
            $usersInStateIds[] = intval( $r['user_id'] );
        }
        $query->matching('RegistrationState', function ($query) use ($usersInStateIds) {
            return $query->andWhere(['RegistrationState.user_id IN' => $usersInStateIds]);
        });
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2022-08-14
    • 2017-03-24
    • 1970-01-01
    • 2019-11-15
    • 2020-02-25
    • 2016-03-12
    相关资源
    最近更新 更多