Jump to content

PHP Cookie Object

- - - - -

  • Please log in to reply
2 replies to this topic

#1
SoN9ne

SoN9ne

    Programmer

  • Members
  • PipPipPipPip
  • 129 posts
Here is a cookie object I use for my applications.
I decided to share this with the community as I hope it will help others.

/**

 * Cookie

 * @author Jeremy Simkins <son9ne@gmail.com>

 */

class Cookie {

	/**

	 * The time the cookie expires.

	 * This is a Unix timestamp so is in number of seconds since the epoch.

	 * In other words, you'll most likely set this with the time()  function plus the number of seconds before you want it to expire.

	 * Or you might use mktime(). time()+60*60*24*30 will set the cookie to expire in 30 days.

	 * If set to 0, or omitted, the cookie will expire at the end of the session (when the browser closes).

	 * @var int

	 */

	private static $expire = 0;


	/**

	 * The path on the server in which the cookie will be available on.

	 * If set to '/', the cookie will be available within the entire domain.

	 * If set to '/foo/', the cookie will only be available within the /foo/ directory and all sub-directories such as /foo/bar/ of domain.

	 * The default value is the current directory that the cookie is being set in.

	 * @var string

	 */

	private static $path;


	/**

	 * The domain that the cookie is available.

	 * To make the cookie available on all subdomains of example.com then you'd set it to '.example.com'.

	 * The . is not required but makes it compatible with more browsers.

	 * Setting it to www.example.com  will make the cookie only available in the www  subdomain.

	 * Refer to tail matching for details (http://curl.haxx.se/...ookie_spec.html).

	 * @var string

	 */

	private static $domain;


	/**

	 * Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client.

	 * When set to TRUE, the cookie will only be set if a secure connection exists.

	 * On the server-side, it's on the programmer to send this kind of cookie only on secure connection (e.g. with respect to $_SERVER["HTTPS"]).

	 * @var bool - true || false

	 */

	private static $secure;


	/**

	 * When TRUE the cookie will be made accessible only through the HTTP protocol.

	 * This means that the cookie won't be accessible by scripting languages, such as JavaScript.

	 * This setting can effectively help to reduce identity theft through XSS attacks (although it is not supported by all browsers).

	 * Added in PHP 5.2.0.

	 * @var bool - true || false

	 */

	private static $httponly;


	/**

	 * Initiate the Cookie object and set default values for cookies

	 * @param string $domain

	 * @param string $path

	 * @param bool $secure

	 * @param bool $httponly

	 */

	public static function init($domain = '', $path = '/', $secure = false, $httponly = false) {

		# Auto set the cookie name from the current domain unless a domain is given

		self::$domain = ( $domain ) ? $domain : ( isset( $_SERVER['HTTP_HOST'] ) ? ( ( substr( $_SERVER['HTTP_HOST'], 0, 4 ) == 'www.' ) ? substr( $_SERVER['HTTP_HOST'], 3 ) : '.' . $_SERVER['HTTP_HOST'] ) : '.weddingbudget.dev' );

		self::$path = $path;

		self::$secure = $secure;

		self::$httponly = $httponly;

	}


	/**

	 * Sets a Cookie

	 * @param string $name

	 * @param mixed $value

	 * @param bool $force - Force the Cookie to set for use on the same page (instead of next loading)

	 * @param int $expire - Set the cookie expiration (Defaults to user closes browser)

	 * @return bool

	 */

	public static function set($name, $value = '', $force = false, $expire = NULL) {

		/**

		 * Fix common pitfalls

		 */

		# Cookie value (A false value will delete the cookie, this will force the value as an int)

		if ( $value === true || $value === false ) {

			$value = (int) $value;

		}


		# Set the cookie value

		if ( $value ) {

			$value = base64_encode( serialize( $value ) );


			# Check cookie size

			if ( strlen( $value ) > ( 4 * 1024 ) ) {

				trigger_error( "The cookie {$name} exceeds the specification for the maximum cookie size.  Some data may be lost", E_USER_WARNING );

			}

		}


		# Force value into superglobal

		if ( $force ) {

			$_COOKIE[$name] = $value;

		}


		# Set the cookie

		return setcookie( $name, $value, ( ( $expire ) ? ( time() + (int) $expire ) : self::$expire ), self::$path, self::$domain, self::$secure, self::$httponly );

	}


	/**

	 * Checks is a cookie exist

	 * @param string $name

	 */

	public static function exist($name) {

		return isset( $_COOKIE[$name] );

	}


	/**

	 * Fetch a Cookie value

	 * @param string $name

	 * @return mixed

	 */

	public static function fetch($name) {

		return ( isset( $_COOKIE[$name] ) ) ? unserialize( base64_decode( $_COOKIE[$name] ) ) : NULL;

	}


	/**

	 * Removes a Cookie

	 * @param string $name

	 * @param bool $force - Force the cookie to delete (Will removed value from super global)

	 * @return bool

	 */

	public static function remove($name, $force = false) {

		# Ensure the cookie is set

		if ( isset( $_COOKIE[$name] ) ) {


			# Remove from superglobal

			if ( $force ) {

				unset( $_COOKIE[$name] );

			}


			# Remove the cookie

			return setcookie( $name, '', time() - ( 3600 * 25 ), self::$path, self::$domain, self::$secure, self::$httponly );

		}

	}

}

Cookie::init();

"Life would be so much easier if we only had the source code."

#2
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,118 posts
  • Location:Vancouver, Eh! Cleverness: 200
A few thoughts: If you are using a class, why throw a hard to capture trigger_error rather than a simple new exception? Why do you serialize and encode in base64 specifically? All browser items or other scripts wishing to access the cookie will need to decode it and unserialize it (you may as well use JSON at this point, faster and JS compatible.) Why return null instead of false on the fetch function when others such as exist() return true or false?

Also seems there is a hard coded domain feature relating to www. that may break.

Alexander.
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#3
SoN9ne

SoN9ne

    Programmer

  • Members
  • PipPipPipPip
  • 129 posts

Alexander said:

If you are using a class, why throw a hard to capture trigger_error rather than a simple new exception?
You are correct, an exception does make more sense.
This object is pretty old and I haven't updated it in a while. I had a few quick changes to it to put it up on here.
For my needs, I did not want an exception but just trigger an error. I didn't want the application to stop because the data I am saving in the cookie is not critical or really necessary for the script but I did want to log the issue. I am using custom error handling so I already have fail-safes in place to capture the error.

Alexander said:

Why do you serialize and encode in base64 specifically?
The data is serialized so I can store a simple array without having to create multiple cookies.
The base64 encoding is just to make it so it's slightly more difficult to view the cookie data, unless it's from the application.

Alexander said:

All browser items or other scripts wishing to access the cookie will need to decode it and unserialize it (you may as well use JSON at this point, faster and JS compatible.)
This is one reason the data is serialized and base64 encoded. I do not want the cookie to be used by JS (even though it still can be).
I was not too concerned with security of the data because I will not store anything sensitive in the cookie but I did not want to it to be too easy for normal users to see what was in the cookie.
Anyone with programming experience could easily see this is a base64 encoding and decode it.
As for JSON, a cookie fits my needs better but everyone has different needs.

Alexander said:

Why return null instead of false on the fetch function when others such as exist() return true or false?
False would work just fine and you are correct, that makes more sense. I used NULL instead because I may store false values but I will never store a NULL value.

Alexander said:

Also seems there is a hard coded domain feature relating to www. that may break.
Yeah, this was for my specific setup and will need to be modified for the user's needs.

Thanks for taking a look :-)
"Life would be so much easier if we only had the source code."




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users