You are viewing revision #2 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.
Cookie management in Yii is easy, but may not be so obvious for the beginners to this framework, so I wrote this simple article to clear some doubts out.
Cookie management ¶
Reading a cookie ¶
To read a cookie value, use following code:
$cookie = Yii::app()->request->cookies['cookie_name']->value;
See also "Safe reading" in the next chapter.
Writing a cookie ¶
To write a cookie value, use following code:
Yii::app()->request->cookies['cookie_name'] = new CHttpCookie('cookie_name', $value);
Notice, that cookie name must be given twice! See also "Reload required" in the next chapter.
Deleting a cookie ¶
To delete a cookie, use following code:
unset(Yii::app()->request->cookies['cookie_name']);
or you can delete ALL cookies with:
Yii::app()->request->cookies->clear();
Notice, that cookie will not be deleted until next page reload - see "Reload required" and "Cookie expiration problem" in the next chapter.
What to remember about? ¶
Cookies are objects ¶
Cookies in Yii are read from CHttpCookie which is an object, that's why you have add ->value to your code (see examples in previous chapter). If you omit that, you'll get warning or error saying that object of class CHttpCookie cannot be converted to a string.
Safe reading ¶
On the same basis, as above, if a particular cookie does not exists, a corresponding object (CHttpCookie instance) for it will not be created! Trying to read such cookie will result in error "Trying to get property of non-object". It avoid that, it is always better to read a cookie using ternary operator, like that:
$cookie = (isset(Yii::app()->request->cookies['cookie_name']->value)) ? Yii::app()->request->cookies['cookie_name']->value : '';
This way, you'll get either cookie value or an empty string.
This example also gives us idea how to check, if particular cookie exits:
$is_cookie = !empty(Yii::app()->request->cookies['cookie_name']->value);
Reload required ¶
Please, remember that server has actually nothing to do with the cookies. It only inform browser (in request result) about changes to cookies. Browser is responsible to do the job.
Therefore, cookies changes are NOT visible until next reload of page (next request). If you set a cookie value in some place in your code and try to read if few lines below, you'll get empty value or warning (or error in strict PHP mode).
This, of course, goes also to modifying cookie value or deleting them, which also requires reload of a page to succeed. Common pitfall, when developing shopping-cart-like solutions is to delete a cookie and testing if it exists in the same page. This will not work - cookie will not be deleted until next reload.
Cookie expiration problem ¶
If you set cookie like in above examples, it will be deleted automatically upon closing a browser (or clearing all cookies with proper option). Again - this is browser, not server job. You must close all open windows (copies) of browsers, because only then all cookies will be deleted. In some rare situation (browser hang-up) you can have a hidden copy (window) of a browser still in memory (on processes list) of which you may not be aware. Starting up new copy of browser will then show you all cookies that were meant to be deleted, as existing and having value - that is because that hidden window prevented browser from fully closing itself, and only then deletion of cookies is a fact.
To set a cookie that will not be deleted upon browser closure (like the one in default Yii login screen, where cookie is available for thirty days after last login), you must set it's expiration date. Like that:
$cookie = new CHttpCookie('cookie_name', $value);
$cookie->expire = time()+60*60*24*180;
Yii::app()->request->cookies['cookie_name'] = $cookie;
As, you can see - we're setting cookie expiration time relative to current time (first common pitfall) and as a timestamp, not date-time variable (second common pitfall). That is, why in above example we used time() PHP function.
We're counting expiration time in seconds (third common pitfall), so in above example we set cookie expiration date to be 180 days from this moment, which equal to 15 552 000 seconds, but it is of course easier to write it as equation.
Common settings for cookie expiration time:
- an hour: 3600 seconds,
- an day: 86400 seconds,
- a week: 604800 seconds,
- a month (unified = 30 days): 2592000 seconds,
- a year (unified = 12 months of 30 days): 31104000 seconds.
Further reading ¶
- CHttpCookie class reference,
- CCookieCollection class reference,
- Handling Cookies forum thread,
Please, extend this article, if you find any mistakes or that something is missing here.
Suggestion on Safe Reading
I don't know this is correct or not but, for me safe reading, should be like this:
$cookie = (isset(Yii::app()->request->cookies['cookie_name'])) ? Yii::app()->request->cookies['cookie_name']->value : '';
Because if the E_ALL is turn on, then it's still going to error, if the 'cookie_name' element is not defined.
Answer to suggestion on Safe Reading
@junxiong: Hm... I have E_ALL (or even higher - E_STRICT) turned on and was testing this piece of code and had no error on non-existing cookies. Maybe Yii handles this problem and returns empty string in such situation? I'm not sure...
But, after all - thanks! :] - it is always good to be safer, if you can - therefore, your solution won't hurt, if cookie exists and provides better security, if it doesn't. So I fully agree with you.
Delete cookie
Note, that unset(Yii::app()->request->cookies['cookie_name']) (or even unset($_COOKIE['cookie_name']) doesn't always work, because it doesn't delete cookie on client side. At least in my case this was a problem.
A solution to this is to set your cookie expiration time to one hour ago as was suggested in official php manual:
// set the expiration date to one hour ago setcookie ("TestCookie", "", time() - 3600); setcookie ("TestCookie", "", time() - 3600, "/~rasmus/", ".example.com", 1);
Cookie common pitfalls
Since internally Yii uses php's set_cookie(), take a look at their common pitfalls:
Be aware: do not use dots in cookie name
If you try to save a cookie with a dot ('.') inside the cookie name, it will be automatiaclly converted in a underscore ('_').
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.