我的cakephp应用程序(2.2)应用程序具有以下内容:
NewsArticle HMBTM NewsCategory
NewsCategory HMBTM NewsArticle
在我的新闻文章中,控制器功能索引()我试图获得一个新闻类别为2的新闻文章的分页列表。
继承我的代码(这是错误的):
$this->paginate = array(
'conditions' => array('newsArticle.news_category_id = 2'),
'limit' => 10,
'order' => array(
'newsArticle.modified' => 'asc'
)
);
$this->set('newsArticles', $this->paginate());
有人能告诉我哪里出错了吗?我猜这与联接表有关。
这是我得到的错误:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'newsArticle.news_category_id' in 'where clause'
这是它产生的SQL:
SQL查询:
SELECT
`NewsArticle`.`id`,
`NewsArticle`.`title`,
`NewsArticle`.`brief`,
`NewsArticle`.`body`,
`NewsArticle`.`filename`,
`NewsArticle`.`dir`,
`NewsArticle`.`mimetype`,
`NewsArticle`.`filesize`,
`NewsArticle`.`live`,
`NewsArticle`.`user_id`,
`NewsArticle`.`created`,
`NewsArticle`.`modified`,
`User`.`id`,
`User`.`username`,
`User`.`password`,
`User`.`forename`,
`User`.`surname`,
`User`.`company`,
`User`.`position`,
`User`.`role`,
`User`.`version_numbers_id`,
`User`.`support_case_reference`,
`User`.`support_web_password`,
`User`.`webforms_email`,
`User`.`tech_email`,
`User`.`group_id`,
`User`.`user_status_id`,
`User`.`view_uat`,
`User`.`manuals`,
`User`.`filename`,
`User`.`dir`,
`User`.`mimetype`,
`User`.`filesize`,
`User`.`created`,
`User`.`modified`,
`User`.`live`,
`User`.`tokenhash`
FROM `cakeclientarea`.`news_articles` AS `NewsArticle`
LEFT JOIN `cakeclientarea`.`users` AS `User`
ON (`NewsArticle`.`user_id` = `User`.`id`)
WHERE
`newsArticle`.`news_category_id` = 2
ORDER BY
`newsArticle`.`modified` asc
LIMIT 10
我可以从中看到它甚至没有触及连接表news_articles_news_categories。
任何人都可以提供帮助,当然这很简单吗?我错过了什么?提前谢谢。
答案 0 :(得分:2)
适用于CakePHP 2。3。4(2013年6月)
麻烦在于Controller / Component / PaginatorComponent.php
函数validateSort()返回错误的订单行,因为它被设置为仅返回同一Model中属性的顺序。正如文档在validateSort上所述
只能对字段或虚拟字段进行排序。
解决这个问题:
在Controller代码中(以用户控制器为例):
public $components = array(
'Paginator' => array(
'className' => 'JoinedPaginator'),
);
在功能中:
$this->paginate = array(
'recursive'=>-1, // should be used with joins
'joins'=>array(
array(
'table'=>'groups',
'type'=>'inner',
'alias'=>'Group',
'conditions'=>array('User.group_id = Group.id')
)
)
)
$fields = array('User.name', 'User.id', 'Group.name');
$users = $this->paginate('User', array(), $fields);
paginate函数中的第三个参数是白名单,通常只有当前对象中的项目,但我们添加了所有列出白名单的对象。
重写Paginator,制作Component / JoinedPaginator.php
<?php
App::uses('PaginatorComponent', 'Controller/Component');
class JoinedPaginatorComponent extends PaginatorComponent {
public $Controller;
function startup(Controller $controller) {
$this->Controller = $controller;
}
public function validateSort(Model $object, array $options, array $whitelist = array()) {
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
if (!in_array($direction, array('asc', 'desc'))) {
$direction = 'asc';
}
$options['order'] = array($options['sort'] => $direction);
}
if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) {
$field = key($options['order']);
if (!in_array($field, $whitelist)) {
$options['order'] = null;
return $options;
}
}
if (!empty($options['order']) && is_array($options['order'])) {
$order = array();
foreach ($options['order'] as $key => $value) {
$field = $key;
$alias = $object->alias;
if (strpos($key, '.') !== false) {
list($alias, $field) = explode('.', $key);
}
// Changed the order field list, to include items in join tables
if (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
$order[$alias . '.' . $field] = $value;
} else if(in_array($alias.'.'.$field, $whitelist)){
// Adding a white list order, to include items in the white list
$order[$alias . '.' . $field] = $value;
} else if ($object->hasField($field)) {
$order[$object->alias . '.' . $field] = $value;
} elseif ($object->hasField($key, true)) {
$order[$field] = $value;
}
}
$options['order'] = $order;
}
return $options;
}
public function paginate($object = null, $scope = array(), $whitelist = array()) {
$this->settings = am ($this->Controller->paginate, $this->settings);
return parent::paginate($object, $scope, $whitelist );
}
}
如您所见,设置未发送到新的paginate对象,因此我也会覆盖paginate函数,只是为了收集设置。
这可让您在JOINED表上订购。
答案 1 :(得分:0)
'conditions' => array('newsArticle.news_category_id = 2')
shoule be:
'conditions' => array('newsArticle.news_category_id'=>'2')
这与错误并不匹配,但没有其他任何东西真正突出。
您可以尝试以不同的方式接近它,以确保不是您的模型关系导致错误。
$this->paginate('NewsArticle');
$this->paginate['NewsArticle']['conditions'] = array('newsArticle.news_category_id'=>'2');
pr($this->paginate);
答案 2 :(得分:0)
您还可以将您的功能切换到NewsCategory控制器,使用可包含并以这种方式对结果进行分页。此链接提供了有关如何使其正常工作的良好示例http://www.24100.net/2012/07/cakephp-hasandbelongstomany-relationship-queries-demystified/
答案 3 :(得分:0)
我花了两天的时间寻找cakephp多重连接条件和分页的解决方案。无法找到任何解决方案,因此想到将我的解决方案发布到具有多个连接和条件的分页。希望这对某人来说会派上用场。
public function index(){
$data = $this->request->data;
$searchText ='';
if($this->request->is("post")) {
$url = array('action'=>'index');
$filters = array();
echo("hello hello helloa");
echo ($this->request->data);
if(isset($data['Skinauditreport']['searchText']) && $data['Skinauditreport']['searchText']){
echo ($data['Skinauditreport']['searchText']);
//maybe clean up user input here??? or urlencode??
$filters['searchText'] = $data['Skinauditreport']['searchText'];
}
//redirect user to the index page including the selected filters
$this->redirect(array_merge($url,$filters));
}
$this->Skinauditreport->recursive = 1;
//Joining 2 tables, skinauditreports_users and users table
$options['joins'] = array(
array('table' =>'skinauditreports_users',
'alias' => 'SkaUser',
'type' => 'inner',
'conditions' => array(
'Skinauditreport.id = SkaUser.ska_id'
)
),
array('table' => 'users',
'alias'=> 'User',
'type' => 'inner',
'conditions' => array(
'SkaUser.user_id = User.id'
)
)
);
// Check user is admin user if then dont filter the report.
if($this->Session->read('Auth.User.group_id') != '3'){
$options['conditions'] = array(
'User.id' => $this->Auth->user('id')
);
}
//Add this condition if there is a search text.
if(isset($this->passedArgs["searchText"])) {
$options['conditions'] =array( array('OR' => array(
array('Skinauditreport.name LIKE' => "%".strtoupper($this->passedArgs["searchText"])."%"),
array('Skinauditreport.name LIKE' => "%".$this->passedArgs["searchText"]."%")
))
);
$searchText = $this->passedArgs["searchText"];
}
$this->set('searchText',$searchText);
//$skaReports = $this->Skinauditreport->find('all',$options);
//$this->set('skaReports', $skaReports);
$this->Paginator->settings = $options;
$this->set('skaReports', $this->paginate('Skinauditreport'));
}