CakePHP While-loop inside another loop - cakephp

Since I'm in need of my navigation buttons I've placed the following code inside my AppController since i need it on every page.
// app/Controller/AppController.php
class AppController extends Controller {
public $uses = array('Categorie');
public function beforeFilter()
{
$parents = $this->Categorie->find('all', array('conditions' => array('cat_parent' => 0)));
$childs = $this->Categorie->find('threaded', array('conditions' => array('cat_parent' => $parents['Categorie']['cat_id'])));
echo '<pre>'.var_dump($parents).'</pre>';
}
}
I don't think this is the good way too accomplish what I want.. how can i do a while inside a while with the CakePHP Framework.
Kind Regards,
Jordy

You don't need a while loop in this case, you could just find the categories where cat_parent is not zero:
$childs = $this->Categorie->find('threaded', array(
'conditions' => 'cat_parent != 0'
));

Related

Can not get paginate parameters using func_get_arg() function in Model

I'm updating cakephp2 to cakephp3.
For model side, I can not get paginate parameters using func_get_arg() function in Model.
How can I get it?
I want to keep using func_get_arg() because other Model classes have also same logic.
class TopController extends AppController {
public function showTop() {
$query = array(
'limit' => 5,
'extra' => array(
'data' => 'test',
),
);
$topRawTable = TableRegistry::get('TopRawSql');
$pages = $this->Paginator->paginate($topRawTable->paginate($query)); //Error occur
}
}
class TopRawSqlTable extends Table {
public $useTable = false;
function paginate()
{
$extra = func_get_arg(6); // null
$limit = func_get_arg(3); // null
$page = func_get_arg(4); // null
// Execute custom query
}
}
I knew that CakePHP2 supports override paginate() and paginateCount() functions. But CakePHP3 DOESN'T support override paginate() and paginateCount(). That's why I couldn't get parameters by func_get_arg().
So, I switched to use CakePHP2 paginator feature.

Cakephp editing BelongsTo associated field

I'm having problem in editing associated (BelongsTo) field...
Class ModelA extends AppModel {
public $belongsTo = array ('ModelB');
public $actsAs = array('Containable');
public function getModelA($id){
$modelA = $this->find('all', array('contain' => array('ModelB'),'conditions' => array('ModelA.id' => $id)));
if(count($modelA)>0){
$modelA = $modelA[0];
}
return $modelA;
}
}
class ModelAsController extends AppController {
public function edit($id = null) {
$modelA = $this->ModelA->getModelA($id);
$this->set('modelA', $modelA);
}
}
Data in the $modelA is in the format:
array(
'ModelA' => array(
...
),
'ModelB' => array(
...
)
)
So far, everything is fine...
But, I'm stuck with the edit.ctp. I need input for editing of the field1 from the ModelB, but I'm getting empty input box. Line of the code goes like this:
echo $this->Form->input('ModelB.field1');
When I try to debug:
Debugger::log($modelA['ModelB']['field1']);
then I have correct value.
What would be the way to have input box filled with field1 of the ModelB?
for a FormHelper to pickup the model data you have to set
$this->request->data = $modelA;
in the Controller, otherwise the helper has no idea where you've hidden the data :)
(tip: usually you can debug the helper code in such cases)

How to update translation cakephp but not main table

I have added translate behaviour to a model, the model comes here
App::uses('AppModel', 'Model');
class Category extends AppModel
{
public $hasMany = "Product";
public $validate = array(
'name' => array(
'rule' => 'notEmpty'
)
);
public $actsAs = array(
'Translate' => array(
'name','folder','show'
)
);
public $name = "Category";
public $translateModel = 'KeyTranslate';
}
And heres the controller for updating the model
public function admin_edit_translate($id,$locale)
{
$this->Category->locale = $locale;
$category = $this->Category->findById($id);
if ($this->request->is('post') || $this->request->is('put')) {
$this->Category->id = $id;
if ($this->Category->save($this->request->data)) {
$this->Session->setFlash('Category translate has been updated');
//$this->redirect(array('action' => 'edit',$id));
} else {
$this->Session->setFlash('Unable to update category');
}
}
if (!$this->request->data) {
$this->request->data = $category;
}
}
My Problem is that i have a name field in the categories database and when i update or create a new translation it gets updated with the translated value. How do i avoid that
You must use Model::locale value to set code language for save in database
This happens because the TranslateBehavior uses callbacks like beforeSave and afterSave to save translated content, so it needs to let the model's save operation continue and thus will contain the last translated content.
You could get around this by tricking the TranslateBehavior into thinking the model is saving something by calling the beforeSave and afterSave like this:
$Model = $this->Category;
$Model->create($this->request->data);
$Model->locale = $locale;
$beforeSave = $Model->Behaviors->Translate->beforeSave($Model, array(
array(
'callbacks' => true
)
));
if($beforeSave) {
$Model->id = $id;
$Model->Behaviors->Translate->afterSave($Model, true);
}
This way the translation will be saved and the main table will be left untouched. Might not be the best way to save translations though. Why do you need to leave the main table untouched?
Callback Behavior::beforeSave is before Model::beforeSave...
but, the simplest way to modify data in Model::beforeSave before Behavior::beforeSave before realy saving is:
$this->Behaviors->Behavior_Name->runtime[Model_Name]['beforeSave'][Field_Name] = '...';

cake php link to the current page with different prefix

In my default layout I would like to show link which points to the current page but with different prefix. I am using prefix 'language' to use address like www.site.com/eng/controller/action/param.
I tried $this->Html->link('eng', array('language' => 'eng') );
But this creates link with url eng/controller/action without passed arguments, without named arguments and without url params.
How I can do this? I would prefer elegant solution like 1 line of code - I know it can be done but can't find it :(.
Try this:
// helper method, possibly AppHelper, or in AppController and set a view var
function getCurrentParams() {
$route = Router::currentRoute();
$params = $this->request->params;
$pass = $params['pass'];
$named = $params['named'];
unset($params['pass'], $params['named']);
if (!empty($route->options['pass'])) {
$pass = array();
}
return array_merge($params, $named, $pass);
}
$params = $this->SomeHelper->getCurrentParams();
$params['language'] = 'eng';
// use $params for your link now
in my case this easy solution worked too!
<?php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
public function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language']) && is_array($url)) {
$url['language']= $this->params['language'];
}
if(count($url) == 1 && isset($url['language'])){
$params = $this->params;
$url = array_merge($params['pass'],$url);
}
return parent::url($url, $full);
}
}
and in AppController
public $helpers = array(
...
'Html' => array('className' => 'MyHtml')
...
);
$this->Html->link('eng', array('language' => 'eng', 'pass') );
Something like this should work:
$url = Router::parse($this->here);
$url['language'='end';
$this->Html->link('eng', $url);
It's not one line, but you could compress it into one line but it would be pretty unreadable.
You could wrap it in a helper / function which would be a one line call though ;-)

CakePHP: Weird Contain Behavior

I'm having some really weird 'Contain' behavior. Whenever I leave $restaurants commented, $spas returns the contained data (assigned in the beforeFilter(), but when I uncomment $restaurants, it ignores the contain statement. (I've even tried cloning the $spas function and naming it "$restaurants" and the same thing happens..
class CouponsController extends AppController {
public function beforeFilter() {
parent::beforeFilter();
$this->Coupon->contain(array('Vendor' => array('VendorLocation'), 'Category'));
}
public function index() {
$showPerPage = 4;
//$restaurants = $this->Coupon->findAllBycategory_id('1', '', '', $showPerPage);
$spas = $this->Coupon->find('all', array('limit' => $showPerPage, 'conditions' => array('Coupon.category_id' => 3)));
$this->set('spas', $spas);
}
Did you attach this behavior in $actsAs variable on Coupon model?
Or you can attach on Controller:
$this->Coupon->Behaviors->attach('Containable');
$this->Coupon->contain(array('Vendor' => array('VendorLocation'), 'Category'));
And detach wherever you want:
$this->Coupon->Behaviors->detach('Containable');

Resources