silverstripe-framework/docs/en/reference/cookies.md
Daniel Hensby 3b9056fc01 NEW Cookie_Backend for managing cookie state
I've decoupled `Cookie` from the actual act of setting and getting
cookies. Currently there are a few limitations to how Cookie works that
this change mitigates:

0. `Cookie` currently changes the super global `$_COOKIE` when setting
to make the state of an application a bit more managable, but this is
bad because we shouldn't be modifying super globals
0. One can't actually change the `$cookie_class` once the
`Cookie::$inst` has been instantiated
0. One can't test cookies as there is no class that holds the state of
the cookies (it's just held in the super global which is reset as part
of `Director::test()`
0. One can't tell the origin of a cookie (eg: did the application set it
and it needs to be sent, or did we receive it from the browser?)
0. `time()` was used, so testing was made difficult
0. There was no way to get all the cookies at once (without accessing
the super global)

Todos are on the phpdoc and I'd like to write some tests for the backend
as well as update the docs (if there are any) around cookies.
DOCS Adding `Cookie` docs

Explains basic usage of `Cookie` as well as how the `Cookie_Backend`
controls the setting and getting of cookies and manages state of sent vs
received cookies
Fixing `Cookie` usage

`Cookie` is being used inconsistently with the API throughout framework.
Either by not using `force_expiry` to expire cookies or setting them to
null and then expiring them (which is redundant).
NEW `Director::test()` takes `Cookie_Backend` rather than `array` for `$cookies` param
2014-10-06 17:44:51 +13:00

3.2 KiB

Cookies

Accessing and Manipulating Cookies

Cookies can be set/get/expired using the Cookie class and its static methods

setting:

Cookie::set('CookieName', 'CookieValue');

getting:

Cookie::get('CookieName'); //returns null if not set or the value if set

expiring / removing / clearing:

Cookie::force_expiry('CookieName');

The Cookie class manipulates and sets cookies using a Cookie_Backend. The backend is in charge of the logic that fetches, sets and expires cookies. By default we use a the CookieJar backend which uses PHP's (setcookie)[http://www.php.net/manual/en/function.setcookie.php] function.

The CookieJar keeps track of cookies that have been set by the current process as well as those that were recieved from the browser.

By default the Cookie class will load the $_COOKIE superglobal into the Cookie_Backend. If you want to change the initial state of the Cookie_Backend you can load your own backend into the CookieJar service registered with the Injector.

eg:

$myCookies = array(
	'cookie1' => 'value1',
);

$newBackend = new CookieJar($myCookies);

Injector::inst()->registerService($newBackend, 'CookieJar');

Cookie::get('cookie1'); //will return 'value1'

Assuming that your appliation hasn't messed around with the $_COOKIE superglobal, you can reset the state of your Cookie_Backend by simply unregistering the CookieJar service with Injector. Next time you access Cookie it'll create a new service for you using the $_COOKIE superglobal

eg:


Injector::inst()->unregisterNamedObject('CookieJar');

Cookie::get('cookiename'); //will return $_COOKIE['cookiename'] if set

Alternatively, if you know that the superglobal has been changed (or you aren't sure it hasn't) you can attempt to use the current CookieJar service to tell you what it was like when it was registered.

eg:


//store the cookies that were loaded into the `CookieJar`
$recievedCookie = Cookie::get_inst()->getAll(false);

//set a new `CookieJar`
Injector::inst()->registerService(new CookieJar($recievedCookie), 'CookieJar');

If you need to implement your own Cookie_Backend you can use the injector system to force a different class to be used.

example:

Injector:
  CookieJar:
    class: MyCookieJar

To be a valid backend your class must implement the Cookie_Backend interface.

Advanced Usage

Sent vs Received Cookies

Sometimes it's useful to be able to tell if a cookie was set by the process (thus will be sent to the browser) or if it came from the browser as part of the request.

Using the Cookie_Backend we can do this like such:


Cookie::set('CookieName', 'CookieVal');

Cookie::get('CookieName'); //gets the cookie as we set it

//will return the cookie as it was when it was sent in the request
Cookie::get_inst()->get('CookieName', false);

Accessing all the cookies at once

One can also access all of the cookies in one go using the Cookie_Backend


Cookie::get_inst()->getAll(); //returns all the cookies including ones set during the current process

Cookie::get_inst()->getAll(false); //returns all the cookies in the request