This is driving me crazy. In my AppController, I have the following:
public function beforeFilter() {
$this->Cookie->name = 'MyCookie';
$this->Cookie->time = '1 year';
$this->Cookie->domain = 'http://mydomain.com';
$firstVisit = $this->Cookie->read('foo');
if ( empty($firstVisit) ) {
$this->set('firstVisit', true);
$this->Cookie->write('foo', 'true');
} else {
$this->set('firstVisit', false);
}
}
This seems like it should work, but nothing is returned and the cookie is completely blank.
What could possible be preventing Cake from actually saving the Cookie?
The cookies are not set until the View is rendered. Maybe you do not have a view for your controller?
The http:// caused it to break. Removing that fixed the problem.
Related
This document shows how to assign layout for error:
$this->layout = 'my_error';
http://book.cakephp.org/3.0/en/development/errors.html#exception-renderer
But i've 2 different layouts for frontend and backend. When NotFoundException is thrown, i want to assign different layout accordingly.
How can i do that? Please help me.
Just check appropriate criteria and set layout accordingly in your template. For e.g.
if ($this->request->param('prefix') === 'admin') {
$this->layout = 'admin';
} else {
$this->layout = 'default';
}
As #ADmad suggest.
Do check the request to identify frontend or backend inside error400.ctp file (you may have another error file, just is a example).
In my case use admin prefix, i did like this:
if (!empty($this->request->params['prefix']) && $this->request->params['prefix'] == 'admin') {
$this->layout = 'Admin/default';
$app = [
'App.imageBaseUrl' => 'admin/img/',
'App.cssBaseUrl' => 'admin/css/',
'App.jsBaseUrl' => 'admin/js/'];
Configure::write($app);
} else {
$this->layout = 'Frontend/default';
}
If you want to re-set layout you have to re-render the action, a redirect would be the most easy solution here. You could also use an AppView.
$view = new AppView();
$view->set($variables);
$view->render();
http://book.cakephp.org/3.0/en/views.html#the-app-view
I'm using the following code to set, and then read a cookie in CakePHP.
public $components = array('Cookie');
public function beforeFilter(){
parent::beforeFilter();
$this->Cookie->name = 'saved_times';
$this->Cookie->time = '1 year';
$this->Cookie->domain = 'localhost';
$this->Cookie->path = '/';
$this->Cookie->httpOnly = false;
$this->Cookie->key = '+%)asG_~s*SAr&bSIq34$#11qe#s!#v!#*(XSL#$XOw!a232d#HKis~#^';
$this->Cookie->secure = false;
}
public function save_position($time){
if($this->Auth->user('id')){
//save to the database
return true;
}else{
//set browser cookie
$this->Cookie->write('time', $time);
echo "set", $this->Cookie->read('time');
}
}
public function read(){
echo $this->Cookie->read('time'), "test";
print_r($this->Cookie->read('time'));
}
The problem is that when I set the cookie I see, "set" and the cookie value echoed out, but when I visit /read/ I'm only seeing "test" and no cookie value. Also I'm using a cookie viewer in chrome, but I only see the CAKEPHP cookie for my domain not saved_times. I don't think the cookie is even being set, but I don't know why
It turns out cookies arent set until the View is rendered. I had no view for my save_position action, so an error page was showing, which didnt set the cookie. Once I added a save_position.ctp file everything worked okay.
The PaginationRecall component is giving me a headache, it let my application crash.
I have a region view, I can call it with /views/[number of region]
I found out that the reason for the crash is that it wants to go back to Page:5
although the url is changed to a different region which only has 1 or 2 pages.
I updated to the latest cakePHP version [v2.3.5] as there was a mention about a fix for 'Preventing pagiation limit from overflowing the max integer value' But updating didn't solve my problem. Not sure if this is a problem with the PaginationRecal component or the Paginator itself.
For example; I can browse to the url ../regions/view/1/page:5 leave that page and when return back all fine [it remembered last page]
But when changing the url to a different region ../regions/view/56/ it crashes with error: Error: The requested address '/regions/view/56' was not found on this server.
Stack Trace
CORE/Cake/Controller/Controller.php line 1074
#deprecated Use PaginatorComponent instead
*/
public function paginate($object = null, $scope = array(), $whitelist = array()) {
return $this->Components->load('Paginator', $this->paginate)->paginate($object, $scope, $whitelist);
}
At first I didn't understand this crash untill I found out it was related to the page number. The problem never pops-up when browsing only on the first page. How can I fix this problem?
I have added the PaginatorRecall Component in my /app/Controller/AppController.php
public $components = array('PaginationRecall');
This is the component: http://bakery.cakephp.org/articles/Zaphod/2012/03/27/paginationrecall_for_cakephp_2_x
Any help much appreciated.
SOLVED
After investigating what the PaginatorRecall component is doing, I found out that it filters out only the page:number and stores it in a session.
I have added a rule to find out if the region is changed and if so then reset the page to page:1
Hope this helps someone else using this component as well.
This is my solution to this problem and the bug that PaginationRecall have with the first page. Surely it is not the most optimal solution, but it is functional.
class PaginationRecallComponent extends Component {
var $components = array('Session');
var $Controller = null;
function initialize(&$controller) {
$this->Controller = & $controller;
$options = array_merge($this->Controller->request->params, $this->Controller->params['url'], $this->Controller->passedArgs
);
$vars = array('page', 'sort', 'direction', 'filter');
$keys = array_keys($options);
$count = count($keys);
for ($i = 0; $i < $count; $i++) {
if (!in_array($keys[$i], $vars) || !is_string($keys[$i])) {
unset($options[$keys[$i]]);
}
}
//save the options into the session
if ($options) {
if ($this->Session->check("Pagination.{$this->Controller->modelClass}.options")) {
$options = array_merge($this->Session->read("Pagination.{$this->Controller->modelClass}.options"), $options);
}
$this->Session->write("Pagination.{$this->Controller->modelClass}.options", $options);
$this->Session->write("region",$this->Controller->modelClass.'/'.$this->Controller->view);
}
$region=$this->Session->read('region');
//recall previous options
if ($this->Session->check("Pagination.{$this->Controller->modelClass}.options") && $region==$this->Controller->modelClass.'/'.$this->Controller->view ) {
$options = $this->Session->read("Pagination.{$this->Controller->modelClass}.options");
if(!isset($this->Controller->params['named' ]['page']) && isset($this->Controller->params['named' ]['direction']) )
{
$options['page']=1;
}
$this->Controller->passedArgs = array_merge($this->Controller->passedArgs, $options);
$this->Controller->request->params['named'] = $options;
}
}
}
In my controller
public function profile() {
$UserInfo = $this->Auth->user()
if(!empty($this->data)) {
print_r($this->data);
$this->User->save($this->data);
}
if(!empty($UserInfo['id'])){
$this->data = $this->User->find('first',array('conditions'=>array('id'=>$UserInfo['id'])));
}
}
when i submit the data it is not submitted to db and i get only previous value.
Why are you querying the session here? of course this will always get you the old data again after the save.
Use the database as always, update the database again and only then overwrite the session maybe (You seem to be using cake 1.3):
public function profile() {
$uid = $this->Session->read('Auth.User.id');
if (!empty($this->data)) {
$this->data['User']['id'] = $uid;
if ($this->User->save($this->data, true, array('email', 'first_name', 'last_name', 'id', ...))) {
// if you rely on auth session data from the user, make sure to update that here
$this->Session->write('Auth.User.email', $this->data['User']['email']); // etc
...
// OK, redirect
} else {
// ERROR
}
} else {
$this->data = $this->User->find('first', ...);
}
}
As you can see I update the session keys that have been changed.
If you are using 2.x (which you did not specify as for now) you could also use
$this->Auth->login($this->request->data['User']); // must be the User array directly
although you will have to careful to pass all the data that has been in the session before.
If you plan on using login(), it would be better to find(first) the updated record again and pass this into login() then.
But personally, I prefer to only update the fields that actually changed.
see Editing own account/profile
Does someone here know how to change the username before the Auth component reads the database?
The problem im having is im using mobile numbers as a login but i want to add the country code (if not present) when loggin in to my site
Any one have an idea on this?
Would be appreciated
If you are using CakePHP 2.0, you can manipulate the login form data as usual and then call $this->Auth->login(). Example:
// in your controller
public function login() {
if ($this->request->is('post')) {
$this->data['User']['username'] = $this->addCountryCode($this->data['User']['username']);
if ($this->Auth->login()) {
// login successful
} else {
// login not successful
}
}
}
you could always extend the Auth component and do whathever you want before the asking the database :)
Something like this...
function login($data = null,$public = false) {
$this->__setDefaults();
$this->_loggedIn = false;
if (empty($data)) {
$data = $this->data;
}
if (/** query the database to check/modify the data. You could use the identify() method of the AuthComponent **/) {
$this->Session->write($this->sessionKey, $user);
$this->_loggedIn = true;
}
return $this->_loggedIn;
}
If you extend the auth component, remember to always use this component instead of the default Auth class. (e.g. in the AppController, the build_acl, the initdb, the beforefilter on the controllers, etc.)
Hope this helps