Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Archive /

Our old forums are still available as a read-only archive.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo

Using Cookies - Short Tutorial


Go to End


3 Posts   5019 Views

Avatar
Double-A-Ron

Community Member, 607 Posts

15 June 2008 at 12:23pm

Edited: 15/06/2008 12:35pm

Hi everyone, I have set up a cookie system on the site I am working on for storing and changing a default currency for the visitor. Pretty simple stuff once I worked it out, but I found that there was little in the way of how-tos available so I am posting what I did here for future searchers.


What we are aiming for: We want to create a cookie for every user that stores a default currency to use across the site. This should be set to a default the very first time the user hits the site (no matter what page they hit). The user should also have the ability to change this setting, and keep it for the duration of their visit without further action. We also need a way to retrieve the value of this currency setting in our template.

You should be able to adapt this code to suit just about any similar site-wide and persistent user value storage you need.

1. Set the default currency. I have selected 'US' as the default currency. This needs to be done in a place that is accessable to all publically viewable pages so that it is set even if a site is found in a lower level page in a search engine. Since all of my pages and page types inherit from the Page class, it makes sense to do this in the PageController init() method:
/* /mysite/code/Page.php */
class Page extends SiteTree {
	static $db = array(
	);
	static $has_one = array(
   );
}

class Page_Controller extends ContentController {
	function init() {
		parent::init();
		
		Requirements::themedCSS("layout");
		Requirements::themedCSS("typography");
		Requirements::themedCSS("form");
		
		// Set default currency unless this is a returning visitor
		$CurrencyCookie = new Cookie;
		if(!$CurrencyCookie->get('site_currency')) {
			$CurrencyCookie->set('site_currency', 'US');
		}
	}
.....

The bolded code is all we need to add to /mysite/code/Page/php. Everything else is default. This code creates a new Silverstripe Cookie object first. This object is then used to see if a Cookie called 'site_currency' is stored on the user's machine using the Cookie object's 'get' method, which simply takes the name of the Cookie as is sole argument. If this Cookie doesn't exist, the code creates one using the Cookie object's 'set' method, which takes a name and a value as arguments. You may also pass an expiry for the Cookie as a third argument to 'set'. This is a number of days, and defaults to 90 if it is omitted.

A quick refresh and ?flush=1 of your page, and should now find a new Cookie in your browser called 'site_currency', with a default value of 'US', and an expiry date 3 months into the future.

Now we need a way to access the value of this Cookie in our templates. This is easy to achieve by adding this little function to /mysite/code/Page.php in the Page_Controller just under the init function that we added to above:
/* mysite/code/Page.php */
class Page_Controller extends ContentController {
	function init() {
		parent::init();
		
		Requirements::themedCSS("layout");
		Requirements::themedCSS("typography");
		Requirements::themedCSS("form");
		
		// Set default currency unless this is a returning visitor
		$CurrencyCookie = new Cookie;
		if(!$CurrencyCookie->get('site_currency')) {
			$CurrencyCookie->set('site_currency', 'US');
		}
	}
	
	function getCookieCurrency() {
		$CurrencyCookie = new Cookie;
		return $CurrencyCookie->get('site_currency');
	}

This simple function first creates a new Silverstripe Cookie object and uses it's 'get' method to return a Cookie called 'site_currency'. This will return the value of the Cookie to the template when we call it. We can now get this value in our template by simply doing this:
<h1>Your Selected Currency is $getCookieCurrency</h1>

This will display "Your Selected Currency is US".

But all of this is rather useless at this point, as we have no way of letting the user change the default currency value. We might as well just assume that all users are wanting US currency and not need the cookie at all. So we want to create a simple form on our page(s) so that a user can change the value, and save this value to the cookie so it saves their preference.
<p>Select a currency from the list below to update pricing across our site:</p>
            <form action="" method="get">
            	<select name="site_cur" id="site_cur">
                	<option value="US">US Dollars</option>
                    <option value="UK">Great Britain Pounds</option>
                    <option value="EU">European Euro</option>
                    <option value="AU">Australian Dollar</option>
                    <option value="NZ">New Zealand Dollar</option>
                </select>
                <input type="submit" value="Change Currency" />
            </form>

This is a very simple form that, when the submit button is hit, will refresh the current page with "site_cur=[value]" in the URL. We will use this URL value to set the Cookie. Note that the submit button does not have a name, this is so the button's value is not added to the URL too. A quick test of this form shows us that the URL is appending the selected currency selection correctly.

Now we need a way to detect if that URL value is present, and if so, use the value to set the Cookie to the user's preference. So back in the Page_Controller init function, we need to add another small block of code under where we set the default currency:
/* mysite/code/Page.php */
class Page_Controller extends ContentController {
	function init() {
		parent::init();
		
		Requirements::themedCSS("layout");
		Requirements::themedCSS("typography");
		Requirements::themedCSS("form");
		
		// Set default currency unless this is a returning visitor
		$CurrencyCookie = new Cookie;
		if(!$CurrencyCookie->get('site_currency')) {
			$CurrencyCookie->set('site_currency', 'US');
		}
		
		// If a site currency has been selected, save value to cookie
		if($_GET['site_cur']) {
			$CurrencyCookie->set('site_currency', strtoupper($_GET['site_cur']));
		}

	}

Pretty simple. This code will check the URL string for the presence of the "site_cur" value (e.g., the change currency form has been submitted). If it is set, we use the Silverstripe Cookie object again, but this time to overwrite the default value with what the user selected from the form we made. strtoupper() is optional, but a bit important in this case as we need to ensure that even if somewhere along the line, the "site_cur" value is entered in lowercase (e.g. 'us'), any future case sensitive comparisons do not give us bogus results.

And that's pretty much it. You should now have a persistent site-wide Cookie that is editable by you users.

This tute was really aimed at new SS users, so if anyone as further tips or code enhancements, please add them to this thread. The one obvious enhancement is a filter on allowable currency values when the Cookie is set.

Cheers
Aaron

Avatar
(deleted)

Community Member, 473 Posts

15 June 2008 at 1:05pm

Instead of creating a new instance of Cookie each time, you could just use the static methods Cookie::set(), Cookie::get() and Cookie::forceExpiry().

Avatar
Double-A-Ron

Community Member, 607 Posts

15 June 2008 at 1:09pm

Thanks Simon, I did attempt accessing those static methods at one stage in trying to work this out, but I got errors. This was early on, so I must have been doing something wrong or trying to access them out of scope. (I can't remember how I was using them, where I was using them or what the error was).


Cleans the code up a bit though. Thanks!
Aaron