CakePHP recursive 2 with translate behavior - cakephp

I would like find all relations by code:
$this->set('types', $this->Project->ProjectType->find('all', array(
'recursive' => 2)));
I get error when I set recursive to 2:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'I18n__name.content' in 'field list'
Model ProjectType using Translate Behavior for content field (text type).
Other recursive works good.
How return results for recursive = 2?

Just don't use recursive at all.
Set it to public $recursive = -1; in your AppModel, and don't change it after that. Then use CakePHP's Containable Behavior to retrieve associated data.
Recursive will give you more headaches than it's worth. If Containable wasn't so easy/awesome, maybe we'd be stuck using recursive, but... it IS awesome and it IS easy :)

Related

How to retrieve data from model using findByType in cakephp?

I am trying to find records from CallForwardingCondition model using following line of code:
$this->loadModel('CallForwardingCondition');
$this->set('callForwardingCondition', $this->CallForwardingCondition->findByType('list'));
In SQL Dump following query is done when page is reloaded:
SELECT `CallForwardingCondition`.`type`, `CallForwardingCondition`.`description` FROM `vpbx`.`call_forwarding_condition` AS `CallForwardingCondition` WHERE `CallForwardingCondition`.`type` = 'list' LIMIT 1
How can I direct Cakephp to findByType which will result in following query?
SELECT `CallForwardingCondition`.`type`, `CallForwardingCondition`.`description` FROM `vpbx`.`call_forwarding_condition` AS `CallForwardingCondition` WHERE `CallForwardingCondition`.`type` LIKE '%' LIMIT 10
For CakePHP 2.x you need to use find('all') and pass it the required conditions and limit:-
$result = $this->CallForwardingCondition->find('all',[
'conditions' => ['CallForwardingCondition.type Like' => '%'],
'limit' => 10
);
findByType is a special find method that will only return the first record matching the type passed as the find method's parameter which is why it isn't returning what you want. You can read more about the findBy magic functions in the official docs.
try this:
$result = $this-> CallForwardingCondition ->find('all',['limit'=>10,'conditions'=>['CallForwardingCondition.type Like'=>'%'])->toArray();
I don't think you can't use findBy with limit. If you want to use limit, you must use findAllBy<fieldName>. Even findAllBy<fieldName>, you can't use LIKE.
This is findAllBy from cakephp
findAllBy<fieldName>(string $value, array $fields, array $order, int $limit, int $page, int $recursive)
So if you want to covert it, you must do the following way;
$this->CallForwardingCondition->findAllByType('something',['CallForwardingCondition.*'],['CallForwardingCondition.id'=>'desc'],'10');
This is findBy from cakephp doc.
findBy<fieldName>(string $value[, mixed $fields[, mixed $order]]);
Hope this help for you.

What is the right way to put the value for the 'limit' property of the Paginator in CakePHP into a config file

Using CakePHP 1.3 I created a small application which has a FooController. In this FooController I am using the Paginator to deliver the content of Foo to its views.
In the head of the FooController class I customized the preparation of the data from Foo like this:
var $paginate = array(
'limit' => 100,
'order' => array('Order.created' => 'desc'));
Now I would like to put the value for 'limit' into a configuration file.
So I created a file $config['list_length'] = '500'; in the config directory which I load in bootstrap.php. That works fine, I can echo the value of list_length, for example in the beforeFilter() of the class.
But I fail to make the Paginator use that value.
First I tried:
var $paginate = array(
'limit' => Configure::read('list_length'),
'order' => array('Order.created' => 'desc'));
But that fails with the following PHP error:
Parse error: syntax error, unexpected '(', expecting ')' in xyz/app/controllers/foo_controller.php on line 9
Then I tried:
public function beforeFilter() {
parent::beforeFilter();
$paginate['limit'] = Configure::read('list_length');
}
But it would still use the value '100' instead of '500'.
I guess this is a rather trivial problem that really comes from the fact that I am not very proficient with basic PHP concepts. I don't have much opportunity to get to program a little bit in my current job, so I'm really out of practice.
I would very much appreciate any hint on how to do this and even more on what concept I am missing here, so I could read a little bit about it.
You almost got it right;
The reason PHP is giving you the error in your first example is that class properties cannot be set using 'dynamic' values; from the documentation:
This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
http://www.php.net/manual/en/language.oop5.properties.php
If you need to set a property to a value that is 'dynamic' (e.g. The result of a function), you will need to assign if from within a class 'method'
You tried to do this in your second example, however, properties of a class/object should be accessed using $this->nameOfTheProperty to indicate it is not a 'variable', but a 'property' of the object;
public function beforeFilter() {
parent::beforeFilter();
$this->paginate['limit'] = Configure::read('list_length');
}
Hope this helps

cakephp Paginator -> sort - model option

I am having some issues sorting the table data by a field of a different model.
From here: http://book.cakephp.org/2.0/en/core-libraries/helpers/paginator.html
It says I can add in the 'model' option but when I try:
echo $this->Paginator->sort('unit', 'Unit', array('model' => 'Unit'));
I get this error:
Warning (2): array_filter() expects parameter 1 to be array, null given [CORE/Cake/View/Helper/PaginatorHelper.php, line 395]
Warning (2): array_merge() [function.array-merge]: Argument #1 is not an array [CORE/Cake/View/Helper/PaginatorHelper.php, line 395]
Any idea what is going on here? The Main / default model is Card and I need to order by the Unit model for one of the column headings.
Thanks
If you are showing records in a list out of some tables, then you can use it via:
<?php echo $this->Paginator->sort('Unit.unit', 'Unit');
It will perfectly work without passing third argument model option.
Just a reminder for newer Versions: Associated models are not automatically loaded in CakePHP3s Paginator. Make sure you include the 'sortWhitelist' Option, see https://book.cakephp.org/3.0/en/controllers/components/pagination.html#control-which-fields-used-for-ordering
Please try below code
echo $this->Paginator->sort('Unit.unit', 'Unit', array('model' => 'Unit'));
Let me know if any.

CakePHP: afterFind is weird with associations

So afterFind works fine and dandy when I'm within the corresponding model/controller. However, when calling an associated model, the data sent to the afterFind callback is formatted differently. This causes afterFind to crap out because it can't find the same array indexes it did when just working within the original model/controller.
Anyone know why, or what a fix might be?
$primary may not be very helpful; I've found that it is always false when using ContainableBehaviour beyond the first depth:
$this->Model->find('first', array(
'contain' => array(
'SecondaryModel' => array(
'TertiaryModel',
),
),
));
If you're setting a value based on a related model, you can check for its presence to deal with either structure like this:
function afterFind($results, $primary) {
if (isset($results['TertiaryModel'])) {
$results['secondary_model_field'] = 'value';
}
else {
foreach ($results as &$result) {
if (is_array($result) && isset($result['TertiaryModel'])) {
$result[$this->alias]['secondary_model_field'] = 'value';
}
} unset($result);
}
return $results;
}
Alternately you may be able to just check for the location of a field on the model itself. If the field doesn't exist at the top level, you will need to iterate over the set of results.
This is what the second parameter to afterFind callback is for.
$primary tells if you if the find was called from this model directly (true), or if it was called by an associated model (false).
A note from the book:
The $primary parameter indicates whether or not the current model was
the model that the query originated on or whether or not this model
was queried as an association. If a model is queried as an
association the format of $results can differ;
Code expecting $primary to be true will probably get a "Cannot use
string offset as an array" fatal error from PHP if a recursive find
is used.
So you may need different processing logic depending on the value of $primary
It appears that Cake 2.6 includes a fix for this, ensuring that all $results arrays are consistently formatted. I've done a little testing with the RC release and it does seem to work, with arrays all being passed in the format {n}.ModelName.data.
The fix is enabled by default, but you can also revert to the legacy behaviour if need be. Just add the following to your model (or AppModel) definition:
public $useConsistentAfterFind = false;

Cakephp - Paginating data from another model

I am trying to do pagination from the accommodation controller but with data from the MemberWall model.
here is the code
Accommodation
$data = $this->Accommodation->Member->MemberWall->paginate('MemberWall');
MemberWall
var $paginate = array(
'limit' => 4,
'order' => array(
'MemberWall.created' => 'asc'
)
);
I get this error
SQL Error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use nea.... Query: paginate
Thanks, Alex
Here is the REAL answer.
$data = $this->paginate($this->Accommodation->Member->MemberWall);
I had trouble finding this in the docs too. You can actually pass a model object into the paginate method.
I've tried and it works in both ways:
$this->paginate('MemberWall');
$this->paginate($this->Accommodation->Member->MemberWall);
In my code I use something like;
$this->loadModel('MemberWall');
$this->paginate = array(.....);
$data = $this->paginate('MemberWall');
$this->paginate('MemberWall'); iirc is the way it works
The MemberWall $paginate array (your second snippet) looks like it's defined in member_walls_controller.php It will not be accessible from accommodations_controller.php
$this->Accommodation->Member->MemberWall->paginate('MemberWall'); is calling a method on the MemberWall model. paginate() is a controller method.
Read Custom-Query-Pagination, particularly the last section.
I'm not sure that you can paginate that far down a relationship and it indicates to me that you probably need to rethink your datamodel and logic.
The 1.2 manual is better written on this topic.

Resources