CakePHP Custom route calling wrong action - cakephp

I have the following code in routes.php:
Router::connect('/c/details/:id/:slug',
array('controller' => 'cars'),
array('pass' => array('id', 'slug'))
);
If I try to access http://domain.com/c/details/123/abc, it works. However, if I remove abc (ie the slug), CakePHP tries to access the action 123 (which is the id, not the action).
Error: The action 123 is not defined in controller CarsController
If I use /c/details/:id/:slug/:action/*, which was what I had before upgrading from 1.2 (yeah, pretty old) to 2.2.1 and it was working fine, CakePHP also tries to access action 123 whether I have a slug or not.
URLs without slugs always worked before upgrading CakePHP and with the code I have in the controller, if there was no slug in the URL, it would redirect to the right URL.
Edit: I just checked and it seems that when I don't provide with a slug, the whole thing is shifted. c is ignored, details becomes the controller and 123becomes the action.
[request] => CakeRequest Object
(
[params] => Array
(
[plugin] =>
[controller] => details
[action] => 123
[named] => Array()
[pass] => Array()
[isAjax] =>
)
When the correct would be, and which is what I get if I provide with a slug:
[request] => CakeRequest Object
(
[params] => Array
(
[plugin] =>
[controller] => cars
[action] => index
[named] => Array()
[pass] => Array
(
[0] => 123
[1] => abc
)
[id] => 123
[slug] => abc
[isAjax] =>
)
Any idea what may be causing this issue now?

You may need 2 routes if you want the slug to be optional (not sure). In any case, add the action key to each route as well.
Router::connect('/c/details/:id',
array('controller' => 'cars', 'action' => 'details'),
array('pass' => array('id'))
);
Router::connect('/c/details/:id/:slug',
array('controller' => 'cars', 'action' => 'details'),
array('pass' => array('id', 'slug'))
);

Related

Kartik Editable Checkbox does not show default value as checked

I am using Kartik/Editable of latest version.
Implemented a checkbox popup which works, but it does not show the default value as checked/unchecked.
Example:
echo Editable::widget([
'name' => 'test',
'value' => 1,
'asPopover' => false,
'inputType'=>Editable::INPUT_CHECKBOX,
]);
This will show a popover where the checkbox is not checked at all, but it should be as value = 1.
According to Kartiks documentation, the value should be an integer, not boolean.
Am I missing something? Or is this by design?
You should add 'options' => ['checked' => true,], for checkbox checked.
Editable::widget([
'name' => 'test',
'value' => 1,
'asPopover' => false,
'options' => ['checked' => true,],
'inputType' => Editable::INPUT_CHECKBOX,
]);

Cakephp Internationalization adds '_locale' property in contain associations

Cakephp seems to be adding the property "_locale" on "contain" associations, its ok if this property sits inside the Entity object, but not in the array that holds the associations as it will break a lot of stuff, this only happens when the language is not the default and the Model has the translate behavior, any ideas on how to fix / remove it?
[product_variations] => Array(
[0] => App\Model\Entity\ProductsVariation Object(
[id] => 15
[product_id] => 12
[name] => Adults
[description] => <p>Adult Ticket</p>
[price_mode] => final
[price] => 15
[stock] => -1
[weight] => 0
[sku] => OITGXNRMARTPPDV
[data] =>
[active] => 1
[enquire] =>
[position] => 1
[products_prices] => Array
(
)
[_locale] => pt
[[new]] =>
[[accessible]] => Array
(
[*] => 1
)
[[dirty]] => Array
(
)
[[original]] => Array
(
)
[[virtual]] => Array
(
)
[[errors]] => Array
(
)
[[invalid]] => Array
(
)
[[repository]] => ProductVariations
),
[_locale] => pt
)
Update: Seems to be due to the use of the "matching" method "Model->find(...)->matching('ProductVariations')...
The manual explains it:
So, after you save your first article, you can now save a translation for it, there are a couple ways to do it. The first one is setting the language directly into the entity:
$article->_locale = 'es';
$article->title = 'Mi primer Artículo';
$this->Articles->save($article);
So be aware of this when you modify the data. I don't know what happens if you remove it and then save the record or try do some something else i18n related with it. :)
The code related to this property is here in the TranslateTrait.
You can try to add a result formatter by calling formatResults() on the query and unset this property from there.

phpactiverecord retrieve records

Let's make it short, I pass an user id into a function and try to get all attributes for this user:
$user = \Sitename\UsrManager::getUserById($user_id);
I then print_r($user) and get a bunch of data:
Sitename\User Object ( [model:protected] => User Object ( [errors] => [attributes:ActiveRecord\Model:private] => Array ( [user_id] => 18 [company_name] => ABC Ltd [company_logo] => logo.png [brief] => Sample text [profile] => Some Profile ) [__dirty:ActiveRecord\Model:private] => Array ( ) [__readonly:ActiveRecord\Model:private] => [__relationships:ActiveRecord\Model:private] => Array ( ) [__new_record:ActiveRecord\Model:private] => ) [_password_updated:Sitename\User:private] => [template:protected] =>
If I want to get specific attribute such as Company Name, I try echo the company name as $user->company_name, but there is nothing to show, what is the proper way to call data(object?) in my example? it's like similar to the old way to call the necessary data like $row['company_name'].

CakePHP model relations, how to avoid unnecessary data?

I'm learning CakePHP, thus I'm making a simple blog in order to learn basic functionality, this blog will have tables holding posts, users, users activation codes and taxonomy along with taxonomy relationships between posts and tags.
Ok, the thing now is, I've managed to set everything up properly and every time I fetch a post, it returns a lot of data:
Array
(
[Post] => Array
(
[post_id] => 1
[post_title] => Test 1
[post_nice_name] => test-1
[post_author] => 1
[post_content] => I'm testing this piece of crap.
[post_creation_time] => 2011-11-13 22:50:05
[post_last_modification] => 2011-11-13 22:50:05
[post_allow_comments] => 1
[post_allow_trackback] => 1
[post_display] => 1
)
[User] => Array
(
[user_id] => 1
[user_email] => XX#XXXXXXXXXXx.XX.XX
[user_password] => XXXXXXXXXXXXXXXXXX
[user_creation_time] => 2011-11-13 10:48:10
[user_last_login] => 2011-11-13 22:49:21
[user_birthday] => 1993-08-24 03:00:00
)
[TaxonomyTags] => Array
(
[0] => Array
(
[tag_id] => 1
[tag_name] => test1
[tag_description] => This tag is a test
[PostsTaxonomyTag] => Array
(
[relation_id] => 1
[post_id] => 1
[taxonomy_tag_id] => 1
)
)
[1] => Array
(
[tag_id] => 2
[tag_name] => test2
[tag_description] => This tag is just another test.
[PostsTaxonomyTag] => Array
(
[relation_id] => 2
[post_id] => 1
[taxonomy_tag_id] => 2
)
)
)
)
This much data is really unnecessary: I don't need the PostsTaxonomyTag array for every tag, nor do I need that much of the user's information, I don't even need some of the post's information!. So I wanted to know if there's any way to filter this information before it is passed on to the view.
You can unbind models befor a find function to prevent unneeded data
$this->Model->unbind(array('hasMany' => array('assocModel')));
I prefer to use the containable behavior for most models which forces you to state the relationships you need at find though. Mcheck the docs about that behavior.
$this->Model->find(
'all',
array(
'conditions' => array(
//set conditions
),
'contain' => array(
'Model2',
'model3'
)
)
);
You can set conditions, order, etc. in the containable set making it powerful for getting exactly the data you need.
... or you can simple use 'recursive' => -1 in options for find.

Cakephp "joins" destroys conditions?

A bug has a state and hasandbelongs to many usergroups among other things.
Now, when listing the bugs I used the pagination helper and also give the user the ability to filter it by various setting. Works great so far. You can filter it by project, you can filter it by state (via the state_id property of the bug) and by several other items. Now I want it to be filtered by the groups that are responsible for the bug.
Since this is a HABTM connection I used "joins" to connect up the tables.
This is what my $this->paginate looks like:
[limit] => 10
[contain] => Array
(
[0] => Project
[1] => User
[2] => Priority
[3] => State
[Comment] => Array
(
[0] => User
)
[4] => Screenshot
[5] => Group
)
[conditions] => Array
(
[Bug.project_id] => 26
[Bug.state_id] => 1
)
[Bug] => Array
(
[joins] => Array
(
[0] => Array
(
[table] => bugs_groups
[alias] => BugsGroups
[type] => inner
[conditions] => Array
(
[0] => BugsGroups.bug_id = Bug.id
)
)
[1] => Array
(
[table] => groups
[alias] => Group
[type] => inner
[conditions] => Array
(
[0] => Group.id = BugsGroups.group_id
[Group.id] => 9
)
)
)
)
The strange thing is - as soon as I look for a Group by using the
"join" the previous conditions (project_id, state_id) are completely ignored?! Is this expected behavior in cake and how would I circumvent it?
Shouldn't these:
[0] => BugsGroups.bug_id = Bug.id
[0] => Group.id = BugsGroups.group_id
Look like:
[BugsGroups.bug_id] => Bug.id
[Group.id] => BugsGroups.group_id
?
Colleague found the solution - putting the joins inside the "Bug" key was the problem. Moving it one step up ($this->paginate['joins'] instead of $this->paginate['Bug']['joins']) makes it work beautifully...

Resources