Variable scoping and persistence

One of the main characteristics of the HTTP protocol is that it is stateless. Every request is completely independent from the others. Web programming is directly affected by this attribute, because in order to build a complete application and not just a bunch of responders, one needs to maintain some internal application state.

There are several ways to do this. For example, the state can be stored in the memory, in the disk as a file, in a database etc. Every web platform (like PHP, ASP, JSP etc) offers the required tools. However, PHP's tools are very poor, limited and not very convenient.

Oxygen offers a streamlined way to maintain the internal state between requests.

Variable lifecycle

In programming, every variable belongs has a scope which directly affects its life time. For example, a variable declared inside a function lives up to the end of that function. After that, it becomes out of scope and it is no longer accessible from the rest of the code. On the other hand, it the variable is declared as static, it lives up to the end of the application process and therefore it becomes out of scope only when the process is unloaded by the operating system.

In PHP, the application process process begins upon the reception of an HTTP request and ends when the response is sent back. There is no way to prolong this time. In addition, there is no way to open background processes that could live longer than that. What's more, there is absolutely no direct communication between the response processes or any way to directly share portions of memory. Therefore, it is not possible for a PHP variable to live longer than one request, unless it is copied somewhere else.

The faster way is to copy the variables to a part of memory which is marked as shared. PHP does not support this directly, however, this becomes possible with the installation of the extension APC (http://php.net/manual/en/book.apc.php). It this extension is installed, Oxygen will use it by default.

Another way is to store the variable in some file in the hard disk. This is not as fast as the memory, but still fast enough for most of the cases. Oxygen uses this mode if APC is not available. The files for the variables are stored in Oxygen's temp folder. See Seting up Oxygen for more info.

Serialization

In order to copy a variable to an external means, either the shared memory or the disk, it has to be serialized first, which means that it has to be converted to a string.

Most of PHP internal data types can be serialized automatically by the language itself. That includes the data types of string, int, float, boolean, null and array. However, the data types resource and callable cannot be serialized. Finally, the data type object can be serialized when the class provides the magic methods __sleep() and __wakeup() or by implementing the interface Serializable. Most of Oxygen's classes implement Serializable for this reason. See http://www.php.net/manual/en/language.oop5.serialization.php.

The scopes

Oxygen provides five scopes and the variables stored to each of them have different life times.

Application scope

A variable stored in the application scope theoretically lives up to the end of the web application (which is forever). In practice, however, this is much shorter, as every file in the temp folder is removed after one day. Yet, this is still very useful for caching data that takes long to be generated from scratch or from sharing data between all PHP processes of the web application.

// storing a variable to the application scope $x = 'Hello!'; Scope::$APPLICATION['my_shared_variable'] = $x; // reading a variable from the application scope $x = Scope::$APPLICATION['my_shared_variable']; echo $x; // output: Hello!

Database scope

A variable stored in the database scope is shared among all the processes that are connected to the same database schema. This scope is very useful for caching database operations. For more information on database connections see Connecting to databases.

// storing a variable to the database scope $x = 'Hello!'; Scope::$DATABASE['my_shared_variable'] = $x; // reading a variable from the database scope $x = Scope::$DATABASE['my_shared_variable']; echo $x; // output: Hello!

Session scope

A session is the group of all requests coming from the same browser. The identification of the brower is done with a cookie and therefore cookies must be enabled in order to make this scope work.

Unlike PHP's $_SESSION array, Oxygen's session scope (similar to all its scope constructs) uses a separate entry for every variable and does not need to load it unless been asked to. Therefore, it is possible to store variables with a big size without problem.

// storing a variable to the session scope $x = 'Hello!'; Scope::$SESSION['my_shared_variable'] = $x; // reading a variable from the session scope $x = Scope::$SESSION['my_shared_variable']; echo $x; // output: Hello!

Window scope

Many users use multiple tabs in the same browser in order to access different parts of a web application simultaneously. Variables strored to the window scope can be shared between all requests coming from the same browser tab. This is useful in order to share data between different ajax calls.

The identification of the browser tab is done with an extra argument in the query string. If Oxygen's action controller is used, this argument is automatically generated. However, this causes one extra HTTP request the first time each new tab is opened. If window scope is not used, it can be deactivated.

// deactivating window scope Oxygen::SetWindowScopingEnabled(false);

Storing a variable to the window scope and reading it back is no different:

// storing a variable to the window scope $x = 'Hello!'; Scope::$WINDOW['my_shared_variable'] = $x; // reading a variable from the window scope $x = Scope::$WINDOW['my_shared_variable']; echo $x; // output: Hello!

Request scope

The request scope is equivalent to PHP's static scope. It is offered here only for completeness and uniformity.

// storing a variable to the request scope $x = 'Hello!'; Scope::$REQUEST['my_shared_variable'] = $x; // reading a variable from the request scope $x = Scope::$REQUEST['my_shared_variable']; echo $x; // output: Hello!

Hard scopes

By default, all variables stored to one of the Oxygen's scopes will be put in the APC shared memory, if this is available. However, a variable put in the shared memory is not guaranteed to stay there. If memory is needed, some variables may be deleted. This is no problem if the data can be regenerated automatically.

However, there are some cases that the data cannot be regenerated. For instance, it is common practice to store the identification of the current user of a web application in the session scope. If this data is erased, it cannot be regenerated automatically; the user will have to log-in again.

To force a variable be kept in the disk, Oxygen offers the alternative scopes Scope::$APPLICATION->HARD, Scope::$DATABASE->HARD and Scope::$SESSION->HARD.

// storing a variable to the session scope, forced to be kept in the disk. Scope::$SESSION->HARD['idUser'] = $idUser; // reading a variable from the hard session scope $idUser = Scope::$SESSION->HARD['idUser'];