php - Cakephp paginate based on model method -
in order model have following method sum total price of order's orderitems
public function gettotalprice($id = null) { if (!$this->exists($id)) { throw new notfoundexception(__('invalid order')); } $total = $this->orderitem->find('first', array( 'conditions' => 'orderitem.order_id = '.$id, 'fields' => 'sum('.$this->orderitem->virtualfields['total_price'].') total', 'group' => 'orderitem.order_id' )); return $total[0]['total']; }
in ordercontroller's view action calling method , setting value send view.
in order's index view see paginator links baked fields.
<th><?php echo $this->paginator->sort('user_id'); ?></th>
but understand it, parameter sort needs actual field on model. there way use paginator helper paginate custom method? or there way make method used virtual field on order model?
update added following custom find method on order model
public $findmethods = array('withtotal' => true); protected function _findwithtotal($state, $query, $results = array()) { if ($state === 'before') { // make sure fetch orderitems if(!isset($query['contain'])) { $query['contain'] = 'orderitem'; } else if (is_array($query['contain'])) { if(!in_array('orderitem', $query['contain'])) { array_push($query['contain'], 'orderitem'); } } else if(is_string($query['contain']) && strpos($query['contain'], 'orderitem') === false) { $query['contain'] = array($query['contain'], 'orderitem'); } return $query; } else if ($state === 'after') { if(count($results) > 0) { foreach($results &$order) { if(isset($order['orderitem'])) { $total = 0; foreach($order['orderitem'] $orderitem) { $total += $orderitem['total_price']; } $order['order']['order_total'] = $total; } } } } return $results; }
then added following order's index view
$this->paginate = array( 'findtype' => 'withtotal' );
before calling $this->paginate('order')
. able read value of $order['order']['order_total']
in view when click $this->paginator->sort('order_total')
link updates parameter in url not sort rows.
update 2 with solution
to fix sorting problem implemented following paginate method in order controller
public function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array()) { // orders total $contain = $extra['contain']; $orders = $this->find('withtotal', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'group', 'contain')); // if sorting order_total if(is_array($order) && array_key_exists('order_total', $order)) { $sortdirection = $order['order_total']; uasort($orders, function($a, $b) use($sortdirection) { if($a['order']['order_total'] == $b['order']['order_total']) { return 0; } else if($sortdirection == "asc") { return ($a['order']['order_total'] > $b['order']['order_total']) ? -1 : 1; } else if($sortdirection == "desc") { return ($a['order']['order_total'] < $b['order']['order_total']) ? -1 : 1; } }); } return $orders; }
i had add empty virtual field named order_total pagination sort validation pass
public $virtualfields = array( 'order_total' => '\'\'' );
read this. first key of array find method.
public $paginate = array( 'popular' );
since 0th index difficult manage, in 2.3 findtype option added:
public $paginate = array( 'findtype' => 'popular' );
also instead of paginate should use $this->paginator->settings in 2.3, looks book example not date yet.
Comments
Post a Comment