Tree Behavior gives new child lft and rght values of 0 - cakephp
I have a MPTT using the TreeBehavior in CakePHP. Tree verifies but when I add a new root node it works. When I try to add a child to that node via $this->{Model}->save($data) where $data now has the ['{Model}']['parent_id'] set, it updates the parents' lft and rght fields to accomodate a new child but the new child has lft and rght values of 0.
Any idea of where I might be going wrong?
I have tried setting the lft and rght to null as well as unsetting, to no avail.
Model
`class Image extends AppModel {
public $displayField = 'title';
public $actsAs = array('Polymorphic', 'Tree');
public $imageResource = false;
// Define virtual fiels at runtime
public function __construct($id=false,$table=null,$ds=null){
parent::__construct($id,$table,$ds);
$this->virtualFields = array(
'path' => "CONCAT('db/', {$this->alias}.uuid, '.', {$this->alias}.ext)"
);
$categories = $this->ImageCategory->find('list', array('fields' => array('ImageCategory.id')));
$this->order = array('FIELD('.$this->alias.'.image_category_id, '.String::toList($categories, ', ').')');
}
public function save($data = null, $validate = true, $fieldList = array()) {
if($this->imageResource === false) {
if(!$this->loadImage(APP.'webroot'.DS.$this->path)) {
if(!$this->loadImage(APP.'webroot'.DS.'db'.DS.$this->uuid.'.'.$this->ext)) {
if(!$this->loadImage(APP.'webroot'.DS.'db'.DS.$data['Image']['uuid'].'.'.$data['Image']['ext'])) {
// Image doesn't exist so we create a new one.
//die('failed to load GD Library image resource');
//$this->saveNew($data, $validate, fieldList);
//$this->uses[] = 'OrigionalImage';
$this->loadImage(APP.'webroot'.DS.'img'.DS.'db'.DS.$this->data['Image']['uuid'].'.'.$this->data['Image']['ext']);
}
}
}
}
$data['Image']['width'] = $this->getWidth();
$data['Image']['height'] = $this->getHeight();
$this->writeToDisk(APP.'webroot'.DS.'img'.DS.'db'.DS.$this->uuid.'.jpg');
//pr($data);exit;
return parent::save($data, $validate, $fieldList);
}
public function saveNew($data = null, $validate = true, $fieldList = array()) {
$parentId = $data['Image']['parent_id'];
$this->recursive = -1;
$parentData = $this->readDataOnly(null, $parentId);
unset($parentData[$parentData['Image']['class']]);
if(!empty($parentData)) {
$data = array();
$data['Image']['parent_id'] = $parentId;
$data['Image']['class'] = $parentData['Image']['class'];
$data['Image']['foreign_id'] = $parentData['Image']['foreign_id'];
$data['Image']['title'] = $parentData['Image']['title'];
$data['Image']['alt'] = $parentData['Image']['alt'];
$data['Image']['image_category_id'] = $parentData['Image']['image_category_id'];
$data['Image']['image_type_id'] = $parentData['Image']['image_type_id'];
$data['Image']['ext'] = 'jpg';
$data['Image']['id'] = null;
$data['Image']['uuid'] = $this->uuid = String::uuid();
return $this->save($data, $validate, $fieldList);
}
return false;
}
public function saveToDB($data = null, $validate = true, $fieldList = array()) {
if($this->imageResource !== false) {
$data['Image']['width'] = $this->getWidth();
$data['Image']['height'] = $this->getHeight();
}
return parent::save($data, $validate, $fieldList);
}
public function read($fields = null, $id = null) {
if(parent::read($fields, $id)) {
$this->loadImage(APP.'webroot'.DS.'img'.DS.$this->data['Image']['path']);
return parent::read($fields, $id);
}
return false;
}
public function readDataOnly($fields = null, $id = null) {
return parent::read($fields, $id);
}
public function create($data = array(), $filterKey = false) {
if(parent::create($data, $filterKey)) {
$this->uuid = $this->data['Image']['uuid'] = String::uuid();
return true;
} else {
return false;
}
}
public function delete() {
unlink(APP.'webroot'.DS.'img'.DS.'db'.DS.$this->data['Image']['uuid'].'.'.$this->data['Image']['ext']);
return parent::delete();
}
public function loadImage($fileString) {
if(!file_exists($fileString)) {
throw new NotFoundException('File: "'.$fileString.'" not found');
return false;
}
//if(empty($this->ext))
$this->ext = strtolower(pathinfo($fileString, PATHINFO_EXTENSION));
// create useing the correct function
switch($this->ext) {
case 'jpg':
$this->imageResource = imagecreatefromjpeg($fileString);
break;
case 'jpeg':
$this->imageResource = imagecreatefromjpeg($fileString);
break;
case 'png':
$this->imageResource = imagecreatefrompng($fileString);
break;
case 'gif';
$this->imageResource = imagecreatefromgif($fileString);
break;
default:
throw new NotFoundException('File "'.$fileString.'" not found');
return false; // just in case
break; // just in case
}
imagealphablending($this->imageResource, true);
return true;
}
public function handelUpload($data = array()) {
$this->file = $data['Image']['file'];
if ($this->file['error'] == false) {
if(
$this->file['type'] == 'image/jpeg' ||
$this->file['type'] == 'image/jpg' ||
$this->file['type'] == 'image/png' ||
$this->file['type'] == 'image/gif'
) {
$this->uuid = String::uuid();
$this->set('uuid', $this->uuid);
$this->ext = strtolower(pathinfo($this->file['name'], PATHINFO_EXTENSION));
$this->set('ext', $this->ext);
$fileLocation = APP.'webroot'.DS.'img'.DS.'db'.DS.$this->uuid.'.'.$this->ext;
if (move_uploaded_file($this->file['tmp_name'], $fileLocation)) {
$this->loadImage($fileLocation);
$this->set('width', $this->getWidth());
$this->set('height', $this->getHeight());
return true;
}
return false;
}
}
}
public function resizeCrop($newWidth, $newHeight) {
$origWidth = $this->getWidth();
$origHeight = $this->getHeight();
$origRatio = $origWidth / $origHeight;
$desired_aspect_ratio = $newWidth / $newHeight;
if ($origRatio > $desired_aspect_ratio) {
/*
* Triggered when source image is wider
*/
$temp_height = $newHeight;
$temp_width = (int)($newHeight * $origRatio);
} else {
/*
* Triggered otherwise (i.e. source image is similar or taller)
*/
$temp_width = $newWidth;
$temp_height = (int)($newWidth / $origRatio);
}
/*
* Resize the image into a temporary GD image
*/
$temp_gdim = imagecreatetruecolor($temp_width, $temp_height);
imagecopyresampled($temp_gdim, $this->imageResource, 0, 0, 0, 0, $temp_width, $temp_height, $origWidth, $origHeight);
/*
* Copy cropped region from temporary image into the desired GD image
*/
$x0 = ($temp_width - $newWidth) / 2;
$y0 = ($temp_height - $newHeight) / 2;
$desired_gdim = imagecreatetruecolor($newWidth, $newHeight);
imagecopy($desired_gdim, $temp_gdim, 0, 0,$x0, $y0,$newWidth, $newHeight);
$this->imageResource = $desired_gdim;
return true;
}
public function crop($startX, $startY, $newWidth, $newHeight) {
$image_p = imagecreatetruecolor($newWidth, $newHeight);
$transparent = imagecolorallocatealpha($image_p, 255, 255, 255, 127);
imagealphablending($image_p, false);
imagesavealpha($image_p,true);
imagefilledrectangle($image_p, 0, 0, $newWidth, $newHeight, $transparent);
imagecopyresampled($image_p, $this->imageResource, 0, 0, $startX, $startY, $newWidth, $newHeight, $newWidth, $newHeight);
$this->imageResource = $image_p;
return true;
}
public function resizePercent($percent) {
(float)$percent = $percent/100;
// Get new dimensions
list($width, $height) = $this->getimageResourcesize($image);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
imagealphablending($image_p, false);
imagesavealpha($image_p,true);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
$this->imageResource = $image_p;
return true;
}
public function stream($quality = 100) {
switch(strtolower($this->ext)) {
case 'jpg':
header("Content-Type: image/jpeg");
imagejpeg($this->imageResource, null, $quality);
break;
case 'jpeg':
header("Content-Type: image/jpeg");
imagejpeg($this->imageResource, null, $quality);
break;
case 'png':
header("Content-Type: image/png");
imagepng($this->imageResource, null, $quality);
break;
case 'gif';
header("Content-Type: image/gif");
imagegif($this->imageResource, null, $quality);
break;
default:
throw new NotFoundException('File "'.$fileString.'" not found');
return false; // just in case
break; // just in case
}
return true;
}
public function writeToDisk($location = null, $quality = 100) {
if(!isset($this->ext) || empty($this->ext)) $this->ext = 'jpg';
if($location == null) $location = APP.'webroot'.DS.'img'.DS.'db'.DS.$this->uuid.'.'.$this->ext;
switch(strtolower($this->ext)) {
case 'jpg':
imagejpeg($this->imageResource, $location, $quality);
break;
case 'jpeg':
imagejpeg($this->imageResource, $location, $quality);
break;
case 'png':
imagepng($this->imageResource, $location, (($quality-100)/10));
break;
case 'gif';
imagegif($this->imageResource, $location, $quality);
break;
default:
throw new NotFoundException('File "'.$fileString.'" not found');
return false; // just in case
break; // just in case
}
return TRUE;
}
private function turnAlphaBlendingOFF() { imagealphablending($im, false); }
private function getImageResourceSize() {
$dim = array();
$dim[] = $this->getWidth($this->imageResource);
$dim[] = $this->getHeight($this->imageResource);
return $dim;
}
public function getWidth() {
return imagesx($this->imageResource);
}
public function getHeight() {
return imagesy($this->imageResource);
}
public $validate = array(
'original_image_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'uuid' => array(
'uuid' => array(
'rule' => array('uuid'),
),
),
'ext' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
'class' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
'foreign_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'title' => array(
'notempty' => array(
'rule' => array('notempty'),
),
),
'image_category_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'image_type_id' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'width' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
'height' => array(
'numeric' => array(
'rule' => array('numeric'),
),
),
);
public $hasOne = array(
'OriginalImage' => array(
'className' => 'Image',
'foreignKey' => 'id',
'conditions' => array('OriginalImage.parent_id' => 'OriginalImage.id', 'OriginalImage.id' => NULL),
),
'PrimaryImage' => array(
'className' => 'Image',
'foreignKey' => 'id',
'conditions' => array('PrimaryImage.primary' => 1),
)
);
public $belongsTo = array(
'ImageCategory' => array(
'className' => 'ImageCategory',
'foreignKey' => 'image_category_id'
),
'ImageType' => array(
'className' => 'ImageType',
'foreignKey' => 'image_type_id'
)
);
Controller
class ImagesController extends AppController {
public $paginate = array(
'limit' => 8,
'order' => 'Image.created DESC',
);
public $helpers = array('Js' => array('Jquery'));
public function admin_index() {
$this->Image->recursive = 0;
// Keywords
if(isset($this->passedArgs['Image.search']) && $this->passedArgs['Image.search'] != '') {
$keywords = $this->passedArgs['Image.search'];
$this->paginate['conditions'][] = array(
'OR' => array(
'Image.title LIKE' => "%$keywords%",
'Image.alt LIKE' => "%$keywords%",
)
);
$this->Image->data['Image']['Search'] = $keywords;
$title[] = __('Search',true).': '.$keywords;
}
// Width
if(isset($this->passedArgs['Image.width']) && $this->passedArgs['Image.width'] != '') {
$width = $this->passedArgs['Image.width'];
$this->paginate['conditions'][] = array(
'Image.width BETWEEN ? AND ?' => array($width-5, $width+5),
);
$this->Image->data['Image']['width'] = $width;
$title[] = __('Search',true).': '.$width;
}
// Height
if(isset($this->passedArgs['Image.height']) && $this->passedArgs['Image.height'] != '') {
$height = $this->passedArgs['Image.height'];
$this->paginate['conditions'][] = array(
'Image.height BETWEEN ? AND ?' => array($height-5, $height+5),
);
$this->Image->data['Image']['height'] = $height;
$title[] = __('Search',true).': '.$height;
}
// class
if(isset($this->passedArgs['Image.class']) && $this->passedArgs['Image.class'] != '') {
$class = $this->passedArgs['Image.class'];
$this->paginate['conditions'][] = array(
'Image.class LIKE' => $class,
);
$this->Image->data['Image']['class'] = $class;
$title[] = __('Search',true).': '.$class;
}
$this->set('count', $this->Image->find('count'));
$this->set('images', $this->paginate('Image', null, array('limit' => 8)));
}
public function admin_view($id = null) {
$this->Image->id = $id;
if (!$this->Image->exists()) {
throw new NotFoundException(__('Invalid image'));
}
$this->set('image', $this->Image->readDataOnly(null, $id));
if($this->Image->data['Image']['parent_id'] == null) {
$this->set('related', $this->Image->children($id, false, null, null, null ,1, 0));
} else {
$this->set('related', $this->Image->children($this->Image->data['Image']['parent_id'], false, null, null, null ,1, -1));
}
}
public function admin_add() {
$this->uses[] = 'Image';
$this->Image->create();
if($this->request->is('post')) {
if($this->Image->handelUpload($this->request->data) && $this->Image->saveToDB($this->request->data)) {
// Make thumbnails
if(true) {
$newParentId = $this->Image->getLastInsertID();
$this->Image->read(null, $newParentId);
$sizes = Configure::read('Image.thumbs.'.$this->Image->data['Image']['class']);
$numberOfResizes = 0;
foreach($sizes as $w => $h) {
if($this->Image->data['Image']['width']!=$w && $this->Image->data['Image']['height']!=$h) {
$this->Image->read(null, $newParentId);
$this->Image->resizeCrop($w, $h);
$this->request->data['Image']['parent_id'] = $this->Image->data['Image']['id'];
if($this->Image->saveNew($this->request->data)) {
$numberOfResizes++;
} else {
$this->Session->setFlash(__('A resized image could not be saved.'));
}
}
}
}
} else {
$this->Session->setFlash(__('The original image could not be saved. Please, try again.'));
}
$this->Session->setFlash(__('The image has been saved with '.$numberOfResizes.' resize(s)!'));
$this->redirect(array('controller' => 'images', 'action' => 'add', 'admin' => true));
}
$imageCategories = $this->Image->ImageCategory->generateTreeList(null,null,null,'-> ');
$imageTypes = $this->Image->ImageType->find('list');
$this->set(compact('imageSubcategories', 'imageTypes', 'imageCategories'));
}
public function admin_edit($id = null) {
$this->Image->id = $id;
if (!$this->Image->exists()) {
throw new NotFoundException(__('Invalid image'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if(!empty($this->request->data['Image']['file'])) {
$children = $this->Image->children($this->request->data['Image']['id']);
pr($children);exit;
if($this->Image->handelReUpload($this->request->data) && $this->Image->saveToDB($this->request->data)) {
// Make thumbnails
if(true) {
$this->Image->read(null, $this->Image->data['Image']['id']);
foreach($sizes as $w => $h) {
if($this->Image->data['Image']['width'] != $w && $this->Image->data['Image']['height'] != $h){
$this->Image->resizeCrop($w, $h);
unset($this->Image->data['Image']['modified']);
if($this->Image->data['Image']['parent_id'] == NULL) {
$this->request->data['Image']['parent_id'] = $this->Image->id;
if($this->Image->save($this->request->data)) {
$this->Session->setFlash(__('The image has been saved!'));
$this->redirect(array('controller' => 'images', 'action' => 'add', 'admin' => true));
}
$this->Session->setFlash(__('The image could not be saved. Please, try again.'));
}
}
}
}
$this->redirect(array('action' => 'view', $this->Image->id));
} else {
$this->Session->setFlash(__('The image could not be saved. Please, try again.'));
}
} else {
}
}
$imageCategories = $this->Image->ImageCategory->find('list');
$imageTypes = $this->Image->ImageType->find('list');
$this->request->data = $image = $this->Image->read(null, $id);
$this->set(compact('imageCategories', 'imageTypes', 'image'));
}
public function admin_delete($id = null) {
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this->Image->id = $id;
if (!$this->Image->exists()) {
throw new NotFoundException(__('Invalid image'));
}
$this->Image->readDataOnly(null, $id);
if ($this->Image->delete()) {
$this->Session->setFlash(__('Image deleted'));
$this->redirect($this->referer());
}
$this->Session->setFlash(__('Image was not deleted'));
$this->redirect(array('action' => 'index'));
}
public function admin_recover() {
$this->Image->recover('parent');
/*
$condidtions[] = array('Image.parent_id !=' => null);
$this->Image->recursive = -1;
$images = $this->Image->find('all', array('conditions' => $condidtions, 'order' =>array('Image.id'), 'fields' => array('id', 'title', 'width', 'height')));
pr($images);
foreach($images as $id => $title) {
$this->Image->readDataOnly(null, $id);
$this->Image->delete();
}
*
*/
}
public function admin_verify() {
pr($this->Image->verify());
exit;
}
You should not specify the lft / rght fields in your save.
Wrong
$this->save(array(
'parent_id' => 123,
'lft' => 0,
'rght' => 0
));
Correct
$this->save(array(
'parent_id' => 123
));
Dont forget to call $this->create(); before the save.
Related
WooCommerce custom Loop - Attribute filters not working
I'm having some issues with some Loop for Custom Catalog Listing. The goal: have Simple Products and some Variant Products (depend on the attribute) listed on the catalog page; I created a custom product loop using wc_get_products with the type array('simple', 'variation') but attribute filters like size or color don't work with this listing. This is the code: $category = get_queried_object(); $currentCat = ""; if ( $category->slug != NULL ){ $currentCat = array($category->slug); } $paged = (get_query_var('paged')) ? absint(get_query_var('paged')) : 1; $ordering = WC()->query->get_catalog_ordering_args(); $ordering['orderby'] = array_shift(explode(' ', $ordering['orderby'])); $ordering['orderby'] = stristr($ordering['orderby'], 'price') ? 'meta_value_num' : $ordering['orderby']; $products_per_page = apply_filters('loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page()); $list_products = wc_get_products(array( 'meta_key' => '_price', 'status' => 'publish', 'category' => $currentCat, 'type' => array('simple', 'variation'), 'limit' => $products_per_page, 'page' => $paged, 'paginate' => true, 'return' => 'ids', 'orderby' => $ordering['orderby'], 'order' => $ordering['order'], )); $totalProducts = (array) $list_products->products; wc_set_loop_prop('current_page', $paged); wc_set_loop_prop('is_paginated', wc_string_to_bool(true)); wc_set_loop_prop('page_template', get_page_template_slug()); wc_set_loop_prop('per_page', $products_per_page); wc_set_loop_prop('total', $list_products->total); wc_set_loop_prop('total_pages', $list_products->max_num_pages); if($totalProducts) { do_action('woocommerce_before_shop_loop'); woocommerce_product_loop_start(); foreach($totalProducts as $productID) { $post_object = get_post($productID); setup_postdata($GLOBALS['post'] =& $post_object); wc_get_template_part('content', 'product'); } wp_reset_postdata(); woocommerce_product_loop_end(); do_action('woocommerce_after_shop_loop'); } else { do_action('woocommerce_no_products_found'); } Anyone can give me an hand, so that filters start working??
Just got the way to put it to work: 1st I have a loop to get all the product ID's with a condition in the variations to confirm if a custom field (checkbox) is checked. This is mainly to get the total number of products to set up pagination. The Goal is to include only the Variations Checked on the Catalog Page. After, I'm doing a second loop, to get all products retrieved from the previous loop. Here is the working solution: if(!function_exists('wc_get_products')) { return; } function get_issues($term) { $hlterms = get_terms($term); foreach($hlterms as $term){ // var_dump($term->taxonomy); return true; } } // Get all Attribute Filters $outputFilters = ""; foreach($_GET as $key => $querystring){ if (strpos($key, 'filter') !== false) { $outputFilters = array(); $newkey = str_replace("filter", "pa", $key); if (get_issues($newkey) === true){ $outputFilters[$newkey] = $querystring; } } } // Check if in some Category $category = get_queried_object(); $currentCat = ""; if ( $_GET['product_cat'] != NULL ){ $currentCat = $_GET['product_cat']; } else if ($category->slug != NULL){ $currentCat = array($category->slug); } // 1st Loop to get total IDs $paged = (get_query_var('paged')) ? absint(get_query_var('paged')) : 1; $products_per_page = apply_filters('loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page()); $ordering['orderby'] = 'id'; $args = array( 'meta_key' => '_price', 'status' => 'publish', 'category' => $currentCat, 'type' => array('simple', 'variation'), 'limit' => 1000, 'paginate' => true, 'return' => 'ids', ); if ($outputFilters != ""){ $args = array_merge($args, $outputFilters); } $list_products = wc_get_products($args); $totalProducts = (array) $list_products->products; $productsIDS = array(); foreach($totalProducts as $productID) { $product_s = wc_get_product( $productID ); if ($product_s->product_type == 'simple') { array_push($productsIDS, $productID); } else { if ($product_s->product_type == 'variation') { $showCatalog = get_post_meta( $productID, '_showoncatalog', true ); if ($showCatalog == "yes"){ array_push($productsIDS, $productID); } } } } // Final loop $args = array( 'meta_key' => '_price', 'status' => 'publish', 'category' => $currentCat, 'type' => array('simple', 'variation'), 'limit' => $products_per_page, 'page' => $paged, 'paginate' => true, 'return' => 'ids', 'orderby' => $ordering['orderby'], 'order' => $ordering['order'], 'include' => $productsIDS, ); if ($outputFilters != ""){ $args = array_merge($args, $outputFilters); } $list_products = wc_get_products($args); $totalProducts = (array) $list_products->products; wc_set_loop_prop('current_page', $paged); wc_set_loop_prop('is_paginated', wc_string_to_bool(true)); wc_set_loop_prop('page_template', get_page_template_slug()); wc_set_loop_prop('per_page', $products_per_page); wc_set_loop_prop('total', $list_products->total); wc_set_loop_prop('total_pages', $list_products->max_num_pages); if($totalProducts) { do_action('woocommerce_before_shop_loop'); woocommerce_product_loop_start(); foreach($totalProducts as $productID) { $post_object = get_post($productID); setup_postdata($GLOBALS['post'] =& $post_object); wc_get_template_part('content', 'product'); } wp_reset_postdata(); woocommerce_product_loop_end(); do_action('woocommerce_after_shop_loop'); } else { do_action('woocommerce_no_products_found'); } /** * Hook: woocommerce_after_shop_loop. * * #hooked woocommerce_pagination - 10 */ #do_action( 'woocommerce_after_shop_loop' ); }
unable get data from database cakephp
i want get data from database and calculate the average Rating but when i get data by author id i have message find() is null this my function public function teacher_average_rating_in_school() { $this->autoRender = false; if($this->request->is('get')) { $author_id = $this->request->query('author_id');// $rate = $this->UserRating->find('all',array('conditions'=>array('author_id'=> $author_id), 'fields'=> array('AVG(UserRating.rstings) as averageRating'), 'recursive' =>-1)); $average = $rate[0][0]['averageRating']; $result = array('success'=>'1' , 'average' => $average ); } else{ $result = array('success'=>'0','message'=>'request type is not GET'); } echo json_encode($result); } and this my model class UserRating extends AppModel { public $validate = array( 'user_id' => array('rule' => 'notBlank'), 'author_id' => array( 'rule' => 'notBlank') , array('rstings' => 'notBlank' )); } why i get find()is null , and how can i solve that ?
Have you load the Modal?? public function teacher_average_rating_in_school() { $this->autoRender = false; if($this->request->is('get')) { $this->loadModel('UserRating'); $author_id = $this->request->query('author_id');// $rate = $this->UserRating->find('all',array('conditions'=>array('author_id'=> $author_id), 'fields'=> array('AVG(UserRating.rstings) as averageRating'), 'recursive' =>-1)); $average = $rate[0][0]['averageRating']; $result = array('success'=>'1' , 'average' => $average ); } else{ $result = array('success'=>'0','message'=>'request type is not GET'); } echo json_encode($result); } If you have already loadModel using then check sql_dump. You can use as follows //inside controller action debug($this->UserRating->lastQuery()); //Or inside layout call this <?php echo $this->element('sql_dump'); ?>
CakePHP HABTM add/edit problems
I have the following relationship: Edition: public $hasAndBelongsToMany = array( 'Band' => array( 'className' => 'Band', 'joinTable' => 'bands_editions', 'foreignKey' => 'edition_id', 'associationForeignKey' => 'band_id', 'unique' => true, ) ); Band: public $hasAndBelongsToMany = array( 'Edition' => array( 'className' => 'Edition', 'joinTable' => 'bands_editions', 'foreignKey' => 'band_id', 'associationForeignKey' => 'edition_id', 'unique' => true, ) ); BandsController: public function add() { if($this->request->is('post')) { $this->Band->create(); if($this->Band->save($this->request->data)) doSomething(); else doSomethingElse(); } } public function edit($id = NULL) { $this->Band->id = $id; if(!$this->Band->exists()) throw new NotFoundException(__('Not found')); if($this->request->is('post') || $this->request->is('put')) { if($this->Band->save($this->request->data)) doSomething(); else doSomethingElse(); } else { $this->request->data = $this->Band->read(NULL, $id); } } When I try to populate Bands with add(), everything goes well, but as soon as I call edit(), Cake stops with this error: Fatal error: Call to a member function schema() on a non-object Debugging, I found that the error is fired when the parser reaches the check about the type of the request. Which is my error?
Try this , I didn't see if it works public function edit($id = null){ if(!$id){ throw new NotFoundException(__("Invalid Post")); } $band = $this->Band->findById($id); if (!$band) { throw new NotFoundException(__('Invalid Post')); } if ($this->request->is(array('post', 'put'))) { $this->Band->id = $id; if ($this->Band->save($this->request->data)) { doSomething(); } else { doDomething(); } } if (!$this->request->data) { $this->request->data = $Band; } }
translate behavior and associated model translation
I searched the web 1000000000000000 times and i can't find a clean solution for this this is my CertificateType model translation part: public $actsAs = array('Translate'=>array('title','description')) ; and the Certificate model: public $actsAs=array('Translate'=>array('filename')) ; public $belongsTo = array( 'CertificateType' => array( 'className' => 'CertificateType', 'foreignKey' => 'certificate_type_id', 'conditions' => '', 'fields' => '', 'order' => '' ) , ); But in fetch time the belonged model will not translate: public function admin_index() { $this->Certificate->locale = $this->Session->read('Config.language'); $this->Certificate->CertificateType->locale = $this->Session->read('Config.language'); $this->Certificate->recursive = 0; $this->set('certificates', $this->paginate()); debug($this->Certificate->paginate()) ; } Why?
I used this and it is working great! in AppModel.php I wrote these piece of code: public function getTranslatedModelField($id = 0, $field) { // retrieve active language $ActiveLanguageCatalog=CakeSession::read('Config.ActiveLanguageCatalog') ; $res = false; $translateTable = (isset($this->translateTable))?$this->translateTable:"i18n"; $db = $this->getDataSource(); $tmp = $db->fetchAll( "SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1", array($this->alias, $ActiveLanguageCatalog['locale'], $id, $field) ); if (!empty($tmp)) { $res = $tmp[0][$translateTable]['content']; } return $res; } public function afterFind($results, $primary = false) { if($primary == false && array_key_exists('Translate', $this->actsAs)) { foreach ($results as $key => $val) { if (isset($val[$this->name]) && isset($val[$this->name]['id'])) { foreach($this->actsAs['Translate'] as $translationfield) { $results[$key][$this->name][$translationfield] = $this->getTranslatedModelField($val[$this->name]['id'], $translationfield); } } else if($key == 'id' && is_numeric($val)) { foreach($this->actsAs['Translate'] as $translationfield) { $results[$translationfield] = $this->getTranslatedModelField($val, $translationfield); } } } } return $results; }
Add code below to AppModel: public function afterFind($results, $primary = false) { if(!empty($this->hasMany)) { foreach($this->hasMany as $model => $settings) { if(isset($this->{$model}->actsAs['Translate'])) { if(!empty($results[0][$model])) { foreach($results[0][$model] as $row => $result) { $supplement = $this->{$model}->find('first', array( 'conditions' => array( $model .'.id' => $result['id']), 'fields' => $this->{$model}->actsAs['Translate'], 'recursive' => -1)); if(!empty($supplement)) { $results[0][$model][$row] = array_merge($results[0][$model][$row], array_diff($supplement[$model], $result)); } } } } } } if(!empty($this->belongsTo)) { foreach($this->belongsTo as $model => $settings) { if(isset($this->{$model}->actsAs['Translate'])) { if(!empty($results[0][$model])) { foreach($results[0][$model] as $row => $result) { $supplement = $this->{$model}->find('first', array( 'conditions' => array( $model .'.id' => $result), 'fields' => $this->{$model}->actsAs['Translate'], 'recursive' => -1)); if(!empty($supplement)) { $results[0][$model] = array_merge($results[0][$model], $supplement[$model]); } } } } } } return $results; } This works with relation hasMany and belongsTo
Thanks to Vahid Alimohamadi for the snipped. I had to modify it to work properly in my proJect. public function getTranslatedModelField($id = 0, $field) { // retrieve active language //$ActiveLanguageCatalog=CakeSession::read('Config.ActiveLanguageCatalog') ; $locale = Configure::read('Config.language'); $res = false; $translateTable = (isset($this->translateTable))?$this->translateTable:"i18n"; $db = $this->getDataSource(); $tmp = $db->fetchAll( "SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1", array($this->alias, $locale/*$ActiveLanguageCatalog['locale']*/, $id, $field) ); if (!empty($tmp)) { $res = $tmp[0][$translateTable]['content']; } return $res; } public function afterFind($results, $primary = false) { if($primary == false && array_key_exists('Translate', $this->actsAs)) { foreach ($results as $key => $val) { if (isset($val[$this->name]) && isset($val[$this->name]['id'])) { //HERE ADDED $field => $translationfield AND PASS IT TO THE getTranslatedModelField foreach($this->actsAs['Translate'] as $field => $translationfield) { $results[$key][$this->name][$field] = $this->getTranslatedModelField($val[$this->name]['id'], $field); } } else if($key == 'id' && is_numeric($val)) { //HERE ADDED $field => $translationfield AND PASS IT TO THE getTranslatedModelField foreach($this->actsAs['Translate'] as $field => $translationfield) { $results[$field] = $this->getTranslatedModelField($val, $field); } } } } return $results; }
I have some update to working in cakephp 2.5. It working for me now. Hope can help. public function getTranslatedModelField($id = 0, $field) { $res = false; $translateTable = (isset($this->translateTable))?$this->translateTable:"i18n"; $db = $this->getDataSource(); $tmp = $db->fetchAll( "SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1", array($this->alias, $this->locale , $id, $field) ); if (!empty($tmp)) { $res = $tmp[0][$translateTable]['content']; } return $res; } public function afterFind($results, $primary = false) { if($primary == false && array_key_exists('Translate', $this->actsAs)) { foreach ($results as $key => $val) { if (isset($val[$this->name]) && isset($val[$this->name]['id'])) { foreach($this->actsAs['Translate'] as $k => $translationfield) { $results[$key][$this->name][$translationfield] = $this->getTranslatedModelField($val[$this->name]['id'], $k); } } else if($key == 'id' && is_numeric($val)) { foreach($this->actsAs['Translate'] as $k => $translationfield) { $results[$translationfield] = $this->getTranslatedModelField($val, $k); } } } } return $results; }
I had done a change for getting current language and works perfectly with cacke 2.4.3 public function getTranslatedModelField($id = 0, $field) { // retrieve active language $locale = $this->locale ;// gets the current assigned locale $res = false; $translateTable = (isset($this->translateTable))?$this->translateTable:"i18n"; $db = $this->getDataSource(); $tmp = $db->fetchAll( "SELECT content from {$translateTable} WHERE model = ? AND locale = ? AND foreign_key = ? AND field = ? LIMIT 1", array($this->alias, $locale , $id, $field) ); if (!empty($tmp)) { $res = $tmp[0][$translateTable]['content']; } return $res; } public function afterFind($results, $primary = false) { if($primary == false && array_key_exists('Translate', $this->actsAs)) { foreach ($results as $key => $val) { if (isset($val[$this->name]) && isset($val[$this->name]['id'])) { foreach($this->actsAs['Translate'] as $translationfield) { $results[$key][$this->name][$translationfield] = $this->getTranslatedModelField($val[$this->name]['id'], $translationfield); } } else if($key == 'id' && is_numeric($val)) { foreach($this->actsAs['Translate'] as $translationfield) { $results[$translationfield] = $this->getTranslatedModelField($val, $translationfield); } } } } return $results; }
The easiest solution is the following get the ids of the associated models items and make another search like the following: $ids = array(); foreach ($wpage['Widget'] as &$widget): $ids[] = $widget['id']; endforeach; $widgets = $this->Wpage->Widget->find('all', array( 'conditions' => array('Widget.id' => $ids) )); $this->set(compact('wpage', 'widgets')); Thanks, Aris
Enabling Translate behavior for related models is very easy in Cake way, by using Model->SubModel->Behaviors->load(...) $this->Certificate->CertificateType->Behaviors->load( 'Translate', array('title','description') ); Have a look at http://book.cakephp.org/2.0/en/models/behaviors.html
passing data to view CakePHP
This might be easy, but I have tried a few ideas but no solution at all, I'm no expert with cakePhp but I'm trying to modify a existing project with limited time. The problem is that I have a entity called 'centro' but I'm using its model on a different controller, 'rw', but I can't get it to pass that data to the view at all; it seems it's because the variable gets erased when I use a redirect to go back to the 'index'. I need that data to generate a google map, the method $this->set(.....) is not working. Here's the code of the 'rw' controller. <?php class RwController extends AppController { var $name = 'Rw'; // var $paginate = array( // 'Tip' => array( // 'limit' => 1, // 'order' => array( // 'tip.created' => 'desc' // ), // ), // 'Evento' => array( // 'limit' => 1, // 'order' => array( // 'evento.fecha' => 'desc' // ), // ) // ); function map() { $this->helpers[]='GoogleMapV3'; } function pageForPagination($model) { $page = 1; // $chars = preg_split('/model:/', $this->params['url']['url'], -1, PREG_SPLIT_OFFSET_CAPTURE); // #print_r($chars); // if(sizeof($chars) > 1 && sizeof($chars) < 3) { // #echo "Belongs to ".$model.": \n"; // #echo var_dump($chars); // } // $params = Dispatcher::parseParams(Dispatcher::uri()); // echo "<p>".var_dump($params)."</p><br />"; #echo $this->params['named']['model'].$model; #echo $this->params['named']['page']; $sameModel = isset($this->params['named']['model']) && $this->params['named']['model'] == $model; $pageInUrl = isset($this->params['named']['page']); if ($sameModel && $pageInUrl) { $page = $this->params['named']['page']; } else { #echo var_dump($this->passedArgs); } $this->passedArgs['page'] = $page; return $page; } function index() { $this->loadModel('User'); $this->loadModel('Evento'); $this->loadModel('Tip'); $dataEvento = $this->Evento->find('all'); $dataTip = $this->Tip->find('all'); $page = $this->pageForPagination('Evento'); $this->paginate['Evento'] = array( 'contain' => false, 'order' => array('Evento.fecha' => 'desc'), 'limit' => 1, 'page' => $page ); $dataEvento = $this->paginate('Evento'); $page = $this->pageForPagination('Tip'); $this->paginate['Tip'] = array( 'contain' => false, 'order' => array('Tip.created' => 'desc'), 'limit' => 1, 'page' => $page ); $dataTip = $this->paginate('Tip'); $this->set('users', $this->User->find('all')); $this->set('eventos', $dataEvento); $this->set('tips', $dataTip); $this->set('rw'); if(isset($this->params['named']['model'])) { if (strcmp($this->params['named']['model'], 'Evento') == 0) { if($this->RequestHandler->isAjax()) { $this->render('/elements/ajax_rw_evento_paginate'); return; } } elseif (strcmp($this->params['named']['model'], 'Tip') == 0) { if($this->RequestHandler->isAjax()) { $this->render('/elements/ajax_rw_tip_paginate'); return; } } } } function about($id = null) { $this->Rw->recursive = 0; $this->set('rw', $this->paginate()); } function beforeFilter() { parent::beforeFilter(); $this->Auth->allow(array('*')); } function getCentros($id = null ){ $this->loadModel('Centro'); $this->log('getcentros','debug'); $this->log('el id'.$id,'debug'); if( sizeof($id) > 1){ $this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud FROM `centros`,`centrosmateriales` WHERE centros.id = centro_id AND material_id ='".$id[0]."' OR material_id='".$id[1]."'")); $this->log('size id > 1 ','debug'); }elseif( sizeof($id) >0) { if($id == 0){ $this->set('centros', $this->Centro->find('all')); }else{ $this->set('centros', $this->Centro->query("SELECT centros.id, name, latitud ,longitud FROM `centros`,`centrosmateriales` WHERE centros.id = centro_id AND material_id ='".$id[0]."'")); } } $this->Session->write('saludos', 'Saludando'); $this->redirect(array('action' => 'index')); } } ?> I have been thinking about ajax but I'm not sure. Anyways, thanks in advance.
Using redirect() sends an actual HTTP redirect to the browser. This causes the browser to send another request to the server, to the URL it has been redirected to. The data that you pass to set() is only available within that single CakePHP request cycle. All PHP data is wiped from memory afterwards. The only way to pass data to the next request is in the URL or in the session. In your case you should rethink your design and set() all data you need in the index() action. You could possibly move the logic from getCentros() into your Centro model. Then, in your index() function, you could just do $this->set( 'centro', $this->Centro->getCentros(); );