Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/246.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在cakephp 3中按嵌套关联对查询结果排序 问题是:_Php_Sorting_Cakephp_Associations_Cakephp 3.x - Fatal编程技术网

在cakephp 3中按嵌套关联对查询结果排序 问题是:

在cakephp 3中按嵌套关联对查询结果排序 问题是:,php,sorting,cakephp,associations,cakephp-3.x,Php,Sorting,Cakephp,Associations,Cakephp 3.x,我有一个cakephp 3.x查询对象,它有两个嵌套的关联,Organizations.Positions.Skills,它被设置为一个视图变量,$Organizations。我试图按照第一个嵌套关联中的列对查询结果的顶级数组进行排序。也就是说,我想按位置中的列对$Organizations进行排序,特别是位置.end) 型号信息 组织有许多职位 职位有很多技能 我做的研究 订单选项 根据需要,find()有一个顺序选项:find()->order(['field'])或查找('all',['o

我有一个cakephp 3.x查询对象,它有两个嵌套的关联,
Organizations.Positions.Skills
,它被设置为一个视图变量,
$Organizations
。我试图按照第一个嵌套关联中的列对查询结果的顶级数组进行排序。也就是说,我想按
位置中的列对
$Organizations
进行排序,特别是
位置.end

型号信息 组织有许多职位

职位有很多技能

我做的研究 订单选项 根据需要,find()有一个顺序选项:
find()->order(['field'])
查找('all',['order'=>'field DESC'])
但是,这仅适用于正在调用的表find()中的字段。在这种情况下,组织。例如,这就是它的典型使用方式

//This works.
//Sorts Organizations by the name of the organization in DESC.
$this->loadModel('Organizations');
$this->set('Organizations',
        $this->Organizations->find('all')
        ->contain([ //eager loading
            'Positions.Skills'
         ])
        ->order(['organization DESC'])
);
但是,尝试将其用于嵌套关联不起作用:

$this->set('Organizations',
  this->Organizations->find(...)
    ->contain(...)
    ->order(['Organizations.Positions.ended DESC'])
);

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Organizations.Positions.ended' in 'order clause'
将其更改为引用将嵌套的字段也不起作用:

//also doesn't work.
$this->set('Organizations',
  $this->Organizations->find(...)
    ->contain(...)
    ->order([Positions.ended DESC])
);

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Positions.ended' in 'order clause'
在这两种情况下,sql错误都是在cakephp执行查询生成的PDO语句时创建的

排序选项 类似地,根据,即时加载/关联具有“排序”选项: $this->loadModel(“组织”)

但是,这只是对嵌套的关联进行排序,特别是对嵌套的关联进行排序。它不会按照嵌套关联(一种多维排序)对整个结果集进行排序

例如:

组织C(组织id 1)有两个职位:

  • 立场5。截至2012年
  • 立场4。截至2014年
  • 组织B(组织id 2)有两个职位:

  • 截至2013年的职位3
  • 截至2015年的职位2
  • 上述代码和数据导致在计算查询时生成以下数组:

    Organizations => [
      0 => [
        'organization' => 'Organization A',
        positions => [
          0 => [
            'position' => 'Position 1',
            'ended' => '2016'
          ]
        ]
      ],
      1 => [
        'organization' => 'Organization C',
        'positions' => [
          0 => [
            'position' => 'Position 4',
            'ended' => '2014'
          ],
          1 => [
            'position' => 'Position 5',
            'ended' => '2012'
          ]
        ]
      ],
      2 => [
        'organization' => 'Organization B',
        'positions' => [
          0 => [
            'position' => 'Position 2',
            'ended' => '2015'
          ],
          1 => [
            'position' => 'Position 3',
            'ended' => '2013'
          ]
        ]
      ]
    ]
    
    其他研究 同样,在我的研究中也出现了以下问题:

    http://stackoverflow.com/questions/26859700/cakephp-order-not-working
    
    http://stackoverflow.com/questions/17670986/order-by-doesnt-work-with-custom-model-find-while-paginating
    
    http://stackoverflow.com/questions/18958410/cakephp-paginate-and-sort-2nd-level-association
    
    http://stackoverflow.com/questions/34705257/cakephp-paginate-and-sort-hasmany-association 
    
    此外,我知道PHP有自己的排序函数,如
    sort()
    multisort()
    ;但是,只有在查询(由foreach)求值后才能调用这些函数。或者,调用$organization->toArray()然后使用multisort;但是,这必须在视图中完成,这将打破MVC分离关注点的惯例(数据和查询由控制器和模型操纵,而不是视图!),而且效率非常低,因为在加载页面时会调用它

    那么,我如何按照嵌套关联对cakephp查询进行排序? 或者,更简单地说,如何对查询进行排序,以便在求值时生成以下数组:

    Organizations => [
      0 => [
        'organization' => 'Organization A',
        'positions' => [
          0 => [
            'position' => 'Position 1',
            'ended' => '2016'
          ]
        ]
      ],
      0 => [
        'organization' => 'Organization B',
        'positions' => [
          0 => [
            'position' => 'Position 2',
            'ended' => '2015'
          ],
          1 => [
            'position' => 'Position 3',
            'ended' => '2013'
          ]
        ]
      ],
      1 => [
        'organization => 'Organization C',
        'positions' => [
          0 => [
            'position' => 'Position 4',
            'ended' => '2014'
           ],
          1 => [
            'position' => 'Position 5',
            'ended' => '2012'
          ]
        ]
      ]
    ]
    
    背景与背景: 我正在用cakephp 3.2为自己建立一个[portfolio网站][7],以展示我的web开发技能,并帮助我寻找开发职业。对于我的简历页面,我正在用嵌套的手风琴组织大量数据,以模仿招聘人员期望在实际简历上看到的简历风格。因此,我的观点是:

  • 循环通过顶级视图变量(组织)
  • 呈现组织详细信息
  • 通过该组织的职位循环(仍在1内)
  • 呈现职位详细信息
  • 循环介绍该职位的相关技能
  • 使用适当的链接呈现每个技能,以按该技能过滤

  • 列表项

    仅通过主查询上的联接检索
    hasOne
    belongsTo
    关联<代码>有许多关联在单独的查询中被检索,因此当您尝试引用
    位置的字段时会出现错误

    在SQL级别和PHP级别上,您想要的应该是相当容易解决的

    SQL级别 在SQL级别,您可以加入
    位置
    ,并按计算的
    max(Positions.end)
    列排序,如:

    $this->Organizations
        ->find('all')
        ->select(['max_ended' => $this->Organizations->query()->func()->max('Positions.ended')])
        ->select($this->Organizations)
        ->contain([
            'Positions.Skills',
            'Positions' => [
                'sort' => ['Positions.ended' => 'DESC']
            ]
        ])
        ->leftJoinWith('Positions')
        ->order([
            'max_ended' => 'DESC'
        ])
        ->group('Organizations.id');
    
    这就是你想要的结果。查询将类似于:

    $Organizations->map(function ($organization) {
        $organization['positions'] =
            collection($organization['positions'])->sortBy('ended')->toList();
        return $organization;
    });
    $sorted = $sorted->sortBy(function ($organization) {
        return
            isset($organization['positions'][0]['ended']) ?
                $organization['positions'][0]['ended'] : 0;
    });
    
    选择
    最大值(位置结束)与最大值结束时相同,
    ... 
    从…起
    组织机构
    左连接
    职位
    在组织上。id=(
    职位.组织机构id
    )   
    分组
    组织id
    订购人
    最大结束描述
    
    PHP级别 在PHP级别上,使用集合也很容易解决问题(请注意,查询是集合,有点像),但是只有当您打算检索所有行,或者出于任何原因必须处理一组无序行时,才有意义。。。比如:

    $Organizations->map(function ($organization) {
        $organization['positions'] =
            collection($organization['positions'])->sortBy('ended')->toList();
        return $organization;
    });
    $sorted = $sorted->sortBy(function ($organization) {
        return
            isset($organization['positions'][0]['ended']) ?
                $organization['positions'][0]['ended'] : 0;
    });
    
    这也可以在结果格式化程序中实现,所以如果您坚持的话,事情会发生在控制器或模型级别

    $query->formatResults(function ($results) {
        /* @var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
        $results = $results->map(function ($row) {
            $row['positions'] =
                collection($row['positions'])->sortBy('ended')->toList();
            return $row;
        });
        return $results->sortBy(function ($row) {
            return isset($row['positions'][0]['ended']) ?
                $row['positions'][0]['ended'] : 0;
        });
    });
    
    看见
      • 这对我来说很有效:

        $this->Organizations->find('all')
        ->contain(['Positions' => ['sort' => ['Positions.ended' => 'DESC']]])
        ->contain('Postions.Skills');
        
        $this->Organizations->find('all')
        ->contain(['Positions' => ['sort' => ['Positions.ended' => 'DESC']]])
        ->contain('Postions.Skills');