# Introduction

Cherrycake is a low-level programming framework for developing modular, efficient and secure PHP web applications.

Instead of a comprehensive, all-in-one web app building environment, Cherrycake aims only to provide a strong foundational layer and methodology that feels comfortable, rational and easy to use while prioritizing this three main goals:

* **Modularity**
  * Provides scalability, standardization and code tidiness.
* **Performance**
  * Maximizes response times and reliability even in very high traffic scenarios.
* **Security**
  * Identifies, blocks and reacts to known attack vectors.

{% hint style="success" %}
Cherrycake is aimed at curious developers and students in the mood for creating a new framework or learning about techniques to do so. If you're one of those, Cherrycake can bring you inspiration, and maybe even provide a foundational layer you can build upon.
{% endhint %}

{% hint style="success" %}
Because Cherrycake is not being maintaned by a big or active community like other akin frameworks, it's not recommended for production use, and is presented only for educational purposes.
{% endhint %}

## Applications

Because Cherrycake sits and stays at the lower level of the server application, it provides you with a clean slate to build any kind of website, but also: API endpoints, client-server architectures, proxy-like architectures, resource serving services, servers for system interfacing or batch processors for example.

Because of this architecture, Cherrycake might come in handy when building websites of any complexity, but could also be a great partner for your client-side JavaScript application by providing the API it needs. Similarly, Cherrycake might be a good starting point if you're experimenting with new ways of using the Internet, or it could even be a strong foundation if you're developing your own server application programming framework.

## Philosophy

Server web app programming frameworks that reach higher implementation levels come inevitably with some loss of control and detachment from the finer details in favor of practicality, standardization and improved development speed. For the vast majority of developers this loss of control is negligible, and the benefits they provide far outweigh the loss.

{% hint style="success" %}
Cherrycake is recommended to web developers who prefer to stay closer to the metal to regain control of every possible finer detail of their application, at the expense of the benefits of higher level frameworks.
{% endhint %}

Very often, this need of control, more than a rational or optimal decision, is simply an emotional manifestation of passionate programmers who enjoy digging deep in the understanding of how a system works and how it can be improved, who like to defy standards and enjoy coming up with their own solutions, even when there already are solutions available.

In that sense, even though Cherrycake also provides many higher level modules, it's defined as a low-level framework because instead of aiming to provide a suite of ready-made solutions for an optimized development cycle, it focuses on providing a strong foundation for you to create them.

## Purpose

Cherrycake is not a replacement for fully-fledged, widely-supported and well-known frameworks like Laravel or Symfony. If you're looking for alternatives to those frameworks, you're looking in the wrong place!


# Status

Although Cherrycake is still under heavy development and it's still in a beta stage, it's functional and it's already running some public web applications without issues. It's still not recommended to use Cherrycake in critical, or data sensitive applications.

Instead, you're encouraged to try it to see for yourself whether it meets your security and stability requisites, and to contribute your suggestions or improvements via the official git repositories.

You might find Cherrycake to perfectly match your needs for your upcoming project, or it might simply become a fun way to contribute and experiment with a newly born engine.


# Changelog

Cherrycake adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), meaning version numbers match the **`<Major>`**`.`**`<Minor>`**`.`**`<Patch>`** syntax:

* **Major** version numbers change when there are changes that are incompatible with earlier major versions. For example: A Cherrycake application using major version `0` will need to be heavily modified in order to work with version `1`.
* **Minor** version numbers change when there are new functionalities or improvements that are compatible with earlier minor versions. For example: A Cherrycake application using version `0.3.x` will work without much changes or no changes at all when upgraded to Cherrycake version `0.4.x`.
* **Path** version numbers change when there are updates that solve bugs in a completely backwards compatibility fashion. For example: A Cherrycake application using version `0.3.4` will work without any changes at all when upgraded to `0.3.5`.

## Version 1.0.0b

A major upgrade released on 2021-05-29, mainly based around leveraging class discovery to [composer](https://getcomposer.org), and better organizing the code into namespaces and subnamespaces. UI Components are entirely removed after being considered as an obsolete UI architecture, and re-formulating Cherrycake's scope to not impose any UI-specific architecture. See the [Migration](/version-0.x/migration#migrating-from-0-x-to-1-x) section for a guide on how to migrate your existing Cherrycake version 0.x application to version 1.x.

### Changed

* Composer-based autoloading system, a standard class and module autloading mechanism that simplifies overall structure for Cherrycake apps.
* Core modules are now stored in /src//.php
* Core classes are now stored in /src/.php
* App module are now stored in /src//.php by default
* App classes are now stored in /src/.php by default
* Modules are now set in their own subnamespace inside the `Cherrycake` namespace. For example, the `Actions` module now resides in the `\Cherrycake\Actions` namespace and the `Output` module now resides in the `\Cherrycake\Output` namespace.
* Because modules now reside in their own subnamespace, classes related to specific modules also reside now in the matching subnamespace. For example, the `Action`, `ActionHtml`, `Request`, `RequestPathComponent` and alike all now reside in the `\Cherrycake\Actions` namespace.
* Class and module files must now have `.php` extension instead of `.class.php`
* Module configuration files are now autodetected, so `isConfigFile` property for modules is no longer needed.
* Janitor tasks configuration files are now autodetected, so `isConfigFile` property is no longer needed.
* Global constants are declared in `/constants.php`.
* Autoloading of classes is now handled via composer, so you need to add this to your `composer.json` file:

  ```javascript
  "autoload": {
    "psr-4": {
        "CherrycakeApp\\": "src/"
    }
  }
  ```

### Removed

UIComponents are no longer part of Cherrycake because they were based on an obsolete web design standard, in favor of modern web UI techniques.


# Migration

Instructions on how to migrate your existing Cherrycake application from earlier versions of the Cherrycake engine.

## Migrating from 0.x to 1.x

* Update your `composer.json` file to require Cherrycake version 1.x instead of version 0.x:

  ```bash
    composer update
  ```
* Create the `src` directory in your project and move your modules there. Remember modules still have their own subdirectory under `src`. You can remove the now empty `Modules` directory.
* Move all your classes to the `src` directory. Remember classes do not have their own subdirectory, so they reside on the root of `src`. You can remove the now empty `Classes` directory.
* Rename all your modules and class files so they end with `.php` instead of `.class.php`. For example: `MyModule.php` instead of `MyModule.class.php`.
* Assign all your modules to their own namespace by modifying or adding a `namespace` directive at the top of the file. For example, if your module is called `MyModule`, you should add this at the top of `src/MyModule/MyModule.php`:

  ```php
    namespace \CherrycakeApp\MyModule;
  ```
* Remember also to correctly namespace the class your modules extend from. For example, instead of your module being declared like this:

  ```php
    class MyModule extends Module {
  ```

  declare it like this instead:

  ```php
    class MyModule extends \Cherrycake\Module {
  ```
* Assign all your classes the right namespace. If they're classes related to a module, move them to the related module's directory and add the matching namespace. For example, if your class is called `ClassForMyModule` and is related to a module called `MyModule`, move it to `src/MyModule`and add this at the top of `src/MyModule/ClassForMyModule.php`:

  ```php
    namespace \CherrycakeApp\MyModule;
  ```
* You'll need to change how you reference Cherrycake's core modules and classes throughout your code. For example, the following code:

  ```php
    $e->Actions->mapAction(
        "homePage",
        new \Cherrycake\Action([
            "moduleType" => ACTION_MODULE_TYPE_APP,
            "moduleName" => "Home",
            "methodName" => "homePage",
            "request" => new \Cherrycake\Request([
                "pathComponents" => false,
                "parameters" => false
            ])
        ])
    );
  ```

  Should be changed to this:

  ```php
    $e->Actions->mapAction(
        "homePage",
        new \Cherrycake\Actions\Action([
            "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
            "moduleName" => "Home",
            "methodName" => "homePage",
            "request" => new \Cherrycake\Actions\Request([
                "pathComponents" => false,
                "parameters" => false
            ])
        ])
    );
  ```
* Autoloading of classes is now handled via composer, so you need to add this to your `composer.json` file:

  ```javascript
    "autoload": {
        "psr-4": {
            "CherrycakeApp\\": "src/"
        }
    }
  ```
* Update composer's autoload by running the command:

  ```bash
    composer dump-autoload
  ```
* See the documentation at [cherrycake.io](https://cherrycake.io) and the examples at [documentation-examples.cherrycake.io/](https://documentation-examples.cherrycake.io/) to see examples using this new namespacing.


# Basics

At its simplest, Cherrycake can be understood primarily as request router. That is, the mechanism that receives requests, hands them over to the proper module for processing, and then hands over whatever resulted from the processing to whoever did the request in the first place.

![](/files/-M4p1B1mJGtsb2kMn8c7)

Cherrycake runs as a PHP application typically behind an HTTP server like NGINX, receiving all relevant requests and connecting with any third party sources like MySQL or Redis when needed.

> Cherrycake apps can also run as [command line apps](/version-0.x/guide/cli).

Without some of the oversimplification of the diagram above, a more accurate representation of the overall architecture of a simple application running Cherrycake looks like this:

![](/files/-M4pB6F3_yY_c5PsN71B)


# Modules

Modules pack process-specific functionality in isolated classes with auto-loading, dependency and configuration capabilities, so it's easier to keep your app structure clean and clear.

In Cherrycake, all process-specific functionality is packed in modules. A great example is the [Database](/version-0.x/reference/core-modules/database) module, which is in charge of all the communication with a server like MySQL.

### Dependency

Most modules depend on others to do their job. When this happens, dependencies are solved automatically and all the needed modules are loaded on the fly. For example, the [Database](/version-0.x/reference/core-modules/database) module might need at some point the [Security](/version-0.x/architecture/security) module to ensure the data you're storing in the database is safe.

### Module configuration

Modules can have configuration files. For example, the [Database](/version-0.x/reference/core-modules/database) module requires a configuration file where you set up a MySQL server address, user and password. User modules can have configuration files too.

### Actionability

Modules can respond to requests, so they're the entry point in the [Lifecycle](/version-0.x/architecture/lifecycle) of a request to any Cherrycake application. The [Actions](/version-0.x/reference/core-modules/actions-1/actions) module takes care of routing requests to the matching mapped modules.


# Classes

Classes encapsulate the object-specific structure and logic of entities in Cherrycake and in your application.

Additionally to your own class implementations, Cherrycake provides core classes for entities that are used throughout the engine and that you can use or extend in your application, like the [Result](/version-0.x/reference/core-classes/result) class, which represents the result of an operation of any kind, or the [Color](/version-0.x/reference/core-classes/color) class, which simply represents a color.

> A more complex example of core classes is the [Item](/version-0.x/reference/core-classes/item) class, which provides many useful methods to work with abstractions of objects, or the [Items](/version-0.x/reference/core-classes/items) class, which provides methods to work with lists of [Item](/version-0.x/reference/core-classes/item) objects.

### Auto-loading

Classes are automatically loaded whenever they're needed, meaning you don't need to predict which classes you'll be using.

### What's the difference between a class and a module?

Modules are intended to pack **process-specific** functionality, can be triggered with actions (see [Lifecycle](/version-0.x/architecture/lifecycle)), can have configuration files and can even depend on other modules. Classes are intended to pack **object-specific** functionality, cannot be triggered with actions and don't get configuration files.

{% hint style="info" %}
**Example**

If you're creating a social networking web application, the code to show the user profile page would go in a **module** you might want to call *ProfilePage*. In the other hand, you might want to have a *User* **class** to hold the information and the logic for that specific user.

In your architecture, the *ProfilePage* module will query the [Database](/version-0.x/reference/core-modules/database) module for a specific user, and you'll get a *User* object in return. The *ProfilePage* module will then take care of building and showing the profile page using that *User* object, most probably using the [Patterns](/version-0.x/reference/core-modules/patterns) module.
{% endhint %}


# Lifecycle

Understanding the lifecycle of a request in Cherrycake will give you valuable insight on how it works.

We'll first go through a simplified version of the lifecycle of a request, assuming we're building a website application and our client is a web browser.

When a Cherrycake application receives a request, it first loads some initial modules like [Output](/version-0.x/reference/core-modules/output), [Errors](/version-0.x/reference/core-modules/errors) and [Actions](/version-0.x/reference/core-modules/actions-1/actions). These are the modules that Cherrycake needs to determine what to do next:

![](/files/-M4tFkH9Hx4qJrI-UTnc)

Cherrycake now asks the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module to attend the received request:

![](/files/-M4tFmqfDblyjsG0DiYA)

To do so, [Actions](/version-0.x/reference/core-modules/actions-1/actions) checks the requested route to see which modules have mapped an action. If it founds a mapped action that matches the current request, loads and runs the module who mapped it.

Let's say the browser requested the home of our website by requesting the `/` route, and that this route has been mapped by a module we called *Home*. Cherrycake loads this module and runs it:

![](/files/-M4tFpKC9HXSFJxnqbyy)

*Home* is an app module (as opposed to a core module), and is in charge of showing the home page of the website. To do so, *Home* uses the [Patterns](/version-0.x/reference/core-modules/patterns) core module to load an HTML file from disk and then send it to the browser. Since the [Patterns](/version-0.x/architecture/patterns) module has not been loaded yet, Cherrycake loads it automatically:

![](/files/-M4tFsUD3O4DOko20OEU)

Since all output is handled by the [Output](/version-0.x/reference/core-modules/output) core module, [Patterns](/version-0.x/reference/core-modules/patterns) reads the requested HTML file and uses [Output](/version-0.x/reference/core-modules/output) to send back the response to the Browser, and the request lifecycle concludes.

![](/files/-M4tGJeQo1neqRGv84KB)

Now let's take a deeper look at how all this happens with some code, in the [Deep lifecycle](/version-0.x/architecture/lifecycle/deep-lifecycle) section.


# Deep lifecycle

Let's take a deep dive on a typical request lifecycle.

To deeper understand the lifecycle of a request, we'll use the same example as in the [Lifecycle](/version-0.x/architecture/lifecycle) section, but this time we'll stop and see with greater detail everything that happens behind the scenes, this will give you a better understanding of the Cherrycake architecture.

{% hint style="info" %}
If you'd rather prefer to start working with Cherrycake and skip this section about the inner workings of Cherrycake, go straight to the [Getting started](/version-0.x/guide/getting-started) guide, or keep on learning about the Cherrycake architecture in the [Performance](/version-0.x/architecture/performance) section.
{% endhint %}

When a request is received, the `index.php` file in your App's public directory is executed. This is the entry point for all requests to your Cherrycake application, and all it does is loading Cherrycake, initialize it and call the [Engine::attendWebRequest](/version-0.x/reference/core-classes/engine/methods#attendwebrequest) method. This looks something like this:

```php
namespace CherrycakeApp;
require "vendor/tin-cat/cherrycake-engine/load.php"

$e = new \Cherrycake\Engine;

if ($e->init(__NAMESPACE__, [
    "baseCoreModules" => ["Actions"]
]))
    $e->attendWebRequest();

$e->end();
```

When the engine is initialized with [Engine::init](/version-0.x/reference/core-classes/engine/methods#init), it loads and initializes the modules specified in `baseCoreModules`. Since the [Actions](/version-0.x/reference/core-modules/actions-1/actions) modules is the one in charge of receiving and handling requests, you should at least specify this module on the list.

> The default value for the `baseCoreModules` key is `["Actions"]`, so if you only need the Actions module like in our example, you can skip this key on the hash array and it will be included automatically. In the example, this means we can simplify the [Engine::init](/version-0.x/reference/core-classes/engine/methods#init) line to just `$e->init(__NAMESPACE__)`

During its initialization, the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module loops through all available modules and asks them to map whatever actions they might need. It does so by using the [Engine::callMethodOnAllModules](/version-0.x/reference/core-classes/engine/methods#callmethodonallmodules) method, which goes through all the available modules and executes the specified static method name, like this:

```php
$e->callMethodOnAllModules("mapActions");
```

> To optimize performance, the method [Engine::callMethodOnAllModules](/version-0.x/reference/core-classes/engine/methods#callmethodonallmodules) caches the information about which methods are available in modules so it doesn't need to search for those methods each time a request is made.

All `mapActions` methods found in any of the available modules (both core and app modules) are executed, so any module that needs to map an action to respond to requests must do it so on its `mapActions` static method by calling the[ Actions::mapAction](/version-0.x/reference/core-modules/actions-1/actions#mapaction) method. In our *Home* example module, this would look like this:

```php
public static function mapActions() {
	global $e;
	$e->Actions->mapAction(
		"homePage",
		new \Cherrycake\Action([
			"moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
			"moduleName" => "Home",
			"methodName" => "homePage",
			"request" => new \Cherrycake\Request([
				"pathComponents" => false,
				"parameters" => false
			])
		])
	);
}
```

Now that we have all the possible actions mapped, the call to[ Engine::attendWebRequest](/version-0.x/reference/core-classes/engine/methods#attendwebrequest) in `index.php` asks the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module to find and run the action that matches the current request URI. This is how this request to the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module looks internally:

```php
$this->Actions->run($_SERVER["REQUEST_URI"]);
```

Since the browser in our example has requested the root page of our website, the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module searches all the mapped actions for one that matches the current "/" request, and finds the action named "homePage".

> Notice that this action matches our example request of the home page (`/` path) because it specifically has no `pathComponents`

In the declaration of this [Action](/version-0.x/reference/core-classes/action) the `moduleName` and `methodName` keys are used to specify which module::method should be called when the action is executed. In our example, *Home::homePage.*

> Cherrycake provides a request-level cache. At this point, if the requested [Action](/version-0.x/reference/core-classes/action) has been cached, the result is obtained from cache and the execution ends here.

The *Home* module will use the [Patterns](/version-0.x/reference/core-modules/patterns) module to retrieve an HTML file and send it back to the browser, this is why this dependency is specified on the `dependentCoreModules` property of *Home*, like this:

```php
var $dependentCoreModules = [
    "Patterns"
];
```

Now *Home::homePage* uses the method [Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out) to send the HTML file to the browser, like this:

```php
function homePage() {
    global $e;
    $e->Patterns->out("Home/Home.html");
    return true;
}
```

In turn, [Patterns](/version-0.x/reference/core-modules/patterns) depends on the [Output](/version-0.x/reference/core-modules/output) module, which was loaded and initialized automatically as soon as the chain of dependencies started, when our *Home* module was loaded.

Since [Patterns](/version-0.x/reference/core-modules/patterns) is actually a parser, it not only loads the HTML file, but also parses it using [Patterns:parse](/version-0.x/reference/core-modules/patterns#parse-patternname-setup) and then sends the result as a [ResponseTextHtml](/version-0.x/reference/core-classes/response) object to [Output::setResponse](/version-0.x/reference/core-modules/output#setresponse-response), like this:

```php
$e->Output->setResponse(new \Cherrycake\ResponseTextHtml([
			"code" => $code,
			"payload" => $this->parse($patternName, $setup)
]));
```

When the execution is about to end, the [Engine](/version-0.x/reference/core-classes/engine) calls the `end` method on all loaded modules. The [Output](/version-0.x/reference/core-modules/output) calls [Output::sendResponse](/version-0.x/reference/core-modules/output#sendresponse-response) on its `end` method, causing the parsed HTML file to be sent to the browser and concluding the request lifecycle.


# Performance

Cherrycake is capable of handling a high number of requests per second in a reasonable server setup, let's take a look at the most important performance features and tools it provides.

### Optimum loading

Modules are loaded only when they're needed, on the fly, and in a per-request basis. This guarantees that each request to the server will only load the code it needs to work, reducing memory usage and latency.

### Four level caching

Cherrycake comes with a solid caching system, implemented in four levels throughout the [lifecycle](/version-0.x/architecture/lifecycle) of a request:

* **Request level cache**
  * Each request can be configured to be cacheable, meaning that requests that have been cached will be served much earlier in the request lifecycle, sparing memory and server usage and critically improving latency.
* **Template level cache**
  * Template files, even when they contain logic and PHP code, can be cached. meaning, for example, that you can fine tune specific sections of a web page to be cached while keeping others live. Since Cherrycake templates can work with HTML, CSS, JavaScript and any other kind of files, this template-level caching logic can be used in many creative ways.
* **Item level cache**
  * The logical items of your applications are represented as objects in Cherrycake called [Items](/version-0.x/reference/core-classes/item), and this Items can be cached with their own caching mechanism. Whenever you work with, for example, users from a database or posts in a blog, each user and post can be cached according to your needs, meaning it will load much faster in subsequent requests. Groups of multiple [Items](/version-0.x/reference/core-classes/items) like database searches, filtered search results or paged listings can also be cached automatically.
* **Database level cache**
  * For your convenience, all SELECT operations in a database can be cached really easily. You can model your caching logic for database retrieval around your specific needs.

Also, you can use the [Cache](/version-0.x/reference/core-modules/cache) system yourself for any other needs you might have. Besides the usual key-value caching methods, it provides a connection-agnostic abstraction layer, object caching, queue lists, push-pop lists and cache pools.

### Web optimizations

Cherrycake automatically minimizes CSS and JavaScript code, it allows you to implement PHP logic into your CSS/JavaScript files and also joins all of them into one single request to improve loading and rendering times.

When needed, images are automatically resized, re-framed and compressed to obtain multiple variants for different purposes.

This loading optimizations, along with the small latencies that can be obtained with the optimized request lifecycle and the multilevel caching benefits, make for web applications with excellent [Google Pagespeed Insights](https://developers.google.com/speed/pagespeed/insights/) ranks.


# Security

Cherrycake structure has been modeled from the ground up with security in mind. Let's explore its most important security features.

### Request security

All requests are predefined with a specification of parameters, their expected types and validation methods. This makes for a strong first security layer that blocks anything that doesn't looks like a request our app would expect.

### Injection prevention

[SQL injection](https://en.wikipedia.org/wiki/SQL_injection) and [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) attack vectors are monitored from the very moment a user-provided data enters the App, to the moment it is stored on the database.

### CSRF detection

Cherrycake implements a [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) threat detection mechanism automatically integrated into all sensible requests.

### Threat logging and blocking

Cherrycake can log all attacks and keep track of suspicious IPs, automatically blacklisting clients that have passed a configured threshold.

### Secure user authentication and session tracking

Cherrycake provides a secure user authentication and session tracking mechanisms using modern password encryption and server-based session data storage.

### Scalability

Thanks to a thorough [lifecycle](/version-0.x/architecture/lifecycle) and its modular structure, Cherrycake allows for the easy implementation of new security mechanisms and the improvement of the existing attack detection routines. We encourage you to contribute your suggestions, ideas and security improvements through the official [GitHub](https://github.com/tin-cat/cherrycake-engine) repository.


# Patterns

Cherrycake provides a patterns parser that uses PHP code to integrate your code seamlessly with your template files, providing advanced Cherrycake capabilities to your template structures.

When working in conjunction with Cherrycake, [Patterns](/version-0.x/reference/core-modules/patterns) becomes a powerful template parser that not only allows you to use templates for your HTML files, but also for your Css, JavaScript and any other kinds of files where you might need template-like capabilities.

These are the most interesting capabilities [Patterns](/version-0.x/reference/core-modules/patterns) brings to your app:

* Lets your HTML, CSS and JavaScript code reside in patterns outside your PHP.
* Because you can unlimitedly nest patterns, you can create neat pattern structures for re-usability.
* Patterns can receive variables, making for an interesting way of reusing HTML code as objectified fragments, and other similar applications.
* Pattern files can get access to the entire Cherrycake engine, so you can use Cherrycake PHP code in your patterns.
* No need to learn a pattern language, just use PHP. Conditional statements, loops and any other PHP code will work in a pattern.
* [Patterns](/version-0.x/architecture/patterns) works with the [Cache](/version-0.x/reference/core-modules/cache) module to provide a pattern-level cache, meaning that individual patterns can be cached as you like to improve performance. Because patterns can be nested, you can cache only the patterns that contain static or almost static information, and let only patterns with dynamic information be parsed each time they're used.
* The [Css](/version-0.x/reference/core-modules/css) and [JavaScript](/version-0.x/reference/core-modules/javascript) modules work with Patterns too, bringing all this capabilities also to your Css and JavaScript files.

Because [Patterns](/version-0.x/reference/core-modules/patterns) is actually a Cherrycake core module, you can use any other template parser you like in your Cherrycake app, build your own or get rid of any template mechanism if you like.

> See the [Patterns guide](/version-0.x/guide/patterns-guide) for a guide on how to use this module.


# Files structure

Let's take a look at how are directories organized in a typical Cherrycake App setup, and the file naming conventions.

{% tabs %}
{% tab title="/" %}
The root of your Cherrycake App directory. Can be placed anywhere in your server, a usual choice would be `/var/www/AppName`

In its most basic form, it contains at least one important file:

* **composer.json**
  * Cherrycake uses [composer](https://getcomposer.org/) to manage dependencies. Modify this file to add your own dependencies if needed. To make your Cherrycake application work, the dependency `tin-cat/cherrycake-engine` is required.
    {% endtab %}

{% tab title="/src" %}
Contains your [modules](/version-0.x/architecture/modules), each one in a subdirectory named in the syntax:

`/src/<ModuleName>/<ModuleName>.php`

Also contains your [classes](/version-0.x/architecture/classes), each in one file named in the syntax:

`/src/<ClassName>.php`

It is recommended that modules follow the naming [conventions](/version-0.x/conventions). For example, the following module:

```php
namespace CherrycakeApp\Home;

class Home extends \Cherrycake\Module {
    [...]
}
```

Must be saved in a file here:

`/src/Home/Home.php`

And the following class:

```php
namespace CherrycakeApp;

class User extends \Cherrycake\Item {
    [...]
}
```

Must be saved in a file here:

`/src/User.php`
{% endtab %}

{% tab title="/config" %}
Contains the configuration files for your modules, if they need one. The syntax of this files is:

`/config/<ModuleName>.config.php`

For example, the configuration file for the module \_Home m\_ust be saved in a file here:

`/config/Home.config.php`

> Check the [Module config files](/version-0.x/guide/modules-guide#modules-config-file) documentation for more information

This directory also holds the configuration files for [Janitor Tasks](/version-0.x/guide/janitor-guide/janitor-tasks-configuration-files).
{% endtab %}

{% tab title="/patterns" %}
Contains the HTML files to be used by the [Patterns](/version-0.x/reference/core-modules/patterns) module. This directory can be set to anything else by changing the `directory` config key of the [Patterns](/version-0.x/reference/core-modules/patterns) module.
{% endtab %}

{% tab title="/public" %}
This is the directory that gets exposed publicly by an HTTP server like NGINX. It must have at least an `index.php` file to load the Cherrycake engine and attend requests.

Check out the [Getting started](/version-0.x/guide/getting-started) section to learn how to build this index file, or use the readily provided with the [Skeleton](/version-0.x/guide/getting-started/skeleton) or [Docker](/version-0.x/guide/getting-started/docker) methods.
{% endtab %}
{% endtabs %}

### Other files and directories

There are some other non-required files and directories in a typical Cherrycake app, you'll find some of them there if you create your Cherrycake App using a boilerplate like the [Cherrycake Skeleton](/version-0.x/guide/getting-started/skeleton).

{% tabs %}
{% tab title="/" %}
If you've used the [Cherrycake Skeleton](/version-0.x/guide/getting-started/skeleton) to start your app, you'll also find this files in your app's root directory:

* **cherrycake**
  * An executable script that allows you to perform a [cli](/version-0.x/guide/cli) call to the Cherrycake application from the server command line.
* **LICENSE\_Cherrycake**
  * This contains the license disclaimer for the Cherrycake engine, please keep this file untouched in all your Cherrycake projects.
* **cli.php**
  * A PHP script to launch a [cli](/version-0.x/guide/cli) request to the Cherrycake application. This PHP file is used by the `cherrycake` script.
* **load.php**
  * A convenience loader for the Cherrycake engine, used by any other scripts that need to run the Cherrycake engine, like `cli.php`, or `public/index.php`
    {% endtab %}

{% tab title="/usr" %}
Usually, this directory is used to store files uploaded by the users of an app. For example: If your app allows your users to upload their profile images, this is where you could be saving them using the [Image](/version-0.x/reference/core-classes/image) core class.
{% endtab %}

{% tab title="/errors" %}
This directory holds the HTML files the [Errors](/version-0.x/reference/core-modules/errors) shows to the browser when errors occur. You change this to a different directory by setting the `patternNames` key in the [Errors](/version-0.x/reference/core-modules/errors) module configuration file.
{% endtab %}

{% tab title="/install" %}
Some Cherrycake modules make use of the database. This directory contains the SQL files needed to create the database tables needed for those Cherrycake modules.

For example, if you plan to use the [Session](/version-0.x/reference/core-modules/session) module to manage your web app user sessions, you'll need to create the `cherrycake_session` table in your database by using the script `session.sql` you'll find in this directory.
{% endtab %}

{% tab title="/vendor" %}
This is the usual directory managed by [Composer](https://getcomposer.org/) to hold all the dependency libraries, including the Cherrycake engine itself.
{% endtab %}
{% endtabs %}


# Items

Cherrycake provides you with an optimized way of interacting with the primordial objects of your app.

Items are Cherrycake's conceptualization of the fundamental objects stored in a database. For example, in an e-commerce site, a product would be an Item, but also would a user, a product category or an invoice.

The most interesting benefits of working with Items in Cherrycake are:

* Items can be easily retrieved, updated or deleted from the database, there's no need to implement your own database access code.
* All security-sensible operations with Items are supervised by the Cherrycake [Security](/version-0.x/architecture/security) mechanisms.
* Items get all the [performance](/version-0.x/architecture/performance) and caching benefits of Cherrycake right out of the box.
* Items support multi language fields, multi-timezone date-time fields, automatic URL slug generation and much more.

> See the [Items guide](/version-0.x/guide/items-guide) to learn how to work with Items in Cherrycake


# Server requirements

### Minimum requirements

* **Linux** operating system. Other operating systems should work without problems but haven't been tested.
* **HTTP Server**, NGINX is recommended, Apache HTTPd should work without problems but hasn't been tested.
* **PHP**, version >= 7
  * **apcu** extension (`opcache` package)
  * **json** extension
  * **mbstring** extension (if not available, use **libonig**)
* [**Composer**](https://getcomposer.org/)

### Dependency requirements

* If you're going to use databases ([Database](/version-0.x/reference/core-modules/database) module)
  * **MariaDB Server**, MySQL also supported
  * **pdo\_mysql** and **mysqli** PHP extensions
* If you're going to use advanced cache
  * **Redis** **Server**
* If you're going to use Image manipulation ([Image](/version-0.x/reference/core-classes/image) class)
  * **gd** PHP extension
  * **LibJPEG**
  * **LibPNG**
* If you're going to connect to external sources like APIs
  * **openssl**
  * **curl**


# Getting started

A simple guide to build a simple "Hello world" application with Cherrycake.

In this guide we'll be creating a simple web application with Cherrycake that shows the well known "Hello world" message in the browser. We won't be using any boilerplates or assisting tools, we'll write all the code you need line by line so you'll learn the very basics of how Cherrycake works.

First of all, check that your web server meets the [minimum requirements](/version-0.x/architecture/server-requirements) and create a folder for your project.

## Installing the Cherrycake engine

You can simply download the latest version of the engine from [GitHub](https://github.com/tin-cat/cherrycake-engine), but the recommended installation method is using [composer](https://getcomposer.org). To do so, `cd` into your project directory and require the Cherrycake engine using composer:

```bash
composer require tin-cat/cherrycake-engine dev-master
```

This will create the `/vendor` directory in your project, and will install there the Cherrycake engine and all its dependencies.

## Setting up autoload

To allow your own classes and modules to be loaded automatically, add this to your `composer.json`file:

```javascript
"autoload": {
    "psr-4": {
        "CherrycakeApp\\": "src/"
    }
}
```

> If you want to use a namespace other than `CherrycakeApp`for your App, modify the snippet above to match it.

## The public directory

For security reasons, we'll put all the files that will be served publicly to the Internet in a subdirectory called `/public`. Create this subdirectory now.

## Setting up the web server

Setting up a web server to work with a Cherrycake application it's almost exactly the same as with any other application, except for one detail: We need to tell the web server to redirect all the queries to the index.php file instead of the usual server behavior. This is how it's done:

**For NGINX:** Add the following to your virtual host configuration file:

```bash
root /<path_to_your_app>/public;
index index.php;
location / {
    try_files $uri $uri/ /?$query_string;
}
```

**For Apache:** Be sure to point your Virtual Host `DocumentRoot` directive to `/path_to_your_app/public` in your virtual host configuration file and create the file `/public/.htaccess` in your project with the following contents:

```bash
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule (.*) - [L]
RewriteRule (.*) / [L]
```

## Setting up the skeleton database

It's not required, but some of the most interesting Cherrycake features need a database to work, you'll discover them while you dive in the rest of this guides.

If you're going to use this features, you'll need to install the skeleton database by importing some SQL scripts into your MySQL or MariaDB database server. You'll find this scripts in the official [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), in the `/install/database` directory.

## Creating the index.php

The `/public/index.php` file will receive all the requests to your app and will be in charge of starting up the Cherrycake engine. Create it now and let's go step by step:

Cherrycake apps need to be declared in a namespace of your choice, or you can use the default `CherrycakeApp` namespace. In any case, we declare the namespace first:

```php
<?php

namespace CherrycakeApp;
```

Now we load the engine, along with any other additional packages. Since Cherrycake works with [composer](https://getcomposer.org), this is done just by including the `autoload.php` file, like this:

```php
require "vendor/autoload.php";
```

Now we can instantiate the engine. We use the `$e` variable as a convention:

```php
$e = new \Cherrycake\Engine;
```

> Note that the entire Cherrycake engine lives inside the `Cherrycake` namespace, while your application lives in its own different namespace you declared above. Every time you'll refer to a Cherrycake class, module or constant you'll need to prefix it with the appropriate `\Cherrycake\` namespace like we did here, or add a `use` statement at the top of your code. You'll see examples of that in the guide section and the provided examples.

Now we call the [Engine::init](/version-0.x/reference/core-classes/engine/methods#init) method to start it up:

```php
if ($e->init(__NAMESPACE__, [
    "appName" => "CherrycakeApp",
    "isDevel" => true,
    "baseCoreModules" => [
        "Actions"
    ]
]))
    $e->attendWebRequest();
```

[Engine::init](/version-0.x/reference/core-classes/engine/methods#init) accepts two parameters. The first must be the namespace of your app. Since we just declared it above, we can pass here the PHP constant `__NAMESPACE__`

The second parameter is an optional hash array that lets you configure some important parameters of the Cherrycake engine. The ones we're using here are:

* **`appName`** The name of the application. You can skip this and one will be generated automatically.
* **`isDevel`** When set to true, the application works in development mode, meaning you'll get extended error reports and other tricks to help you develop your app. When not specified, this parameter defaults to `false`.
* **`baseCoreModules`** Is an array of the module names that should be loaded upon initialization of the engine. If not specified, only the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module will be loaded.

> Check the [Engine::init](/version-0.x/reference/core-classes/engine/methods#init) documentation for more configuration parameters when initializing the engine.

Let's take a pause here to see why we've added the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module on the `baseCoreModules` list: We need our app to attend requests (it would be pretty useless otherwise), and [Actions](/version-0.x/reference/core-modules/actions-1/actions) is the module in charge of doing exactly that.

By including [Actions](/version-0.x/reference/core-modules/actions-1/actions) in `baseCoreModules`, it will be loaded immediately and, as part of the loading process, it will be initialized by calling the [Actions::init](/version-0.x/reference/core-modules/actions-1/actions#init) method. What this method does in the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module, among other things, is to go through all available modules in both the Cherrycake engine and your app, check if they have a method called `mapActions` and run it.

> It's as if the Actions module asked all other modules: "If you have any actions you would like to map to respond to requests, please let me know now!"

This causes all modules that have some action to map to do so (by using the [Actions::mapAction](/version-0.x/reference/core-modules/actions-1/actions#mapaction) method), thus leaving [Actions](/version-0.x/reference/core-modules/actions-1/actions) ready to attend requests.

> Note that there's actually no need to specify a `baseCoreModules` setup key when initializing the engine. If you skip this parameter, the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module will be loaded by default, which is the most common scenario when developing regular apps.

Now, if [Engine::init](/version-0.x/reference/core-classes/engine/methods#init) goes well, we run the [Engine::attendWebRequest](/version-0.x/reference/core-classes/engine/methods#attendwebrequest) method. What this method does is quite simple: By calling the [Actions::run](/version-0.x/reference/core-modules/actions-1/actions#run) method, it asks the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module to go through all mapped actions and run the one that matches the current request.

Lastly, we need to finalize execution by calling the [Engine::end ](/version-0.x/reference/core-classes/engine/methods#end)method, which in turn calls the `end` methods of all the loaded modules, so they can perform any cleaning tasks like disconnecting from external sources:

```php
$e->end();
```

So, our `index.php` file ends looking like this:

```php
<?php

namespace CherrycakeApp;

require "vendor/autoload.php";

$e = new \Cherrycake\Engine;

if ($e->init(__NAMESPACE__, [
    "isDevel" => true
]))
    $e->attendWebRequest();

$e->end();
```

> Note that because we're ok with the default configuration parameters for the [Engine::init ](/version-0.x/reference/core-classes/engine/methods#init)call, we've simplified it and only the `isDevel` configuration key remains.

Your Cherrycake app setup is ready, but if you run it now by browsing to your web server address, you'll get an error:

{% hint style="danger" %}
No mapped action found for this request
{% endhint %}

This is quite normal, since we haven't yet configured any actions for Cherrycake to respond to. Let's do it now.

## The "Hello world" module

Four our setup to be complete, we'll tell Cherrycake to attend requests to the `/` route of your web application and respond by showing a simple HTML "Hello world" message.

To do this, we'll create a module called `HelloWorld` that will map an action into the [Actions](/version-0.x/reference/core-modules/actions-1/actions) module.

Create the file `/src/HelloWorld/HelloWorld.class.php` and edit it so it declares an empty module structure, like this:

```php
<?php

namespace CherrycakeApp\HelloWorld;

class HelloWorld extends \Cherrycake\Module {
}
```

> Remember to use the same namespace you choose for your application in the `/public/index.php` file.

> Also, don't forget that modules have their own directory inside `/src`, that directory name must match the module name, even with uppercase and lowercase characters.

To map an action for the `HelloWorld` module so it will respond to requests, declare the static method `mapActions`, and call the[ Actions::mapAction](/version-0.x/reference/core-modules/actions-1/actions#mapaction) method, like this:

```php
<?php

namespace CherrycakeApp\HelloWorld;

class HelloWorld extends \Cherrycake\Module {

    public static function mapActions() {
        global $e;
        $e->Actions->mapAction(
            "home",
            new \Cherrycake\Actions\ActionHtml([
                "moduleType" => ACTION_MODULE_TYPE_APP,
                "moduleName" => "HelloWorld",
                "methodName" => "show",
                "request" => new \Cherrycake\Actions\Request([
                    "pathComponents" => false,
                    "parameters" => false
                ])
            ])
        );
    }
    
}
```

This will map an action that will respond to requests to the `/` path (that's why `pathComponents` has been set to false), and will call the `show` method on the `HelloWorld` module (the same module we're working on). Take a look at the [Actions guide](/version-0.x/guide/actions-guide) to learn about how to map more advanced actions.

If we run our app now, we'll get this error:

{% hint style="danger" %}
Mapped method HelloWorld::show not found
{% endhint %}

Which is quite understandable, because we haven't yet created the `show` method we told the [Action](/version-0.x/reference/core-classes/action) to run. Let's add it now:

```php
<?php

namespace CherrycakeApp\HelloWorld;

class HelloWorld extends \Cherrycake\Module {

    public static function mapActions() {
        global $e;
        $e->Actions->mapAction(
            "home",
            new \Cherrycake\Actions\ActionHtml([
                "moduleType" => ACTION_MODULE_TYPE_APP,
                "moduleName" => "HelloWorld",
                "methodName" => "show",
                "request" => new \Cherrycake\Actions\Request([
                    "pathComponents" => false,
                    "parameters" => false
                ])
            ])
        );
    }
    
    function show() {
        global $e;
        $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
            "code" => RESPONSE_OK,
            "payload" => "<html><body>Hello world</body></html>"
        ]));
    }
    
}
```

To send our "Hello World" HTML code to the client, we send a [ResponseTextHtml](/version-0.x/reference/core-classes/response) object using the [Output::setResponse](/version-0.x/reference/core-modules/output/methods#setresponse) method.

And that's it! If you now run your app you should see a boring yet quite welcoming "Hello world" message in your browser.

> This seems to be a somewhat overkill way of doing what could've been done with a simple `echo "Hello world"` line, isn't it?

Bear with me with the rest of the guides and you'll find this architecture to really come in handy when what you want to accomplish with your app is much more complex than a "Hello World"!

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/helloWorld) site.
{% endhint %}


# Skeleton start

Start a Cherrycake app using the pre-built skeleton, a simple "Hello world" web app ready to run.

The Cherrycake Skeleton is a [GitHub repository](https://github.com/tin-cat/cherrycake-skeleton) you can download or clone that leaves you with a boilerplate Cherrycake application ready to run and to be modified.

Instead of creating the files and directories you need each time you create a new Cherrycake application, you download a [Cherrycake skeleton](https://github.com/tin-cat/cherrycake-skeleton) and start working straightaway.

> The Cherrycake Skeleton additionally provides you with other useful files, like the SQL scripts to setup the database tables needed by some Cherrycake core modules or the `cli.php` file you'll need to run [CLI applications](/version-0.x/guide/cli).

## Starting an app with a Cherrycake Skeleton

First, clone or [download](https://github.com/tin-cat/cherrycake-skeleton) the Cherrycake Skeleton:

```bash
git clone https://github.com/tin-cat/cherrycake-skeleton CherrycakeApp
```

Now download the dependencies with composer:

```php
composer install
```

Follow the [Setting up the web server](/version-0.x/guide/getting-started#setting-up-the-web-server) section of the documentation and you should be ready to go!


# Docker start

Set up a development environment with a skeleton "Hello world" Cherrycake web app to start working in just a few minutes using Docker.

{% hint style="warning" %}
Please note that the Cherrycake Docker project only runs in Linux. Should work in Mac Os too, but hasn't been tested yet.
{% endhint %}

First of all if you haven't done it before, [install Docker](https://docs.docker.com/get-docker).

Clone or [download](https://github.com/tin-cat/cherrycake-docker) the Cherrycake Docker project:

```bash
git clone https://github.com/tin-cat/cherrycake-docker.git CherrycakeAppDocker
```

Once in the Cherrycake Docker directory, use the `cherrycake` script to interact with the docker project. Run `./cherrycake` without any argument to see a list of all the available commands:

```bash
./cherrycake
```

> Note that, depending on your Docker installation, you might need root privileges to run the `./cherrycake` script. In such cases, use `sudo ./cherrycake` instead.

To start the server, use the `start` command:

```bash
./cherrycake start
```

Once the initial build is complete, you'll have a working development environment ready:

* Access `http://localhost` on your browser to see the running app.
* Access `http://localhost:8080` to admin your database (User `root`, no password)
* Your Cherrycake app is stored under the `/app` directory, start working there!


# Modules guide

Modules are the fundamental containers of functionality in Cherrycake apps.

Modules pack the process-specific logic of an app and have some [additional benefits](/version-0.x/architecture/modules) and [important differences](/version-0.x/architecture/classes#whats-the-difference-between-a-class-and-a-module) over regular classes. Modules come in two flavors:

* [**Core modules**](/version-0.x/reference/core-modules)
  * Ready-made modules provided by Cherrycake, they implement all the process-specific functionality behind the Cherrycake architecture.
  * Cherrycake comes with a bunch of [Core modules](/version-0.x/reference/core-modules) aimed to help you build your app. From the main [Actions](/version-0.x/reference/core-modules/actions-1/actions) module that routes the requests to your app to modules to work with [Css](/version-0.x/reference/core-modules/css) and [JavaScript](/version-0.x/reference/core-modules/javascript) files, to control the user [Session](/version-0.x/reference/core-modules/session), to access [Database](/version-0.x/reference/core-modules/database) and [Cache](/version-0.x/reference/core-modules/cache) servers, [automate tasks](/version-0.x/reference/core-modules/janitor), [store logs](/version-0.x/reference/core-modules/log) and much more.
* **App modules**
  * Modules created by the developer when creating a new application, which will be in charge of all the processes in your App. You'll have to decide a great App module structure based on the needs of your application.
  * A really simple example of an App module would be the `HelloWorld` module we created in the[ Getting started](/version-0.x/guide/getting-started#the-hello-world-module) section, but a more complex scenario like an e-commerce site might need modules like `Products`, `Cart`, `Payments`, `ProductCategories`, `Search` and so, for example.

## Loading modules

Modules must be loaded before they can be used, they can be loaded in three ways:

* As a **Base core module**, when initializing the engine. Base core modules are loaded right when the engine is initialized. You specify your base modules in the `baseCoreModules` setup key of [Engine::init](/version-0.x/reference/core-classes/engine#init-appnamespace-setup). See the [Deep lifecycle](/version-0.x/architecture/lifecycle/deep-lifecycle) section for more details on this.
* As a **dependent module**, when they're required by other modules in their [Module::dependentCoreModules](/version-0.x/reference/core-classes/module/properties#usddependentcoremodules) or [Module::dependentAppModules](/version-0.x/reference/core-classes/module/properties#usddependentappmodules) properties. See [Specifying module dependencies](#specifying-module-dependencies).
* At any point in your code, **programmatically**. Just by calling [Engine::loadCoreModule](/version-0.x/reference/core-classes/engine/methods#loadcoremodule) or [Engine::loadAppModule](/version-0.x/reference/core-classes/engine/methods#loadappmodule).

## Accessing modules

Once they're loaded, modules are always accessible as properties of the engine. For example, the [Patterns](/version-0.x/reference/core-modules/patterns) module will be available in your code by doing this:

```php
global $e;
$e->Patterns->out("Pattern.html");
```

## Modules lifecycle

When a module is loaded for the first time during a request, this is what happens:

1. The module file is loaded, and the module instantiated.
2. The `init` method of the module is called, which does the following:
   1. If the module has some dependencies on other modules, they're loaded.
   2. If the module has a configuration file, it is loaded.
   3. Any other module-specific initialization is done.
3. When the engine request has finished, or if any module initialization failed, the `end` method is called.

## App module files

The App modules you create must be stored in the `/src` directory of your app, and also in their own subdirectory, which has to be named exactly like your module. The file name has to be also the exact name of you module, plus the `.php` extension.

> You can change the default `/src` directory for the one of your choice by setting the `appModulesDir` setup key when calling [Engine::init](/version-0.x/reference/core-classes/engine/methods#init)

For example, if you were to create a module called `Products`, it should be stored on the `/src/Products/Products.php` directory.

> Note that both the subdirectory and the file name itself are case-sensitive.

## Modules configuration file

Modules can have their own configuration file where all settings related to them should be entered. Configuration files are stored under the `/config` directory by default, but you can set your own directory specifying the `configDir` setup key in [Engine::init](/version-0.x/reference/core-classes/engine/methods#init)

Module configuration files must have a name that matches the module name, even with upper and lowercase characters. For example, the configuration file for the [Database](/version-0.x/reference/core-modules/database) module must be called `/config/Database.config.php`

Module configuration files must declare a hash array named in the syntax `$<ModuleName>Config`. For example, this is how a configuration file for the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module would look:

```php
<?php

namespace Cherrycake;

$HtmlDocumentConfig = [
    "title" => "Web page title",
    "description" => "Web page description"
];
```

You can set default configuration values that will be used if the configuration file didn't exist, or if a specific configuration key was not set on the configuration file. To do so, set the [Module::config](/version-0.x/reference/core-classes/module/properties#usdconfig) property of your module, like this:

```php
class MyModule extends \Cherrycake\Module {
    protected $isConfigFile = true;
    protected $config = [
        "title" => "Default title",
        "description" => "Default description"
    ];
}
```

To get a configuration value from a module, use the [Module::getConfig ](/version-0.x/reference/core-classes/module/methods#getconfig)method, for example:

```php
$this->getConfig("title");
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/modulesGuideConfigurationFile) site.
{% endhint %}

## Modules constants file

Modules can have a constants file specifically aimed to hold their related constant declarations so they will be available anywhere in your code even if the module has not been loaded or initialized. Use them to store constants that are intended to be used outside the module itself.

For example, the [Database](/version-0.x/reference/core-modules/database) module declares some useful constants in its constants file like `DATABASE_FIELD_TYPE_INTEGER`, `DATABASE_FIELD_TYPE_TIMESTAMP` and `DATABASE_FIELD_TYPE_STRING`.

Constants files are stored in the same directory as the module file, and the file name has to match the exact name of you module, plus the `.constants.php` extension. For example, the constants file for a module called`Products` would be stored in `/src/Products/Products.constants.php`, and it might look like this:

```php
<?php

namespace CherrycakeApp;

const PRODUCTS_SIZE_SMALL = 0;
const PRODUCTS_SIZE_MEDIUM = 1;
const PRODUCTS_SIZE_SMALL = 2;
```

## Specifying module dependencies

When your module makes use of another modules regularly, you should specify them as a dependency.

Set the [dependentCoreModules](/version-0.x/reference/core-classes/module#usddependentcoremodules) property of your module to specify which Core modules are required by yours, and the [dependentAppModules](/version-0.x/reference/core-classes/module#usddependentappmodules) to specify dependencies between your own modules, here's an example:

```php
namespace CherrycakeApp\MyModule;

class MyModule extends \Cherrycake\Module {
    protected $dependentCoreModules = [
        "Database",
        "Patterns"
    ];
    
    protected $dependentAppModules = [
        "MyOtherModule"
    ];
}
```


# Classes guide

Classes contain the logic behind  the elemental objects that are used within a Cherrycake application.

Classes encapsulate [object-specific logic](/version-0.x/architecture/classes), and they also come in two flavors:

* [**Core classes**](/version-0.x/reference/core-classes)
  * Ready-made classes provided by Cherrycake, providing useful object entities to interact with Cherrycake functionalities like the [Action](/version-0.x/reference/core-classes/action) or the [RequestParameter](/version-0.x/reference/core-classes/requestparameter), and other generalist classes to use throughout your code like the [Item](/version-0.x/reference/core-classes/item) or the [Image](/version-0.x/reference/core-classes/image) classes.
* **App classes**
  * Classes created by the developer to encapsulate object logic, often inheriting from core classes like [Item](/version-0.x/reference/core-classes/item).
  * For example, in an e-commerce web application you might need a `Product` class, a `ProductCategory` class and perhaps a `CartItem` class, all them might extend the [Item](/version-0.x/reference/core-classes/item) core class.

## Loading classes

Classes are automatically loaded the first time they're used, so you don't have to worry to include them anywhere.

For example, to create an [Image](/version-0.x/reference/core-classes/image) object, just do this anywhere in your code:

```php
$image = new \Cherrycake\Image;
```

Likewise, to create an object of a class you've created (an App class), just remember to specify our app's namespace instead of `\Cherrycake\`:

```php
$product = new \CherrycakeApp\Product;
```

You can also add `use` statements at the top of your file so you don't need to prefix class names each time you want to use them, like this:

```php
use Cherrycake;

$image = new Image;
```

## App class files

The App classes you create must be stores in the `/src` directory of your app, and the file name must match the class name, plus the `.php` extension. Unlike modules, classes do not need their own directory under `/src`.

> Note that class file names are case-sensitive.


# Actions guide

Actions is the routing core module of Cherrycake, and allows your application to receive requests and attend them accordingly.

When using [Actions](/version-0.x/reference/core-modules/actions-1/actions), all the modules who will be receiving requests should map their actions in the [Module::mapActions](/version-0.x/reference/core-classes/module/methods#mapactions) method, by calling [Actions::mapAction](/version-0.x/reference/core-modules/actions-1/actions#mapaction).

> [Actions](/version-0.x/reference/core-modules/actions-1/actions) is the default base core module because it is what you'll need in most cases. If you're experimenting with different ways of using Cherrycake, you can specify a different set of base modules in [Engine::init](/version-0.x/reference/core-classes/engine/methods#init)

When a request is received, [Actions](/version-0.x/reference/core-modules/actions-1/actions) will look through all the mapped actions. If any of them matches the current request, it will load the associated module and run the mapped method.

> [Actions](/version-0.x/reference/core-modules/actions-1/actions) calls [mapActions](/version-0.x/reference/core-classes/module#mapactions) methods on all available modules during its initialization, using the [Engine::callMethodOnAllModules](/version-0.x/reference/core-classes/engine/methods#callmethodonallmodules)

For example, the following module maps a simple action named `home` that will call the `viewHome` method when the root page `/` is requested:

```php
<?php

namespace CherrycakeApp\Home;

class Home extends \Cherrycake\Module {

    public static function mapActions() {
        global $e;
        
        $e->Actions->mapAction([
            "home",
            new \Cherrycake\Actions\ActionHtml([
                "moduleType" => ACTION_MODULE_TYPE_APP,
                "moduleName" => "Home",
                "methodName" => "viewHome",
                "request" => new \Cherrycake\Actions\Request([
                    "pathComponents" => false
                ])
            ])
        ]);
        
    }
    
    function viewHome() {
        // Show the home page
    }

}
```


# Complex actions

In the previous example, the `pathComponents` is left to false because we wanted the action to respond to requests to the root `/` page. To map actions that respond to more complex routes like `/about/contact`, we use `pathComponents` to pass an array of [RequestPathComponent](/version-0.x/reference/core-classes/requestpathcomponent) objects representing the segments of the path.

In this example, we map an action that will respond when the `/about/contact` path is requested:

```php
...

$e->Actions->mapAction([
    "aboutContact",
    new \Cherrycake\Actions\ActionsActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "About",
        "methodName" => "viewContact",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "about"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "contact"
                ])
            ]
        ])
    ])
]);

...
```

> See [RequestPathComponent::\_\_construct](/version-0.x/reference/core-classes/requestpathcomponent/methods#__construct) to learn more about other options when setting up path components for complex routes.


# Variable path components

A lot of times we'll need to respond to requests where some component of the path is dynamic, like when we are attending requests like `/product/4739` to show some specific product id. For this, we use the `REQUEST_PATH_COMPONENT_TYPE_VARIABLE_NUMERIC` type instead, like this:

```php
...

$e->Actions->mapAction(
    "viewProduct",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Products",
        "methodName" => "view",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "product"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_VARIABLE_NUMERIC,
                    "name" => "productId",
                    "securityRules" => [
                        SECURITY_RULE_NOT_EMPTY,
                        SECURITY_RULE_INTEGER,
                        SECURITY_RULE_POSITIVE
                    ]
                ])
            ]
        ])
    ])
);

...
```

In this case, instead of passing a `string` like we do with the `REQUEST_PATH_COMPONENT_TYPE_FIXED` type for the `product` part of the path, we pass a `name` to identify the received value, and a `securityRules` array to be sure the value we receive is secure.

In our example, the `viewProduct` action is triggered when we receive a request like `/product/4739`, and we specify that `4739` will be stored as `productId`, that it cannot be empty and that it has to be a positive integer.

> Check out the [Security](/version-0.x/reference/core-modules/security) module to learn more about the `securityRules` and filters we can configure when mapping actions with `pathComponents`.

To receive the `productId` value that was passed when the client requested `/product/4739`, we simply add a `request` parameter to the method triggered by the action (`Products::view` in the example above), and we'll get a [Request](/version-0.x/reference/core-classes/request) object that contains, among other useful things, the value of the `productId` path section:

```php
function view($request) {
    echo "The requested product id is ".$request->productId;
}
```

{% hint style="success" %}
See this example working in the [Cherrycake Documentation examples](https://documentation-examples.cherrycake.io/example/actionsGuideVariablePathComponents) site.
{% endhint %}


# Accept GET or POST parameters

To map actions that receive parameters, pass an array of [RequestParameter](/version-0.x/reference/core-classes/requestparameter) objects via the `parameters` key when creating [Request](/version-0.x/reference/core-classes/request) object. For example, mapping an action that receives a `userId` parameter via GET would look like this:

```php
...

$e->Actions->mapAction([
    "viewUser",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Users",
        "methodName" => "viewUser",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "user"
                ])
            ],
            "parameters" => [
                new \Cherrycake\Actions\RequestParameter([
                    "type" => REQUEST_PARAMETER_TYPE_GET,
    						    "name" => "userId",
                    "securityRules" => [
                        SECURITY_RULE_TYPICAL_ID
                    ]
    						])
            ]
        ])
    ])
]);

...
```

This action will be triggered when URLs like `/user?userId=381` are requested. You can then get the `userId` value just like we did above for dynamic paths:

```php
function viewUser($request) {
    echo "The requested user id ".$request->userId;
}
```

> Check out the [Security](/version-0.x/reference/core-modules/security) module to learn more about the `securityRules` and `filters` you can configure when mapping actions with `parameters`.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/actionsGuideAcceptGetOrPostParameters) site.
{% endhint %}


# Getting the URL of an action

Whenever you need the URL of one of your own actions, say, to build a button in your web app that links to that action, you can just write it like this in your HTML pattern:

```markup
<a href="/about/contact">Contact</a>
```

But doing so, if you ever change your action parameters or path components, you'll be forced to change your links manually in all your patterns, one by one.

To avoid this, use the [Actions::getAction](/version-0.x/reference/core-modules/actions-1/actions#getaction) method to get the action you want to get the URL of, and then use [Request::buildUrl ](/version-0.x/reference/core-classes/request/request-methods#buildurl-setup)on the action's [$request ](/version-0.x/reference/core-classes/action/properties#request)to retrieve it.

This is how it would look:

```php
$url = $e->Actions->getAction("aboutContact")->request->buildUrl();
```

You can do this directly in your HTML pattern:

```markup
<a href="<?= $e->Actions->getAction("aboutContact")->request->buildUrl() ?>">Contact</a>
```

Or you can pass the URL as a parameter to your pattern:

```php
$e->Patterns->out("page.html", [
    "variables" => [
        "urlAboutContact" => $e->Actions->getAction("aboutContact")->request->buildUrl()
    ]
]);
```

```markup
<a href="<?= $urlAboutContact ?>">Contact</a>
```

## Getting the URL of actions with variable path components or GET parameters

When you want to get the URL of a more complex action that has some variable path components like `/product/4739`, or maybe accepts some GET parameters like `/user?userId=381`, you pass the `parameterValues` option key to [Request::buildUrl](/version-0.x/reference/core-classes/request/request-methods#buildurl) with the values you need.

For example, for this action that has one fixed and one variable path component:

```php
$e->Actions->mapAction([
    "viewProduct",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Products",
        "methodName" => "view",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "product"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_VARIABLE_NUMERIC,
                    "name" => "productId",
                    "securityRules" => [
                        SECURITY_RULE_NOT_EMPTY,
                        SECURITY_RULE_INTEGER,
                        SECURITY_RULE_POSITIVE
                    ]
                ])
            ]
        ])
    ])
]);
```

You would build a valid URL like this:

```php
echo $e->Actions->getAction("viewProduct")->request->buildUrl([
    "parameterValues" => [
        "productId" => 4739
    ]
]);
```

```
/product/479
```

Now consider this more complex action that has one fixed path component and accepts accepts one GET parameter called `userId`:

```php
$e->Actions->mapAction([
    "viewUser",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Users",
        "methodName" => "view",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "user"
                ])
            ],
            "parameters" => [
                new \Cherrycake\Actions\RequestParameter([
                    "type" => REQUEST_PARAMETER_TYPE_GET,
    						    "name" => "userId",
                    "securityRules" => [
                        SECURITY_RULE_TYPICAL_ID
                    ]
    						])
            ]
        ])
    ])
]);
```

You would build the URL for this action the same way, just specify the right parameter name:

```php
echo $e->Actions->getAction("viewUser")->request->buildUrl([
    "parameterValues" => [
        "userId" => 381
    ]
]);
```

```
/user?userId=381
```


# Cached actions

When an action is configured as cacheable, when a request is received for that action, the cached output will be returned instead of executing the method. This can provide extremely efficient and short response times as the engine will only load the minimal set of modules needed to attend the cached request.

To activate caching for an action, set the `isCache` setup key to true when creating the [Action](/version-0.x/reference/core-classes/action/methods#__construct-setup) object.

To use a different cache provider, TTL or prefix, specify also the `cacheProviderName`, `cacheTtl` or `cachePrefix` [setup keys](/version-0.x/reference/core-classes/action/methods#__construct-setup). See [Working with Cache](/version-0.x/guide/cache-guide) for more details on this concepts.

For example, if we wanted to activate the cache for the action we used in the first example on this section, it would look like this:

```php
...

$e->Actions->mapAction([
    "home",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Home",
        "methodName" => "viewHome",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => false
        ]),
        "isCache" => true
    ])
]);

...
```

Furthermore, if we wanted to use a cache provider and TTL different from the default ones:

```php
...

$e->Actions->mapAction([
    "home",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Home",
        "methodName" => "viewHome",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => false
        ]),
        "isCache" => true,
        "cacheProviderName" => "redis",
        "cacheTtl" => CACHE_TTL_SHORT
    ])
]);

...
```

The default cache provider is called `engine`, and uses [APCu](https://www.php.net/manual/en/book.apcu.php) for a fast yet basic caching mechanism. See Working with Cache to use other more advanced alternatives like [Redis](https://redis.io).

## Removing an action from cache

If you need to remove an action from cache before its TTL expiration time arrives, use the [Action::clearCache](/version-0.x/reference/core-classes/action/methods#resetcache), like this:

```php
$e->Actions->getAction("home")->clearCache();
```

For complex actions with variable path components or parameters, you must specify the specific path components or parameters values for which you want to clear the cache as an argument.

For example, for this action that has one fixed and one variable path component to attend requests like `/product/479`:

```php
$e->Actions->mapAction([
    "viewProduct",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => ACTION_MODULE_TYPE_APP,
        "moduleName" => "Products",
        "methodName" => "view",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "product"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => REQUEST_PATH_COMPONENT_TYPE_VARIABLE_NUMERIC,
                    "name" => "productId",
                    "securityRules" => [
                        SECURITY_RULE_NOT_EMPTY,
                        SECURITY_RULE_INTEGER,
                        SECURITY_RULE_POSITIVE
                    ]
                ])
            ]
        ])
    ])
]);
```

If we wanted to clear the cache for the request to the product with id `479`, we would do this:

```php
$e->Actions->getAction("home")->clearCache([
    "productId" => 479
]);
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/actionsGuideCachedAction) site.
{% endhint %}


# Brute force attacks

Dictionary attacks and other kinds of brute force attacks often rely on the ability to send lots of requests per second in order to, for example, try different passwords to hack an account. In those cases, the faster our server responds, the easier is for the attacker to try many passwords per second.

One way of making it difficult for the attackers is to add an intentional delay to the response, so the amount of time needed to try a reasonable amount of passwords rises quickly, hopefully discouraging the attacker.

By setting the `isSensibleToBruteForceAttacks` setup key to true when creating the [Action](/version-0.x/reference/core-classes/action/methods#__construct-setup) object, Cherrycake will take care of adding this delay to the request.

The delay is only added when the method called by the action returns `false`. Be sure to return `false` in methods mapped as actions when the sensible task was unsuccessful. For example: If a received password or key of any kind was checked against a database or any kind of authentication method, and it failed.

> A random delay is used to emulate an unstable connection for added stealthiness. This can be adjusted by setting the `sleepSecondsWhenActionSensibleToBruteForceAttacksFails` configuration key of the [Actions](/version-0.x/reference/core-modules/actions-1) module.


# Patterns guide

Patterns provides your HTML, CSS, JavaScript and other types of files with a dynamic template mechanism that brings performance, re-usability and code tidiness benefits.

The simplest way of using [Patterns](/version-0.x/architecture/patterns) is just calling the [Patterns::out](/version-0.x/reference/core-modules/patterns#out-patternname-setup-code) method to send a pattern to the browser:

```php
$e->Patterns->out("helloworld.html");
```

This will read the file `/patterns/pattern.html`, parse and output it to the client as the `payload` of an [ResponseTextHtml ](/version-0.x/reference/core-classes/response)response.

> You can change the directory where your patterns are stored by setting the `directory` key of the Patterns module configuration file.

But this is just the most common way of using a pattern. You might need to simply get the results of a parsed pattern in a variable. For doing so, instead of using the [Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out) method, you use [Patterns::parse](/version-0.x/reference/core-modules/patterns/methods#parse) like this:

```php
$parsedContents = $e->Patterns->parse("helloworld.html");
```

{% hint style="warning" %}
**Security warning**

Since patterns are parsed as PHP code, you're strongly advised against parsing files that are uploaded by the user or coming from untrusted sources.
{% endhint %}


# Passing variables to a pattern

We can pass variables to be used inside a pattern via the `variables` setup key in the [Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out) or the [Patterns::parse](/version-0.x/reference/core-modules/patterns/methods#parse) call.

Imagine our `helloworld.html` file looks like this:

```markup
<!DOCTYPE html>
<html>
<body>
    <p>Here's a gift for you: 🧁</p>
</body>
</html>
```

But we want the gift emoji to be passed as a variable to the pattern to be able to pass a different one each time we make the call to [Patterns::out ](/version-0.x/reference/core-modules/patterns/methods#out)or [Patterns::parse](/version-0.x/reference/core-modules/patterns/methods#parse).

To do so, first we replace the emoji in the `helloworld.html` file with a PHP statement that simply echoes the variable `$emoji`, like this:

```markup
<!DOCTYPE html>
<html>
<body>
    <p>Here's a gift for you: <?= $emoji ?></p>
</body>
</html>
```

> Note that, to use PHP code inside a pattern, we need to enclose it in PHP's opening and closing tags: `<?php ... ?>`. In this case, however, we use the shorthand `<?= ... ?>` which is a shortcut for the more verbose `<?php echo ... ?>`

And now, in our call to[ Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out), we pass `emoji` as a variable:

```php
$e->Patterns->out("helloworld.html", [
    "variables" => [
        "emoji" => "🧸"
    ]
]);
```

So now, the browser shows this:

```markup
Here's a gift for you: 🧸
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/patternsGuidePassingVariables) site.
{% endhint %}


# Nested patterns

One of the most powerful ideas behind template systems like [Patterns](/version-0.x/architecture/patterns) is the ability to include patterns within patterns, this opens many new ways of organizing and re-using your code.

Maybe the first idea that comes to mind is to put the header and the footer of your HTML document in two separate patterns because they're almost always the same in all the pages of your website. Let's do it.

Let's assume you save the header for your pages in a pattern called `header.html`, and it looks like this:

```markup
<!DOCTYPE html>
<html>
<body>
```

And your footer.html looks like this:

```markup
</body>
</html>
```

Then, you simply include those patterns in your main pattern. Because patterns have access to the Cherrycake engine, this is done by simply calling the [Patterns::parse ](/version-0.x/reference/core-modules/patterns/methods#parse)method you already know of, but this time inside your pattern:

```markup
<?= $e->Patterns->parse("header.html") ?>

    <p>Here's a gift for you: <?= $emoji ?></p>

<?= $e->Patterns->parse("footer.html") ?>
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/patternsGuideNestedPatterns) site.
{% endhint %}


# Cached patterns

When a pattern is cached, its contents are read from the cache instead of the pattern file. Anything inside the pattern is cached, including any PHP code and nested patterns.

The main reason to cache a pattern is to avoid executing it every time it is used, specially if it contains instructions that are very resource demanding. While the pattern is in cache, it will be served instantly, no matter how long it took to parse it the first time it was used.

When combined with the ability to create structures of nested patterns, cached patterns can become a powerful tool to create high performance websites.

The main way to specify which patterns you want to cache is by adding them to the `cachedPatterns` key in the [Patterns configuration](/version-0.x/architecture/patterns) file, `/config/Patterns.config.php`, like this:

```php
<?php

namespace Cherrycake;

$PatternsConfig = [
    "cachedPatterns" => [
        "helloworld.html" => [
            "cacheTtl" => \Cherrycake\CACHE_TTL_1_MINUTE
        ]
    ]
];
```

This would cause the `helloworld.html` pattern to be parsed the first time it is used, and then stored in cache for one minute. During that minute, every other time the same pattern is used, the cached parsed result will be used instead. After one minute, the TTL will expire and the pattern will be parsed again on the next use. See [Working with Cache](/version-0.x/guide/cache-guide) for more details on this concepts.

## Removing a pattern from cache

If you want to remove a pattern from the cache before its TTL expiration time arrives, use the [Patterns::clearCache](/version-0.x/reference/core-modules/patterns/methods#clearcache) method, here's an example:

```php
$e->Patterns->clearCache("helloworld.html");
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/patternsGuideCachedPatterns) page.
{% endhint %}


# Cache guide

The Cache module provides your Cherrycake application with a standardized interface to implement caching and shared memory mechanisms into your App by connecting to multiple external cache providers.

## Cache providers

To use cache in your application, you must first define a cache provider. Each cache provider connects your app with a different cache mechanism or server, that means your app can make use of different caches at the same time.

Cache providers are configured in the [Cache configuration](/version-0.x/reference/core-modules/cache) file `/config/Cache.config.php`. For example, if you want to use a simple but fast APCu cache provider, your Cache configuration file would look like this:

```php
<?php

namespace Cherrycake;

$CacheConfig = [
    "providers" => [
        "fast" => [
            "providerClassName" => "CacheProviderApcu"
        ]
    ]
];
```

> Note we called our cache provider `fast`

You can configure more than one cache providers. For example, let's add a Redis cache provider too, called `huge`:

```php
<?php

namespace Cherrycake;

$CacheConfig = [
    "providers" => [
        "fast" => [
            "providerClassName" => "CacheProviderApcu"
        ],
        "huge" => [
            "providerClassName" => "CacheProviderRedis",
            "config" => [
                "scheme" => "tcp",
                "host" => "localhost"
                "port" => 6379,
                "database" => 0,
                "prefix" => "CherrycakeApp:"
            ]
        ]
    ]
];
```

> Since some functionalities of Cherrycake make use of caching mechanisms, there is a default cache provider called `engine` that uses an APCu cache provider. This provider is always defined, no matter what you setup in your `Cache.config.php` file.

## Modules that depend on Cache

Some Core modules make use of Cache by their own, like [Database](/version-0.x/reference/core-modules/database) and [Patterns](/version-0.x/reference/core-modules/patterns). Those modules always accept a configuration key to tell them the name of the cache provider to use, as defined in your `Cache.config.php`

## How long cached objects stay in cache?

The data you store in cache, as well as the objects cached by modules like [Database](/version-0.x/reference/core-modules/database) and [Patterns](/version-0.x/architecture/patterns), are normally persistent between requests, and it's the job of the cache mechanism to keep them there for as long as possible, or until their TTL expiration time arrives.

However, you can not rely on a cache or shared memory system as a persistent way of storing information. Generally, cached objects are deleted when the server restarts, when it runs out of memory, or if it implements certain cache eviction policies, like removing all cached objects that are too old, or that haven't been accessed too much.

> To store information in a persistent way, use [Database](/version-0.x/reference/core-modules/database).

## Other ways of using shared memory

Some specific cache providers like Redis implement other useful ways of working with shared memory, like [Lists](/version-0.x/guide/cache-guide/lists), [Queues](/version-0.x/guide/cache-guide/queues) and [Pools](/version-0.x/guide/cache-guide/pools).

This methods are specially suited for high performance operations like the storage of events in a high traffic scenario, or the intermediate storage of data that needs to be accessed extremely fast, lots of times per second.


# Time To Live

Time to Live, or TTL, is a common concept in caching: It represents the amount of time the cached object will be available in the cache. Even though this mechanism might work differently for different cache systems, in general, cached objects are removed automatically from cache when their TTL has passed, so you'll get `false` if you try to access them after that.

> This TTL mechanism is ideal for a lot of simple caching needs: Say you want to cache a calculated value, but you want the cache to be renewed each hour, to keep the calculation in the value relatively up to date. You would store the value in cache with a TTL of one hour, and every time you need to access that value, you would check first if it's in cache. If it is, you use the cached value. If it's not, you calculate a new value and then store it in cache, again with a one hour TTL.

### What about when TTL is zero?

Generally, when an object is stored in cache with a zero TTL, the cache system tries to hold it as long as possible, considering the resources of the server and any persistence mechanisms the server might implement. You should not rely on a zero TTL to store any persistent information.

> As a general rule, do not use cache systems to store persistent information. Use a database instead.


# Using cache

Cache providers are available to use through properties in the [Cache](/version-0.x/reference/core-modules/cache) module. For example, to set the key `myKey` into the cache provider `fast`, use the [CacheProvider::set ](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#set)method, like this:

```php
$value = $e->Cache->fast->set("myKey", "value", \Cherrycake\CACHE_TTL_5_MINUTES);
```

And [CacheProvider::get](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#get) to set a value into a cache key:

```php
$value = $e->Cache->fast->get("myKey")
```


# Lists

A list is an isolated subset of keys stored in the shared memory of the cache system that can be manipulated at once as a group. For example, you might want store all cached objects related to the user with id `214` in a list named `user_214`, like this:

```php
$userId = 214;
$cacheListName = "user_".$userId;
$e->Cache->huge->listSet($cacheListName, "numberOfVisits", $numberOfVisits);
$e->Cache->huge->listSet($cacheListName, "numberOfFollowers", $numberOfFollowers);
$e->Cache->huge->listSet($cacheListName, "numberOfLikes", $numberOfLikes);
```

Now, when you want to clear the entire cache for a specific user, you don't have to remember all the cache keys you used for that user, you just clear the entire list:

```php
foreach ($e->Cache->huge->listGetAll($cacheListName) as $listKey)
    $e->Cache->huge->listDel($cacheListName, $listKey);
```

Check [Lists methods](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#list-methods) to see more ways to interact with cache lists.


# Queues

Queues are ordered lists of values. New values can be appended to the end of a queue with [CacheProviderRedis::queueRPush](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#queuerpush), or prepended to the beginning with [CacheProviderRedis::queueLPush](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#queuelpush). You then can use [CacheProviderRedis::queueRPop](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#queuerpop) to extract a value from the end of the queue and [CacheProvider::queueLPop](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#queuelpop) to extract it from the beginning.

> Queues are great to store events in the same order as they arrive. For example, they're a really efficient way of storing an ordered log of page views, even if your pages get a huge amount of traffic. In a separate process that runs automatically every few minutes, you can then retrieve those page view events and store them in a database for persistence.


# Pools

Pools work a little bit like [queues](/version-0.x/guide/cache-guide/queues), with the exception of not being ordered. You cannot choose whether to add a value to the beginning or to the end of a pool, you just throw the value into the pool with [CacheProviderRedis::poolAdd](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#pooladd), and it stays there.

Also, when you get objects from the pool with [CacheProviderRedis::poolPop](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#poolpop-poolname), you can't choose what object you get, you just get a random one.

One benefit you get when using pools is that you can check if a certain value is in the pool by using [CacheProviderRedis::isInPool](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#isinpool), and you can also get the number of values in the pool with [CacheProviderRedis::poolCount](/version-0.x/reference/core-classes/cacheprovider/cacheprovider-methods#poolcount).


# Database guide

The Database module provides your Cherrycake application with a standardized interface to connect to database servers like MySQL and MariaDB.

## Database providers

To connect to database servers you must configure a database provider. Just like with the [Cache](/version-0.x/guide/cache-guide) module, you can configure multiple providers to connect to multiple databases at the same time.

> Cherrycake is currently only compatible with MySQL and MariaDB servers.

Database providers are configured in the [Database configuration](/version-0.x/reference/core-modules/database#configuration) file `Database.config.php`.For example, if you want to connect to a MySQL database server, your Cache configuration file would look like this:

```php
<?php

namespace Cherrycake;

$DatabaseConfig = [
    "providers" => [
        "main" => [
            "providerClassName" => "DatabaseProviderMysql",
            "config" => [
                "host" => "localhost",
                "user" => "user",
                "password" => "password",
                "database" => "cherrycake",
                "charset" => "utf8mb4",
                "cacheProviderName" => "engine"
            ]
        ]
    ]
];
```

> Note we called our database provider `main`

## Modules that depend on Database

Just like Cache, some other modules use Database for many purposes, for example: The [Session](/version-0.x/reference/core-modules/session) module uses a database connection to store information about sessions.

> That's why in the [Cherrycake Skeleton](/version-0.x/guide/getting-started/skeleton) boilerplate you'll find the `/install` directory containing some SQL scripts to create the tables some this modules need.


# Basic queries

Basic queries to a database are done using [DatabaseProvider::query](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#query). Since database providers are available as properties of the Database module, a simple query to a provider named `main` would look like this:

```php
$result = $e->Database->main->query("select * from users");
```

Database queries are returned in the form of a [DatabaseResult](/version-0.x/reference/core-classes/databaseresult) object you can manipulate. For example, use the [DatabaseResult::isAny](/version-0.x/reference/core-classes/databaseresult/databaseresult-methods#isany) method to check if there were any results, or the [DatabaseResult::countRows](/version-0.x/reference/core-classes/databaseresult/databaseresult-methods#countrows) to get the number of rows in the result.

To loop through all the rows, iterate over the [DatabaseResult::getRow](/version-0.x/reference/core-classes/databaseresult/databaseresult-methods#getrow) method:

```php
while ($row = $result->getRow()) {
    echo $row->getField("name")."\n";
}
```

Rows are returned as [DatabaseRow](/version-0.x/reference/core-classes/databaserow) objects which, as you can see in the example above, allow you to retrieve information from each row in the results. Here's the result:

```
Douglas Engelbart
John Horton Conway
Frank Abagnale
Carl Sagan
Richard Feynmann
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples ](https://documentation-examples.cherrycake.io/example/databaseGuideBasicQueries)site.
{% endhint %}


# Prepared queries

Prepared queries are just like regular queries where the variables are stored and check separately instead of being directly appended to the SQL query.

Even though prepared queries are a little more verbose to code, they provide a very important extra layer of security against SQL injection attacks, specially when you're using data coming from user input or other untrusted sources.

{% hint style="warning" %}
Because of the security benefits, you're strongly advised to always use prepared queries instead of basic queries.
{% endhint %}

In prepared queries, instead of specifying your values in the SQL string like this:

```sql
insert into users (name, email) values ('Frank', 'frank.abagnale@united.com');
```

You replace the values with question marks `?` like so:

```sql
insert into users (name, email) values (?, ?);
```

And then pass the values in a separate array to [DatabaseProvider::prepareAndExecute](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#prepareandexecute), this is how it looks.

```sql
$result = $e->Database->main->prepareAndExecute(
    "insert into users (name, email) values (?, ?)",
    [
        [
            "type" => \Cherrycake\Database\DATABASE_FIELD_TYPE_STRING,
            "value" => "Frank"
        ],
        [
            "type" => \Cherrycake\Database\DATABASE_FIELD_TYPE_STRING,
            "value" => "frank.abagnale@united.com"
        ]
    ]
);
```

> See [Database constants](/version-0.x/reference/core-modules/database#constants) for a list of all available field types.


# Cached queries

Cached queries allow you to dramatically improve performance in certain situations by preventing the database server from repeatedly performing the same query, storing the results in cache instead.

To perform a basic query with cache, use the [DatabaseProvider::queryCache](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache) method, this is how it would look:

```php
$result = $e->Database->main->queryCache(
    "select * from users order by rand()",
    \Cherrycake\CACHE_TTL_1_MINUTE
);
```

When iterating over the results like we did in the [Basic queries](/version-0.x/guide/database-guide/basic-queries) section, you would get something like this:

```php
Douglas Engelbart
John Horton Conway
Frank Abagnale
Carl Sagan
Richard Feynmann
```

Note here that, even though the results have been randomly ordered thanks to the `by rand()` clause in the SQL statement, we'll always get the results in the same order if we execute the query multiple times. This is because the results were stored in the cache, and the query is not actually running, we're just getting the same results the cache system got in the first run.

> Because the cached results will expire after 1 minute because we set the TTL to `CACHE_TTL_1_MINUTE`, the result order will change if we execute the query when a minute has passed from the first execution, and they will remain in the same order for 1 more minute.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/databaseGuideCachedQueries) site.
{% endhint %}

## Cached prepared queries

To use caching in prepared queries, use the [DatabaseProvider::prepareAndExecuteCache](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#prepareandexecutecache) method, which works like the normal, non-cached prepared query methods, but adding the additional cache parameters you already know of:

```sql
$result = $e->Database->main->prepareAndExecuteCache(
    "select name from users where dateSignUp >= ?",
    [
        [
            "type" => \Cherrycake\Database\DATABASE_FIELD_TYPE_DATETIME,
            "value" => mktime(0, 0, 0, 1, 1, 2020)
        ]
    ],
    \Cherrycake\CACHE_TTL_1_MINUTE
);
```

> Remember that, for security reasons, prepared queries are the recommended way of querying the database, specially when you're using data coming from untrusted sources in your query.


# Cache key naming

Each object stored in cache has its own unique identifier key. When you run a cached query without specifying any [`cacheKeyNamingOptions`](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache) parameter like we did in the [Cached queries](/version-0.x/guide/database-guide/cached-queries) section, the cache key is automatically generated by creating a unique hash from the SQL statement itself.

For example, when executing the cached query`select * from users order by rand()`, a unique key is generated internally that looks like this:

```php
CherrycakeApp_Database_64df95723d106ba80b0cf725bc56ddd1
```

> When letting Database generate automatically the cache keys, different keys are generated even if a single character of the SQL statement has changed.

This means that you can trust a different cache key will be generated for each different query you perform, so in most simple queries you don't need to care about cache key collisions.

But in certain situations you'll need to cache different queries under the same cache key to get the maximum benefits of using a cached database system. For example, when you're retrieving data from the database relative to the current date and time.

Imagine you want to query all the users that have signed up to your web app during the last 24 hours, and that you want that query to be cached. You could do that like this:

```php
$timestamp24HoursEarlier = time() - (24 * 60 * 60);
$result = $e->Database->main->queryCache(
    "select * from users where dateSignUp >= '".date("Y-n-j H:i:s", $timestamp24HoursEarlier)."'",
    \Cherrycake\CACHE_TTL_1_HOUR
);
```

Can you see the problem here? We want the query to be cached for an hour and we haven't specified the [`cacheKeyNamingOptions`](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache) parameter, so the unique cache key for this query will be automatically generated using the SQL statement.

The problem is that, because we're basing our query on a value that changes every second, the SQL statement itself also changes every second, thus generating a different automatic cache key almost every time the cached query is executed.

> This will cause our cache memory to fill with useless objects, and will cause the query to be executed once per second if it is requested very often.

To solve this kind of situations, we specify our own cache key instead of letting Database create its own automatically. We do this by passing the [`cacheKeyNamingOptions`](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache) parameter to [DatabaseProvider::queryCache](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache), like this:

```php
$timestamp24HoursEarlier = time() - (24 * 60 * 60);
$result = $e->Database->main->queryCache(
    "select * from users where dateSignUp >= '".date("Y-n-j H:i:s", $timestamp24HoursEarlier)."'",
    \Cherrycake\CACHE_TTL_1_HOUR,
    [
        "uniqueId" => "usersSignedUpLast24Hours"
    ]
);
```


# Removing queries from cache

You can manually remove a cached query from cache before its natural TTL-driven expiration time by using the [DatabaseProvider::clearCacheQuery](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#clearcachequery) method, here's an example:

```php
$e->Database->main->clearCacheQuery([
    "uniqueId" => "usersSignedUpLast24Hours"
]);
```

Because query cache keys are automatically generated if you don't specify any [Cache key naming](/version-0.x/guide/database-guide/cache-key-naming) when calling methods like [DatabaseProvider::queryCache](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#querycache) and [DatabaseProvider::prepareAndExecuteCache](/version-0.x/reference/core-classes/databaseprovider/databaseprovider-methods#prepareandexecutecache), you can only remove queries from cache that have been originally performed with a specific Cache key naming.

> The most usual way to cache queries and then be able to remove them whenever we need is to use a known `uniqueId` for each query, like in the example above.


# Items guide

Using Items in your Cherrycake application brings you many benefits when interacting with the primordial objects of your app, like optimized loading, storage, caching and embedded security mechanisms.

Items are Cherrycake's conceptualization of the fundamental objects stored in a database. For example, in an e-commerce site, a product would be an Item, but also would a user, a product category or an invoice.

## Creating an Item class

Items always come from a database table, so let's imagine we have a database of movies and we want to define an [Item](/version-0.x/reference/core-classes/item) to work with the movies that are stored in our database, in a table called `movies` with the following fields:

| Field name       | Specs                                           |                                                        |
| ---------------- | ----------------------------------------------- | ------------------------------------------------------ |
| **`id`**         | `unsigned` `int` `auto_increment` `primary key` | The unique id to identify movies.                      |
| **`title`**      | `varchar`                                       | The name of the movie.                                 |
| **`summary`**    | `text`                                          | A summary of the movie plot.                           |
| **`year`**       | `year`                                          | The year the movie was released.                       |
| **`dateAdded`**  | `datetime`                                      | The date and time the movie was added to the database. |
| **`directorId`** | `unsigned` `int`                                | The id of the director in the `directors` table.       |

> You can get an SQL script to create this table in the [Cherrycake documentation examples repository](https://github.com/tin-cat/cherrycake-documentation-examples), in the [`/install/database/movies.sql`](https://github.com/tin-cat/cherrycake-documentation-examples/blob/master/install/database/movies.sql) file.

Items are [App classes](/version-0.x/guide/classes-guide#app-class-files) that extend the Cherrycake's [Item](/version-0.x/reference/core-classes/item) core class, so we create the `Movie` class in the file `/classes/Movie.class.php`, and it looks like this:

```php
<?php

namespace CherrycakeApp;

class Movie extends \Cherrycake\Item {
    protected $tableName = "movies";
    protected $fields = [
        "id" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER
        ],
        "title" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING
        ],
        "summary" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_TEXT
        ],
        "year" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_YEAR
        ],
        "imdbRating" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_FLOAT
        ]
    ];
}
```

We set some properties of the class to configure it:

* **`tableName`** The name of the table where the items are stored.
* **`fields`** A hash array to specify the field names and field types of the table. See [Database constants](/version-0.x/reference/core-modules/database#constants) for all the available field types. See [Item::$fields](/version-0.x/reference/core-classes/item/item-properties#fields) for more keys you can use here to customize how your Item works.

You can also set this other properties if you'll be using values different from the defaults:

* **`databaseProviderName`** The database provider name where this items are stored. The default is `main`
* **`idFieldName`** The name of the field that contains values to uniquely identify each item in the table. Defaults to `id`

With this we've already created a functional Item that can now represent a movie in our app with the added benefits of using Cherrycake Items.

Now, what can you do with your new `Movie` class? Let's see how to create a `Movie` object we can manipulate. Let's say we want to load the movie with id `15`:

```php
$movie = new Movie([
    "loadMethod" => "fromId",
    "id" => 15
]);
```

Field values for an [Item](/version-0.x/reference/core-classes/item) are accessed just like regular properties, like this:

```php
echo "{$movie->title} ({$movie->year})";
```

```
Brainstorm (1983)
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideBasicUsage) site.
{% endhint %}

We can also update items on the database by using [Item::update](/version-0.x/reference/core-classes/item/item-methods#update), for example:

```php
$movie->update([
    "imdbRating" => 8.7
]);
```

Changing an Item's property manually and then calling [Item::update](/version-0.x/reference/core-classes/item/item-methods#update) without any parameters also works. This will do the same as the example above:

```php
$movie->imdbRating = 8.7;
$movie->update();
```

To remove an item from the database, use the [Item::delete](/version-0.x/reference/core-classes/item/item-methods#delete) method:

```php
$movie->delete();
```


# Item cache

All the performance benefits of a cache system when working with Items.

Activating cache for your [Item](/version-0.x/reference/core-classes/item) class is as easy as setting the `loadFromIdMethod` of your class to `queryDatabaseCache`:

```php
...

class Movie extends \Cherrycake\Item {
    protected $tableName = "movies";
    protected $loadFromIdMethod = "queryDatabaseCache";
    protected $fields = [
        "id" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER
        ],
        "title" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING
        ],
        "summary" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_TEXT
        ],
        "year" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_YEAR
        ],
        "imdbRating" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_FLOAT
        ]
    ];
}
```

You can now add some other optional properties for caching if you want to change the defaults:

* **`cacheProviderName`** The name of the cache provider to use. Default: `engine`
* **`cacheTtl`**: The TTL to use when caching data for this Item. Default: `CACHE_TTL_NORMAL`
* **`cacheSpecificPrefix`**: The [key prefix](/version-0.x/reference/core-modules/cache/cache-methods#buildcachekey) to use when caching data for this item. Default: none

Just like this, whenever you're loading a `Movie`, it will be loaded extremely fast from the cache without any actual request to the database, as long as it has been loaded before at least once, and the TTL expiration time hasn't yet arrived.

If you need to remove an item from cache, use the [Item::clearCache](/version-0.x/reference/core-classes/item/item-methods#clearcache) method, like this:

```php
$movie->clearCache();
```

> To give you maximum control, the cache of an Item is not automatically cleared after doing an [Item::update](/version-0.x/reference/core-classes/item/item-methods#update) operation, so you have to remember to do also [Item::clearCache](/version-0.x/reference/core-classes/item/item-methods#clearcache) if you want the changes to be effective immediately if someone requests the same Item, so they don't have to wait for the TTL expiration.


# Item lists

Item lists are groups of Item objects retrieved from the database.

Working with Items becomes a lot more powerful when in conjunction with Item lists. Items allows you to retrieve multiple Items at once from the database and work with them as you would do with a regular list.

Just like when creating single Item classes, Item lists are [App classes](/version-0.x/guide/classes-guide#app-class-files) that extend the Cherrycake's [Items](/version-0.x/reference/core-classes/items) core class. Let's say we want to create an Item list class to work with lists of movies. To do so, so we create the `Movies` class in the file `/classes/Movies.class.php`, and it looks like this:

```php
<?php

namespace CherrycakeApp;

class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
}
```

Just by setting these two properties we'll have a working `Movies` class:

* **`tableName`** The name of the table where the items are stored.
* **`itemClassName`** The name of the Item class.

You can also set some other properties if you need to change the defaults:

* **`databaseProviderName`** The database provider name where this items are stored. Defaults to `main`

We're now ready to start retrieving Movie lists from the database. Let's see how we could simply get a list of all the movies on the database:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => []
]);
echo "{$movies->count()} Movies found";
```

```
30 Movies found
```

You can automatically fill your `Movies` object with `Movie` items when creating it by passing the `fillMethod` key as you see in the example above.

> Since we're not specifying any parameters in the `p` key, we'll simply get all movies in the database at once.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideItemLists) site.
{% endhint %}

Let's see how we could iterate through the results to show all the movie titles and their release years:

```php
foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
Alien (1979)
The Thing (1982)
Silent Running (1972)
Arrival (2016)
Interstellar (2014)
Ex Machina (2014)
2001: A Space Odyssey (1968)
The Martian (2015)
Planet of the Apes (1968)
Moon (2009)
Contact (1997)
The Man from Earth (2007)
Dune (1984)
Blade Runner (1982)
Brainstorm (1983)
The Hitchhiker’s Guide to the Galaxy (2005)
Blade Runner 2049 (2017)
Prometheus (2012)
The Last Starfighter (1984)
Enemy Mine (1985)
Explorers (1985)
Tron (1982)
WarGames (1983)
Close Encounters of the Third Kind (1977)
The War of the Worlds (1953)
The Day the Earth Stood Still (1951)
E.T. the Extra-Terrestrial (1982)
The Abyss (1989)
War of the Worlds (2005)
Super 8 (2011)
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideIterate) site.
{% endhint %}

## Limit results

To get only the first `n` results instead of all of them, you can specify the `limit` key when creating your `Movies` object, like this:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "limit" => 3
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
Alien (1979)
The Thing (1982)
Silent Running (1972)
```

## Results pagination

There's also a simple way of paginating results by specifying the `itemsPerPage` and `page` keys. Let's say you're dividing your movie listing in pages containing five movies each, and you want to get the third page. You would do it like this:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "isPaging" => true,
        "itemsPerPage" => 5,
        "page" => 2
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
Contact (1997)
The Man from Earth (2007)
Dune (1984)
Blade Runner (1982)
Brainstorm (1983)
```

> Remember that pages start at zero, not at 1.

## Iterating Items in a pattern

Since we already learned how to [pass variables to a pattern](/version-0.x/guide/patterns-guide/passing-variables-to-a-pattern), why don't we pass the `$movies` object to a pattern, and iterate it there to create a nice `<UL>` list? This is how it can be done:

We output the pattern using the [Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out) method, passing the `$movies` variable along:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "limit" => 5
]);

$e->Patterns->out("MoviesList.html", [
    "variables" => [
        "movies" => $movies
    ]
]);
```

We create the pattern `MoviesList.html` like this:

```markup
<html><body>

<ul>
    <?php foreach ($movies as $movie) { ?>
        <li><?=$movie->title?> (<?=$movie->year?>)</li>
    <?php } ?>
</ul>

</body></html>
```

And this is the result:

{% tabs %}
{% tab title="Browser" %}

* Alien (1979)
* The Thing (1982)
* Silent Running (1972)
* Arrival (2016)
* Interstellar (2014)
  {% endtab %}
  {% endtabs %}

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideIterateInPattern) site.
{% endhint %}


# Items custom filters

We've just seen how to retrieve very simple lists of Item objects from the database, but what about when you need to filter the results, join tables, specify extra SQL statements or get an ordered list of Items?

To do so, you can overload the `fillFromParameters` method of your `Items` class to take care of any additional filtering, ordering or querying you might need for your Item listings.

> The [Items::fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) method is in charge of requesting the database and loading the [Item](/version-0.x/reference/core-classes/item) objects in the list. It is called internally whenever you create your [Items](/version-0.x/architecture/items) object with the `fillMethod` key set as `fromParameters` .

For example, let's say we wanted a way to get movie listings containing only movies released on a specific year. We would overload the `fillFromParameters` method of our `Movies` object like this:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    
    function fillFromParameters($p = false) {
        // Treat parameters
        self::treatParameters($p, [
            "year" => [
                "default" => false
            ]
        ]);
        
        // Modify $p accordingly
        if ($p["year"]) {
            $p["wheres"][] = [
                "sqlPart" => "movies.year = ?",
                "values" => [
                    [
                        "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER,
                        "value" => $p["year"]
                    ]
                ]
            ];
        }
        
        // Call the parent fillFromParameters
        return parent::fillFromParameters($p);
    }
}
```

There are three important things we did here:

1. **Treat parameters:** We use the [BasicObject::treatParameters](/version-0.x/reference/core-classes/basicobject/basicobject-methods#treatparameters-and-usdparameters-usdsetup) helper method to treat the parameters passed via `$p`. In this case, we simply set up a default value of `false` for the `year` parameter. This way of treating parameters might come specially in handy when you have many parameters with default values and requisites.
2. **Modify $p accordingly**: Because we'll be sending the `$p` parameters array to the parent [fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) method that does all the work, we compose it now according to our special parameters. In this case, if we've got a `year` parameter, we add a new `where` statement to `$p` that will cause the final SQL statement to only request movies from the specified year.
3. **Call the parent fillFromParameters:** Because we're overloading the [fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) method to add our own Movie-specific logic, we now call the parent [fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) method, which is the one that does the actual work.

With this in place, our `Movies` object can now work with movies from a specific year, like this:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "year" => 1968
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
2001: A Space Odyssey (1968)
Planet of the Apes (1968)
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideCustomFilters) site.
{% endhint %}


# Items custom ordering

Just like the way you [customize filters](/version-0.x/guide/items-guide/items-custom-filters) in your Items object, you can also create custom orders to get ordered Item lists.

Let's say you want to be able to get movie lists ordered by the year they were released, from older to newer. You would overload the fillFromParameters method of your [Items](/version-0.x/reference/core-classes/items) object like this:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    
    function fillFromParameters($p = false) {
        // Treat parameters
        self::treatParameters($p, [
            "orders" => ["addArrayKeysIfNotExist" => [
                "released" => "movies.year asc"
            ]]
    		]);
        
        // Call the parent fillFromParameters
        return parent::fillFromParameters($p);
    }
}
```

This time, the only modification we did was to add a new ordering method to the [`orders`](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) `$p` parameter. Our ordering method is called `released`, and the SQL part responsible of the ordering is `movies.year desc`.

In the example we're using the [BasicObject::treatParameters](/version-0.x/reference/core-classes/basicobject/basicobject-methods#treatparameters-and-usdparameters-usdsetup) helper method that allows us to treat parameter hash arrays like `$p` more easily, specially when you have lots many parameters to treat.

> Without using [treatParameters](/version-0.x/reference/core-classes/basicobject/basicobject-methods#treatparameters-and-usdparameters-usdsetup), `$p["orders"]["released"] = "movies.year asc";` would've done almost the same.

And that's it, now we can use the Movies class to retrieve lists of movies ordered by their release year like this:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "order" => ["released"]
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
The Day the Earth Stood Still (1951)
The War of the Worlds (1953)
2001: A Space Odyssey (1968)
Planet of the Apes (1968)
Silent Running (1972)
Close Encounters of the Third Kind (1977)
Alien (1979)
The Thing (1982)
Blade Runner (1982)
Tron (1982)
E.T. the Extra-Terrestrial (1982)
Brainstorm (1983)
WarGames (1983)
Dune (1984)
The Last Starfighter (1984)
Enemy Mine (1985)
Explorers (1985)
The Abyss (1989)
Contact (1997)
The Hitchhiker’s Guide to the Galaxy (2005)
War of the Worlds (2005)
The Man from Earth (2007)
Moon (2009)
Super 8 (2011)
Prometheus (2012)
Interstellar (2014)
Ex Machina (2014)
The Martian (2015)
Arrival (2016)
Blade Runner 2049 (2017)
```

> Note that, when instantiating the Movies object, the order `key` is an array. This is because we can pass more than one orders to get lists ordered by multiple criteria at the same time. For example, ordering movies first by their release year, and then by their title. Take a look at [Mixing filters and ordering](/version-0.x/guide/items-guide/mixing-filters-and-ordering) for an example.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideCustomOrdering) site.
{% endhint %}


# Mixing filters and ordering

Let's take a look at a more advanced example of mixing both [custom filters](/version-0.x/guide/items-guide/items-custom-filters) and [custom ordering](/version-0.x/guide/items-guide/items-custom-ordering). This time, we'll setup the Movies class from [our past examples](/version-0.x/guide/items-guide/item-lists) so it can work with movies released between two given years, and it can order the results by their release year and by their title:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    
    function fillFromParameters($p = false) {
        // Treat parameters
        self::treatParameters($p, [
            "minYear" => ["default" => false],
            "maxYear" => ["default" => false],
            "orders" => ["addArrayKeysIfNotExist" => [
                "released" => "movies.year asc",
                "title" => "movies.title asc"
            ]]
        ]);
        
        // Modify $p accordingly
        if ($p["minYear"]) {
            $p["wheres"][] = [
                "sqlPart" => "movies.year >= ?",
                "values" => [
                    [
                        "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER,
                        "value" => $p["minYear"]
                    ]
                ]
            ];
        }
        
        if ($p["maxYear"]) {
            $p["wheres"][] = [
                "sqlPart" => "movies.year <= ?",
                "values" => [
                    [
                        "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER,
                        "value" => $p["maxYear"]
                    ]
                ]
            ];
        }
        
        // Call the parent fillFromParameters
        return parent::fillFromParameters($p);
    }
}
```

That's it, did you get it? Now we can use our new `Movies` class to get a neat list of movies released in the glorious 80's, ordered by their release year and title, check this out:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "minYear" => 1980,
        "maxYear" => 1989,
        "order" => ["released", "title"]
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} ({$movie->year})\n";
```

```
Blade Runner (1982)
E.T. the Extra-Terrestrial (1982)
The Thing (1982)
Tron (1982)
Brainstorm (1983)
WarGames (1983)
Dune (1984)
The Last Starfighter (1984)
Enemy Mine (1985)
Explorers (1985)
The Abyss (1989)
```

> Note that to get a listing ordered both by release year and title at the same time, instead of defining a single order in the `fillFromParameters` method, we define two, and then we apply both of them when instantiating our `Movies` object, by passing the array `["released", "title"]` in the `order` key.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideFiltersAndOrdering) site.
{% endhint %}


# Items with relationships

Cherrycake does not restricts you on how to establish relationships between tables in your database, and the [Item](/version-0.x/reference/core-classes/item) and [Items](/version-0.x/architecture/items) classes provide some capabilities that will help you build the relationship structure of your liking.

For example, in addition to our `movies` table, let's imagine we have also a simple `directors` table containing the names and birth years of movie directors, and that it looks like this:

| Field name      | Specs                                           |                                   |
| --------------- | ----------------------------------------------- | --------------------------------- |
| **`id`**        | `unsigned` `int` `auto_increment` `primary key` | The unique id to identify movies. |
| **`name`**      | `varchar`                                       | The name of the director.         |
| **`birthYear`** | `year`                                          | The year the director was born.   |

A simple relationship would be one that allows us to get the name of the director of one of our movies. Since we already defined our [`Movie`](/version-0.x/guide/items-guide#creating-an-item-class) class, let's now define a class to represent a director. We create the file `/classes/Director.class.php`, and it looks like this:

```php
<?php

namespace CherrycakeApp;

class Director extends \Cherrycake\Item {
    protected $tableName = "directors";
    protected $fields = [
        "id" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER
        ],
        "name" => [
            "type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING
        ]
    ];
}
```

Now, we add a method to our `Movie` class that allows us to get a `Director` object:

```php
class Movie extends \Cherrycake\Item {
    ...
    
    function getDirector() {
        return new Director([
            "loadMethod" => "fromId",
            "id" => $this->directorId
        ]);
    }
}
```

So now, whenever we have a `Movie` object, we can get its Director by calling the `getDirector` method, for example:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "limit" => 5,
        "order" => ["random"]
    ]
]);

foreach ($movies as $movie)
    echo "{$movie->title} directed by {$movie->getDirector()->name}\n";
```

```
Explorers directed by Joe Dante
E.T. the Extra-Terrestrial directed by Steven Spielberg
Tron directed by Steven Lisberger
Close Encounters of the Third Kind directed by Steven Spielberg
Arrival directed by Denis Villeneuve
```

Getting the director's name was this straightforward: `$movie->getDirector()->name`

> Note that in this example we've also applied the `random` order, which is always available in addition to your custom orders, to simply randomize the order of the resulting [Item](/version-0.x/reference/core-classes/item) objects.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideRelationships) site.
{% endhint %}

## Custom filtering with relationships

Quite often you'll need to look for data in other tables when using your [Items](/version-0.x/architecture/items) classes. For example, let's say we want to be able to get all the movies whose director was less than 35 years old when they were released.

This is done by [adding a custom filter](/version-0.x/guide/items-guide/items-custom-filters) to our Items class, but because the director's `birthYear` is in the `directors` table and not in the `movies` table, we'll need some way to access it in the new `Movies` custom filter.

We'll call this filter `releasedWhenDirectorWasYoungerThan`, and here's how it would be done:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    
    function fillFromParameters($p = false) {
        // Treat parameters
        self::treatParameters($p, [
            "releasedWhenDirectorWasYoungerThan" => [
                "default" => false
            ]
        ]);
        
        // Modify $p accordingly
        if ($p["releasedWhenDirectorWasYoungerThan"]) {
            $p["tables"][] = "directors";
            $p["wheres"][] = ["sqlPart" => "directors.id = movies.directorId"];
            $p["wheres"][] = [
                "sqlPart" => "movies.year - directors.birthYear <= ?",
                "values" => [
                    [
                        "type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER,
                        "value" => $p["releasedWhenDirectorWasYoungerThan"]
                    ]
                ]
            ];
        }
        }
        
        // Call the parent fillFromParameters
        return parent::fillFromParameters($p);
    }
}
```

Here's what we did in this filter:

* First we added the table `directors` to the `tables` parameter to make it available in our SQL statements by doing `$p["tables"][] = "directors";`
* Then we've added a new entry to the `wheres` array of SQL statements to connect the `directors` with the `movies` table, with the `sqlPart`: `directors.id = movies.directorId`
* Finally, we've added another where statement to filter out only the movies whose director was younger than the specified age when the movie was released, with the `sqlPart`:`movies.year - directors.birthYear <= ?`

> Remember that when using values coming from untrusted sources, it's highly recommended to use the [prepared queries methodology](/version-0.x/guide/database-guide/prepared-queries): Use a question mark `?` instead of the value, and then pass along the value specification in the `values` key of the array.

So now it's ready to run:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "releasedWhenDirectorWasYoungerThan" => 35
    ]
]);

foreach ($movies as $movie)
    echo
        "\"{$movie->title}\"".
        " directed by ".
        $movie->getDirector()->name.
        " at age ".
        ($movie->year - $movie->getDirector()->birthYear).
        "\n";
```

```
"The Thing" directed by John Carpenter at age 34
"Silent Running" directed by Douglas Trumbull at age 30
"The Hitchhiker’s Guide to the Galaxy" directed by Garth Jennings at age 33
"Tron" directed by Steven Lisberger at age 31
"Close Encounters of the Third Kind" directed by Steven Spielberg at age 31
"The Abyss" directed by James Cameron at age 35
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/itemsGuideFiltersWithRelationships) site.
{% endhint %}


# Items cache

Item lists are just as easily cacheable as [individual Items](/version-0.x/guide/items-guide/item-cache). Just set the `isCache` property to `true` in your Items object definition:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    protected $isCache = true;
    
    ...
}
```

You can also add this other properties if you can to change the default values for caching Items:

* **`cacheProviderName`** The name of the cache provider to use. Default: `engine`
* **`cacheTtl`** The TTL to use when caching data for this Item. Default: `CACHE_TTL_NORMAL`

Now, all the Movies queried using your `Movies` object will benefit of the caching performance improvements.

## Clearing Items specific cache

There are many situations on which you'll need to clear an Items list cache. For example, whenever a new item is added to the database, you'll need to clear the cache so the new item it will show up the next time the Items list is requested.

To clear an Items list cache, just call the clearCache method passing the same value you passed the `p` key when instantiating your Items object, or when you called the [Items::fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) method.

For example, let's take the [last example](/version-0.x/guide/items-guide/mixing-filters-and-ordering) of our Movies object, where we've got a list of movies released in the 80's, ordered by release year and title:

```php
$movies = new Movies([
    "fillMethod" => "fromParameters",
    "p" => [
        "minYear" => 1980,
        "maxYear" => 1989,
        "order" => ["released", "title"]
    ]
]);
```

If we wanted to clear the cache for this specific request, we would do this:

```php
$movies->clearCache([
        "minYear" => 1980,
        "maxYear" => 1989,
        "order" => ["released", "title"]
]);
```

## Clearing Items global cache with the CachedKeysPool mechanism

But what if we wanted to clear all the cached requests an Items object has done? Clearing the Items cache for a specific request like we did above does not clears the cache for requests with different parameters.

> Clearing the cache for movies released between 1980 and 1989 like we did above will not clear the cache for movies between different years, or ordered differently.

This is solved by activating the CachedKeysPool mechanism of our Items object, which will keep track of the cache keys of all the requests made, and will allow us to clear them all at once by calling the [clearCachedKeysPool](/version-0.x/reference/core-classes/items/items-methods#clearcachedkeyspool) method.

To activate the CachedKeysPool mechanism, we set the [cachedKeysPoolName](/version-0.x/reference/core-classes/items/items-properties#cachedkeyspoolname) property of our `Items` class to some pool name to identify this Item's cached keys, like so:

```php
class Movies extends \Cherrycake\Items {
    protected $tableName = "movies";
    protected $itemClassName = "\CherrycakeApp\Movie";
    protected $isCache = true;
    protected $cachedKeysPoolName = "movies";
    
    ...
    
}
```

So from now on, calling the [clearCachedKeysPool](/version-0.x/reference/core-classes/items/items-methods#clearcachedkeyspool) method will ensure all the cache related to queries performed using the `Movies` object are cleared:

```php
$movies->clearCachedKeysPool();
```


# HtmlDocument guide

When you're using Cherrycake to build a web app, the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module helps you create standard HTML structure headers and footers with some additional useful capabilities.

The two most important methods of the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module are [HtmlDocument::header](/version-0.x/reference/core-modules/htmldocument/htmldocument-methods#header) and [HtmlDocument::footer](/version-0.x/reference/core-modules/htmldocument/htmldocument-methods#footer), they both take care of building the usual `<html><body> ...` and `...</body></html>` tags. For example, take this code that outputs a simple HTML response to show a webpage:

```php
$e->Output->setResponse(new \Cherrycake\ResponseTextHtml([
    "code" => \Cherrycake\RESPONSE_OK,
    "payload" =>
        $e->HtmlDocument->header().
        "Hello world!".
        $e->HtmlDocument->footer()
]));
```

This would output the following HTML code:

```markup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="robots" content="index,follow" />
<link rel="stylesheet" type="text/css" href="/css?set=coreUiComponents:718d83f2e5ae92b539f90f7dc7e3ba24" />
<script type="text/javascript" src="/js?set=coreUiComponents:d41d8cd98f00b204e9800998ecf8427e"></script>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=2" />
</head>
<body>
Hello world!</body>
</html>
```

Take a look at the[ configuration of the HtmlDocument](/version-0.x/reference/core-modules/htmldocument), where you can configure the title of your page, description, keywords, and many other important aspects of your HTML document structure.

> See how HtmlDocument also took care of including a CSS stylesheet and a JavaScript script automatically. This will come in handy when you start using the [CSS and Javascript modules](/version-0.x/guide/css-and-javascript-guide).

## Common usage with Patterns

You might find quite helpful to use the [header](/version-0.x/reference/core-modules/htmldocument/htmldocument-methods#header) and [footer](/version-0.x/reference/core-modules/htmldocument/htmldocument-methods#footer) [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) methods in your HTML [patterns](/version-0.x/guide/patterns-guide). Just call them at the beginning and at the end of your pattern and you'll get a complete HTML document.

For example, take a look at this HTML pattern named `home.html`:

```markup
<?= $e->HtmlDocument->header() ?>
Hello world!
<?= $e->HtmlDocument->footer() ?>
```

Now we parse it and send it to the user's browser with [Patterns::out](/version-0.x/reference/core-modules/patterns/methods#out):

```php
$e->Patterns->out("home.html");
```

And we get exactly the same "Hello World!" HTML page as above.

Remembers to add the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module to your module's list of dependent core modules so it is available to use, like this:

```php
namespace CherrycakeApp\MyModule;

class MyModule extends \Cherrycake\Module {
    protected $dependentCoreModules = [
        "HtmlDocument"
    ];
    
    ...
}
```


# Css and Javascript guide

The [Css](/version-0.x/reference/core-modules/css) and [Javascript](/version-0.x/reference/core-modules/javascript) core modules allow you to easily work with CSS and JavaScript files in your web page project with some neat additional features:

* CSS and JavaScript files are parsed as [patterns](/version-0.x/architecture/patterns).
* Automatic minimization and single-request serving of multiple files.
* Cached CSS and JavaScript.
* Modules inject the CSS and JavaScript code they themselves.
* CSS and JavaScript dependencies via modules.
* Works in conjunction with [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) to automatically link the needed CSS/JavaScript resources in the HTML document.
* Only the required CSS and JavaScript code is loaded.

## Css and Javascript sets

When using the [Css](/version-0.x/reference/core-modules/css) or the [Javascript](/version-0.x/reference/core-modules/javascript) modules, you first define at least one set that will contain the `*.css` and `*.js` files you'll be using.

Sets are defined in the [Css module configuration file](/version-0.x/reference/core-modules/css#configuration) `/config/Css.config.php` and in the [Javascript module configuration file](/version-0.x/reference/core-modules/javascript#configuration) `/config/Javascript.config.php`.

Let's take a look at a typical `Css.config.php` configuration file:

```php
<?php

namespace Cherrycake;

$CssConfig = [
    "sets" => [
        "main" => [
            "directory" => APP_DIR."/css"
        ]
    ]
];
```

The `Javascript.config.php` configuration file looks quite similar:

```php
<?php

namespace Cherrycake;

$JavascriptConfig = [
    "sets" => [
        "main" => [
            "directory" => APP_DIR."/javascript"
        ]
    ]
];
```

> Each set can only load files from the directory you've configured.

You can add files to each set directly in the configuration file. Let's say we want to add the CSS file `base.css` to the `main` set, we would modify `Css.config.php` to look like this:

```php
<?php

namespace Cherrycake;

$CssConfig = [
    "sets" => [
        "main" => [
            "directory" => APP_DIR."/css",
            "files" => [
                "base.css"
            ]
        ]
    ]
];
```

You can also just set `isIncludeAllFilesInDirectory` to `true`, and all the `*.css` files in the specified `directory` will be added to the set:

```php
<?php

namespace Cherrycake;

$CssConfig = [
    "sets" => [
        "main" => [
            "directory" => APP_DIR."/css",
            "isIncludeAllFilesInDirectory" => true
        ]
    ]
];
```

> This works exactly the same for the `Javascript.config.php` file.

## CSS and JavaScript minification

To activate minification, set the `isMinify` key to `true` in the configuration file of the [Css](/version-0.x/reference/core-modules/css#configuration) or the [Javascript](/version-0.x/reference/core-modules/javascript#configuration) module:

```php
<?php

namespace Cherrycake;

$CssConfig = [
    "isMinify" => true,
    "sets" => [
        "main" => [
            "directory" => APP_DIR."/css",
            "isIncludeAllFilesInDirectory" => true
        ]
    ]
];
```

## CSS and JavaScript Caching and versioning

CSS and JavaScript are always cached automatically, and file versioning is automatically taken care of using content-based unique ids. Cherrycake ensures the browser caches the CSS and JavaScript requests, and that it is always receiving their latest versions if they have changed in the last update.

> This ultimately means that you don't need to take care of implementing a caching policy or versioning for your CSS or JavaScript files, and the visitors to your website won't need to clear their caches to load the proper updated CSS and JavaScript files.

## Linking the CSS and JavaScript to your HTML document

If you're using the [HtmlDocument](/version-0.x/guide/htmldocument-guide) module to build your HTML document, the proper links to get the required CSS and JavaScript sets are already being added automatically to the `<head>` section of the document:

```markup
...
<link rel="stylesheet" type="text/css" href="/css?set=coreUiComponents:718d83f2e5ae92b539f90f7dc7e3ba24-main:90deae3cd3e3bc042e83c0404f30c69f" />
<script type="text/javascript" src="/js?set=coreUiComponents:d41d8cd98f00b204e9800998ecf8427e-main:d41d8cd98f00b204e9800998ecf8427e"></script>
...
```

> If you're creating your own HTML document structure instead of using the [HtmlDocument](/version-0.x/guide/htmldocument-guide) module, you can call the [Css::getSetUrl](/version-0.x/reference/core-modules/css/css-methods#getseturl) and [Javascript::getSetUrl](/version-0.x/reference/core-modules/javascript/javascript-methods#getseturl) methods to retrieve the proper URLs to request the CSS and JavaScript code.

{% hint style="success" %}
A basic example of the usage of the Css module can be seen working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/cssAndJavascriptBasicExample) site.
{% endhint %}


# Modules injecting CSS and JavaScript

You know how to [add CSS or JavaScript files](/version-0.x/guide/css-and-javascript-guide) to your sets so they get loaded in your web app, there's a better way to do it so it follows the [Cherrycake modules logic](/version-0.x/guide/modules-guide) for encapsulation and dependency.

Since modules often represent isolated features of your web app, it makes sense to pair them with the piece of CSS and JavaScript code they need to run.

A simple way of doing it is by calling the [Css::addFileToSet](/version-0.x/reference/core-modules/css/css-methods#addfiletoset) or [Javascript::addFileToSet](/version-0.x/reference/core-modules/javascript/javascript-methods#addfiletoset) methods in the [init](/version-0.x/reference/core-classes/module/methods#init) method of your module, like this:

```php
<?php

namespace CherrycakeApp\Home;

class Home extends \Cherrycake\Module {

    function init() {
        if (!parent::init())
            return false;
        global $e;
        $e->Css->addFileToSet("main", "home.css");
        return true;
    }
    
}
```

> Don't forget to call [parent::init](/version-0.x/reference/core-classes/module/methods#init) before your module's own initialization tasks.

By doing this, you'll also get the benefits of dependencies: Whenever a module depends on another module, that module's CSS and JavaScript will also be loaded.

## Loading Css and JavaScript only where it's needed

Specially when certain areas of your web app depend on specific CSS or JavaScript code that is not used in any other part of the app, it makes sense to make those modules load their own files instead of adding them manually to the `Css.config.php` or `Javascript.config.php` files.

By doing so, that code will only be loaded when the modules that need those Css and JavaScript files are loaded. That is: when the user is visiting the areas in your web app that need them.

## Optimizing number of requests vs. CSS and JavaScript re-usability

A problem shows up when you start optimizing your site so certain Css or JavaScript only gets loaded in certain pages. Because Cherrycake joins all your CSS and JavaScript code in a single request to optimize loading times, you might find the browser loading different versions of the Css and JavaScript files on each page of your app when you have modules adding their own CSS and JavaScript files, defeating the purpose of using a cache and actually loading pieces of code that were already loaded in other requests with different CSS or JavaScript set configurations.

The question is: Shall I make the browser load all the CSS and JavaScript on the first page so the upcoming pages take advantage of the cache, or it's better to distribute my CSS and JavaScript in separate requests to different sets, so only the code needed for each page is loaded?

These are the options Cherrycake gives you to solve this problem:

* Setup the CSS and JavaScript files you want to load in your web app by listing them in the `Css.config.php` or `Javascript.config.php` files, or just set the `isIncludeAllFilesInDirectory` to `true` there, [as seen here](/version-0.x/guide/css-and-javascript-guide). All files in the specified directories will be loaded in the first request to your web app, and subsequent requests will take advantage of the browser's caching mechanism.
* Let your modules add the CSS and JavaScript they need by overloading the init method as you've seen [above](#loading-css-and-javascript-only-where-its-needed). Certain Css and JavaScript will only be loaded when the browser requests the pages that need them, but you might lose performance, caching and re-usability benefits if not done carefully.
* You can control which sets get joined in a single request, and divide them in different requests to further customize your CSS and JavaScript loading strategy by using the [HtmlDocument `cssSets` and `javascriptSets` configuration keys](/version-0.x/reference/core-modules/htmldocument#configuration).

If you're really looking to optimize your loading strategy, a good solution is to use a combination of the three approaches above:

* Manually add to the config files the CSS and JavaScript files you know you'll be reusing throughout your entire app, in the `main` set.
* Create one or more additional sets to hold other files used by modules that need special functionality, and load those files from the [init](/version-0.x/reference/core-classes/module/methods#init) method of those modules.
* Force the main set to be loaded in its own request, and the rest of the sets in another request, using the [HtmlDocument `cssSets` and `javascriptSets` configuration keys](/version-0.x/reference/core-modules/htmldocument#configuration).


# Session guide

The Session module provides a session tracking and session storage mechanism.

When using the [Session](/version-0.x/reference/core-modules/session) module, each visitor to your web app is assigned a random and secure unique identifier, and you'll be able to keep track of their activity across requests, and store visitor-specific data.

The most obvious use of a session mechanism like this is to implement a login system to let your users identify themselves with some sort of password, and give them access to their private sections and functionalities. This is exactly what the [Login module](/version-0.x/guide/login-guide) does using [Session](/version-0.x/reference/core-modules/session).

But you can use the [Session](/version-0.x/reference/core-modules/session) module for many other purposes. Let's see how.

## Setting up the Session database table

The [Session](/version-0.x/reference/core-modules/session) module uses the `cherrycake_session` table in the database to store the sessions information.

> You can create the Session table in your database by importing the `session.sql` file you'll find in the [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), under the `install/database` directory.

Because [Session](/version-0.x/reference/core-modules/session) needs a connection to a database, you need to set it but by creating a `/config/Database.config.php` file just like we did in the [Database guide](/version-0.x/guide/database-guide).

## Working with Session

First, let's remember our simple [Hello world web app](/version-0.x/guide/getting-started#the-hello-world-module), which worked with this basic `HelloWorld` app module:

```php
<?php

namespace CherrycakeApp\HelloWorld;

class HelloWorld extends \Cherrycake\Module {

    public static function mapActions() {
        global $e;
        $e->Actions->mapAction(
            "home",
            new \Cherrycake\ActionHtml([
                "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
                "moduleName" => "HelloWorld",
                "methodName" => "show",
                "request" => new \Cherrycake\Actions\Request([
                    "pathComponents" => false,
                    "parameters" => false
                ])
            ])
        );
    }
    
    function show() {
        global $e;
        $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
            "code" => \Cherrycake\RESPONSE_OK,
            "payload" =>
                $e->HtmlDocument->header().
                "Hello world!".
                $e->HtmlDocument->footer()
        ]));
    }
    
}
```

> Note we've updated the `show` method to use the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module to create the HTML document structure, now that we learned how it works in the [HtmlDocument Guide](/version-0.x/guide/htmldocument-guide).

Now, to use the [Session](/version-0.x/reference/core-modules/session) module, you first need to add it to the list of your core [module dependencies](/version-0.x/guide/modules-guide#specifying-module-dependencies), like this:

```php
class HelloWorld extends \Cherrycake\Module {
    protected $dependentCoreModules = [
        "Session"
    ];

    ...    
}
```

Now, let's say we want to show how many times the visitor has seen the Hello World page. We'll do this by storing the views counter in the visitor's session, like this:

```php
function show() {
    global $e;
    
    $e->Session->numberOfTimesViewed ++;
    
    $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
        "code" => \Cherrycake\RESPONSE_OK,
        "payload" =>
            $e->HtmlDocument->header().
            "You've seen this page {$e->Session->numberOfTimesViewed} times".
            $e->HtmlDocument->footer()
    ]));
}
```

Now, every time a visitor reloads the page they'll see the counter growing:

```
You've seen this page 2 times
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/sessionGuideExample) site.
{% endhint %}


# Login guide

The Login module provides a standardized method for implementing secure user identification workflows for web apps.

Using the [Login](/version-0.x/reference/core-modules/login) module, you're able to start implementing a secure password-based user authentication mechanism to your app.

Instead of implementing a complete user authentication workflow, the [Login](/version-0.x/reference/core-modules/login) module provides you a standardized method that you can adopt to create your authentication workflow, where things like the login form, the user database structure or the logout button are still up to you to implement to your liking.

Let's imagine we have in our database the following table called `users`, where we store all the users of our app, along with their login credentials:

| Field name         | Specs                                           |                                  |
| ------------------ | ----------------------------------------------- | -------------------------------- |
| **`id`**           | `unsigned` `int` `auto_increment` `primary key` | The unique id to identify users. |
| **`name`**         | `varchar`                                       | The name of the user.            |
| **`email`**        | `varchar`                                       | The email of the user.           |
| **`passwordHash`** | `varchar`                                       | The hashed password.             |

## Creating the User class

First thing to do is creating a class to represent a user in our app. This class must extend the `LoginUser` class, which in turn also extends the [Item](/version-0.x/reference/core-classes/item) class just as we learned in the [Items guide](/version-0.x/guide/items-guide), so it will be also the [Item](/version-0.x/reference/core-classes/item) class that will represent an individual user in your app. Our `User` class will start looking like this:

```php
<?php

namespace CherrycakeApp;

class User extends \Cherrycake\LoginUser {
    protected $tableName = "users";
    
    protected $fields = [
        "id" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER],
        "name" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING],
        "email" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING],
        "passwordHash" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING]
    ];
}
```

For our `User` class to work properly with the [Login](/version-0.x/reference/core-modules/login) module, we need to add two properties:

* **`userNameFieldName`** The name of the field that holds the user name we want our users to identify with.
* **`encryptedPasswordFieldName`** The name of the field that holds the encrypted password of the users.

It would end looking like this:

```php
<?php

namespace CherrycakeApp;

class User extends \Cherrycake\LoginUser {
    protected $tableName = "users";
    protected $userNameFieldName = "email";
    protected $encryptedPasswordFieldName = "passwordHash";
    
    protected $fields = [
        "id" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_INTEGER],
        "name" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING],
        "email" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING],
        "passwordHash" => ["type" => \Cherrycake\DATABASE_FIELD_TYPE_STRING]
    ];
}
```

Now we're ready to authenticate users in our web app, follow along in the next section to learn how to implement a complete login workflow using the [Login](/version-0.x/reference/core-modules/login) module.


# Creating a complete login workflow

The [Login](/version-0.x/reference/core-modules/login) module provides the logic for a user authentication mechanism, but it's up to you to build a form to ask the user for his credentials, or to implement any kind of interface for a user to authenticate in your web app.

We'll analyze step by step the example provided in the Cherrycake documentation examples [repository](https://github.com/tin-cat/cherrycake-documentation-examples), in the module called `LoginGuide`.

{% hint style="success" %}
See this complete login workflow working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/loginGuideHome) site.
{% endhint %}

First we'll create our module in `/src/LoginGuide/LoginGuide.class.php`:

```php
<?php

namespace CherrycakeApp\LoginGuide;

class LoginGuide extends \Cherrycake\Module {
    protected $dependentCoreModules = [
        "HtmlDocument",
        "Login"
    ];
}
```

> See how we've already added the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) and [Login](/version-0.x/reference/core-modules/login) dependencies.

Now we'll [define an action](/version-0.x/guide/actions-guide) that will show a welcome page when the user visits the `/login-guide` URL:

```php
<?php

namespace CherrycakeApp\LoguinGuide;

class LoginGuide extends \Cherrycake\Module {
    protected $dependentCoreModules = [
        "HtmlDocument",
        "Login"
    ];
    
    public static function mapActions() {
        global $e; 
        $e->Actions->mapAction(
            "loginGuideHome",
            new \Cherrycake\Actions\ActionHtml([
                "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
                "moduleName" => "LoginGuide",
                "methodName" => "home",
                "request" => new \Cherrycake\Actions\Request([
                    "pathComponents" => [
                        new \Cherrycake\Actions\RequestPathComponent([
                            "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                            "string" => "login-guide"
                        ])
                    ]
                ])
            ])
        );
    }
    
    function home() {
        global $e;
    
        $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
            "code" => \Cherrycake\RESPONSE_OK,
            "payload" =>
                $e->HtmlDocument->header().
                ($e->Login->isLogged() ?
                    "You are logged in"
                :
                    "You are not logged in"
                ).
                $e->HtmlDocument->footer()
        ]));
    }
}
```

Notice that the page shows the message `You are logged in` or `You are not logged in`. To determine whether the current user is logged in, we use the [Login::isLogged](/version-0.x/reference/core-modules/login/login-methods#islogged) method.

Now we'll add another action that will show a login form in the `/login-guide/login-page` URL:

```php
$e->Actions->mapAction(
    "loginGuideLoginPage",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "LoginGuide",
        "methodName" => "loginPage",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "login-guide"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "login-page"
                ])
            ]
        ])
    ])
);
```

```php
function loginPage() {
    global $e;

    $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
        "code" => \Cherrycake\RESPONSE_OK,
        "payload" =>
            $e->HtmlDocument->header().
            "
                <form method=post>
                    <input name=email type=text name=email placeholder=\"Email\" />
                    <input name=password type=password name=password placeholder=\"Password\" />
                    <input type=submit value=\"Login\"/>
                </form>
            ".
            $e->HtmlDocument->footer()
    ]));
}
```

And we'll add a button right next to the `You are not logged in` message, that will link to this login page:

```php
function home() {
    global $e;

    $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
        "code" => \Cherrycake\RESPONSE_OK,
        "payload" =>
            $e->HtmlDocument->header().
            ($e->Login->isLogged() ?
                "You are logged in"
            :
                "You are not logged in".
                "<a href=\"{$e->Actions->getAction("loginGuideLoginPage")->request->buildUrl()}\" class=button>Login</a>"
            ).
            $e->HtmlDocument->footer()
    ]));
}
```

See how, instead of linking directly to `/login-guide/login-page`, we've used the [Actions::getAction](/version-0.x/reference/core-modules/actions-1/actions#getaction) and the [Request::buildUrl](/version-0.x/reference/core-classes/request/request-methods#buildurl) methods in chain to obtain the URL for the action that triggers the login page, as you've learned in the [Actions guide](/version-0.x/guide/actions-guide/getting-the-url-of-an-action).

So now, when we access the /login-guide page, this appears:

![](/files/-M6zpj34mg4e9ie2-oq1)

And when we click the Login button, the `/login-guide/login-page` appears:

![](/files/-M6zpMdL9xgNhBDayVj8)

> Clicking the `Login` button does nothing because we haven't yet set the `action` property of the form HTML element.

Now let's create an action that will be triggered when the `Login` button is clicked. This action will use the Login module to check the received `email` and `password`, and act accordingly afterwards.

We'll call this action `loginGuideDoLogin`:

```php
$e->Actions->mapAction(
    "loginGuideDoLogin",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "LoginGuide",
        "methodName" => "doLogin",
        "request" => new \Cherrycake\Actions\Request([
            "isSecurityCsrf" => true,
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "login-guide"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "do-login"
                ])
            ]
        ]),
        "isSensibleToBruteForceAttacks" => true
    ])
);
```

> We've set the [`isSensibleToBruteForceAttacks`](/version-0.x/reference/core-classes/action/methods#__construct) parameter to true when creating the [Action](/version-0.x/reference/core-classes/action) to improve the resistance of this request to brute force attacks. We've also set the [`isSecurityCsrf`](/version-0.x/reference/core-classes/request/request-methods#__construct) parameter to true when creating the [Request](/version-0.x/reference/core-classes/request), which adds protection against Cross-Site Request Forgery-type attacks to this request.

Now we need to modify the login form in the `loginPage` method to make it request this `loginGuideDoLogin` action URL whenever its posted. We've already seen how to retrieve the URL of an action above. In this case, we'll do it like this: `$e->Actions->getAction("loginGuideDoLogin")->request->buildUrl();`

And this is how it looks when implemented in the form:

```php
"
    <form method=post action=\"{$e->Actions->getAction("loginGuideDoLogin")->request->buildUrl()}\">
        <input name=email type=text name=email placeholder=\"Email\" />
        <input name=password type=password name=password placeholder=\"Password\" />
        <input type=submit value=\"Login\"/>
    </form>
"
```

And here's how the `doLogin` method looks:

```php
function doLogin($request) {
    global $e;
    $result = $e->Login->doLogin($request->email, $request->password);
    if (
        $result == \Cherrycake\Login\LOGIN_RESULT_FAILED_UNKNOWN_USER
        ||
        $result == \Cherrycake\Login\LOGIN_RESULT_FAILED_WRONG_PASSWORD
    ) {
        $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
            "code" => \Cherrycake\RESPONSE_OK,
            "payload" => $e->HtmlDocument->header()."Login error".$e->HtmlDocument->footer()
        ]));
    }
    else {
        $e->Output->setResponse(new \Cherrycake\Actions\Response([
            "code" => \Cherrycake\RESPONSE_REDIRECT_FOUND,
            "url" => $e->Actions->getAction("loginGuideHome")->request->buildUrl()
        ]));
    }
}
```

Note we've used the [Login::doLogin](/version-0.x/reference/core-modules/login/login-methods#dologin) method to check the passed email and password. If the login failed, we show a simple error page. If it was successful, we redirect the user to the login home using [Output::setResponse](/version-0.x/reference/core-modules/output/methods#setresponse) with a [RESPONSE\_REDIRECT\_FOUND](/version-0.x/reference/core-modules/output#constants) code.

{% hint style="info" %}
To login with the example users in the Cherrycake documentation examples skeleton database, you can use the following email/password combinations:

* **Douglas Engelbart**
  * Email: `doug@berkeley.edu`
  * Password: `TheMotherOfAllDemos413`
* **John Horton Conway**
  * Email: `johnny@princeton.org`
  * Password: `lavidaloca`
* **Frank Abagnale**
  * Email: `frank.abagnale@united.com`
  * Password: `catch_me_?_you_can`
* **Carl Sagan**
  * Email: `carl@cosmos.org`
  * Password: `palebluedot34`
* **Richard Feynmann**
  * Email: `ricky@mit.edu`
  * Password: `137`
    {% endhint %}

Now, when you login with a correct email and password, you'll get redirected to the Login guide home, and the message `You are logged in` will be shown.

What if we wanted to show the user name there? Something like `You are logged in as <user name>`. Well, since the [Login](/version-0.x/reference/core-modules/login) module does all the work of retrieving the logged user for you, as long as you have the [Login](/version-0.x/reference/core-modules/login) module as a dependency in your modules, you'll be able to access the logged `User` object at any time via `$e->Login->user`. This is how we would modify the `home` method in our example to include the user name:

```php
"You are logged in as {$e->Login->user->name}"
```

## Adding a logout button

Let's add a logout button now. First, we'll create a new action to perform the logout operation, we'll call it `loginGuideLogout`, and it will be triggered with the `/login-guide/logout` URL:

```php
$e->Actions->mapAction(
    "loginGuideLogout",
    new \Cherrycake\Actions\ActionHtml([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "LoginGuide",
        "methodName" => "logout",
        "request" => new \Cherrycake\Actions\Request([
            "pathComponents" => [
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "login-guide"
                ]),
                new \Cherrycake\Actions\RequestPathComponent([
                    "type" => \Cherrycake\REQUEST_PATH_COMPONENT_TYPE_FIXED,
                    "string" => "logout"
                ])
            ]
        ])
    ])
);
```

Now, just like we did before, we add a logout button in the `home` method that will appear along the `Your are logged in as ...` message. This time, to get the logout URL we use `$e->Actions->getAction("loginGuideLogout")->request->buildUrl();`

```php
function home() {
    global $e;

    $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
        "code" => \Cherrycake\RESPONSE_OK,
        "payload" =>
            $e->HtmlDocument->header().
            ($e->Login->isLogged() ?
                "You are logged in as {$e->Login->user->name}".
                "<a href=\"{$e->Actions->getAction("loginGuideLogout")->request->buildUrl()}\" class=button>Logout</a>"
            :
                "You are not logged in".
                "<a href=\"{$e->Actions->getAction("loginGuideLoginPage")->request->buildUrl()}\" class=button>Login</a>"
            ).
            $e->HtmlDocument->footer()
    ]));
}
```

And now we implement the `logout` method like this:

```php
function logout() {
    global $e;
    $e->Login->logoutUser();
    $e->Output->setResponse(new \Cherrycake\Actions\Response([
        "code" => \Cherrycake\RESPONSE_REDIRECT_FOUND,
        "url" => $e->Actions->getAction("loginGuideHome")->request->buildUrl()
    ]));
}
```

This calls the [Login::logoutUser](/version-0.x/reference/core-modules/login/login-methods#logoutuser) method and then redirects them to the login home page.

## Encrypting user passwords

You're in charge of adding new users to your database and storing their credentials in the fields you've specified when [creating your User class](/version-0.x/guide/login-guide#creating-the-user-class).

The [Login](/version-0.x/reference/core-modules/login) module uses by default a very secure salted password hashing mechanism which implements a [Password-Based Key Derivation Function](https://en.wikipedia.org/wiki/PBKDF2) method, a [Key stretching](https://en.wikipedia.org/wiki/Key_stretching) algorithm. This method is compliant with the PBKDF2 test vectors specified in the [RFC 6070](https://www.ietf.org/rfc/rfc6070.txt), and is based on the [implementation](https://github.com/defuse/password-hashing) by [Taylor Hornby](https://github.com/defuse) from [Defuse.ca](https://defuse.ca).

To generate a password hash to be stored in the database, use the [Login::encryptPassword](/version-0.x/reference/core-modules/login/login-methods#encryptpassword) method, like this:

```php
echo $e->Login->encryptPassword("mypassword");
```

```
sha512:100000:I3Yrl8zztLfTj0Lu04rbNDsprLQKSz8Z:farmXBKJuxjcgrg9ELnDnZkKmzOHx5EL
```


# Locale guide

The Locale module provides a mechanism to build apps that adapt to users using different languages, timezones, currencies and other local unit standards.

To allow your app to work with different languages and localization settings, you must at least set up the `availableLocales`, `defaultLocale`, `canonicalLocale` and `availableLanguages` [configuration keys](/version-0.x/reference/core-modules/locale#configuration) in the `config/Locale.config.php` file like this:

```php
<?php

namespace Cherrycake;

$LocaleConfig = [
	"availableLocales" => [
		"main" => [
			"language" => LANGUAGE_ENGLISH,
			"dateFormat" => DATE_FORMAT_MIDDLE_ENDIAN,
			"temperatureUnits" => TEMPERATURE_UNITS_FAHRENHEIT,
			"currency" => CURRENCY_USD,
			"decimalMark" => DECIMAL_MARK_POINT,
			"measurementSystem" => MEASUREMENT_SYSTEM_IMPERIAL,
			"timeZone" => TIMEZONE_ID_ETC_UTC
		]
	],
	"defaultLocale" => "main",
	"canonicalLocale" => "main",
	"availableLanguages" => [LANGUAGE_ENGLISH]
];
```

* **`availableLocales`** The different localizations your app will support. See the [Locale configuration](/version-0.x/reference/core-modules/locale#configuration) for an explanation of the available options.
* **`defaultLocale`** The name of the locale to use as default.
* **`canonicalLocale`** The name of the locale to be considered the main locale of the app.
* **`availableLanguages`** An array of the languages that will be available in the app, from the available [`LANGUAGE_?`](/version-0.x/reference/core-modules/locale#constants) constants.

> If you don't setup your own `availableLocales`, or if you don't create a [Locale](/version-0.x/reference/core-modules/locale) configuration file at all, a default locale named `main` will be used with the [default configuration values](/version-0.x/reference/core-modules/locale#configuration).

Once your `availableLocales` are in place, you can choose the locale to use by calling the [Locale::setLocale](/version-0.x/reference/core-modules/locale/locale-methods#setlocale-localename) method. From that point on, all the texts, dates, timezones and other localized data will be retrieved using that locale's setup. For example:

```php
echo $e->Locale->formatTimestamp(time());
echo $e->Locale->formatCurrency(19.5);
echo $e->Locale->getTimeZoneName();
```

```
5/18/20
USD19.50
Etc/UTC
```

## Multiple locales

If your app supports multiple localized versions with different languages or localization configurations, you just add more locales to your `Locale.config.php` file. Imagine we have a web site with a global version in english, and a local version for Spain:

```php
<?php

namespace Cherrycake;

$LocaleConfig = [
	"availableLocales" => [
		"global" => [
			"language" => LANGUAGE_ENGLISH,
			"dateFormat" => DATE_FORMAT_MIDDLE_ENDIAN,
			"temperatureUnits" => TEMPERATURE_UNITS_FAHRENHEIT,
			"currency" => CURRENCY_USD,
			"decimalMark" => DECIMAL_MARK_POINT,
			"measurementSystem" => MEASUREMENT_SYSTEM_IMPERIAL,
			"timeZone" => TIMEZONE_ID_ETC_UTC
		],
		"spain" => [
			"language" => LANGUAGE_SPANISH,
			"dateFormat" => DATE_FORMAT_LITTLE_ENDIAN,
			"temperatureUnits" => TEMPERATURE_UNITS_CELSIUS,
			"currency" => CURRENCY_EURO,
			"decimalMark" => DECIMAL_MARK_COMMA,
			"measurementSystem" => MEASUREMENT_SYSTEM_METRIC,
			"timeZone" => TIMEZONE_ID_EUROPE_MADRID
		]
	],
	"defaultLocale" => "global",
	"canonicalLocale" => "global",
	"availableLanguages" => [LANGUAGE_ENGLISH, LANGUAGE_SPANISH]
];
```

Now, we can switch the working locale whenever we need, and Locale will act accordingly:

```php
echo $e->Locale->formatTimestamp(time());
echo $e->Locale->formatCurrency(19.5);
echo $e->Locale->getTimeZoneName();

$e->Locale->setLocale("spain");

echo $e->Locale->formatTimestamp(time());
echo $e->Locale->formatCurrency(19.5);
echo $e->Locale->getTimeZoneName();
```

```
5/18/20
USD19.50
Etc/UTC

18/5/20
19,50€
Europe/Madrid
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/localeGuideBasic) site.
{% endhint %}


# Multilingual texts

Locale allows you to change the language of your app based on the selected locale.

To use the multilingual text features of the [Locale](/version-0.x/reference/core-modules/locale) module, Cherrycake uses the `cherrycake_locale_texts` and `cherrycake_locale_textcategories` database tables with the following structure:

> You can create this tables in your database by importing the `locale.sql` file you'll find in the [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), under the `install/database` directory.

## Text categories

Optionally, texts in the database can be organized in categories, this might come in handy if you have lots of texts.

Add your text categories as rows to the `cherrycake_locale_textcategories` table, here's the columns specification:

* **`code`** A unique identifier for the category, you'll be using it later to refer to this category in your code.
* **`description`** Describe the kind of texts you'll be storing in this category.

## Adding texts

Add translated texts as rows to the `cherrycake_locale_texts` table, with this column specification:

* **`textCategories_id`** The category id assigned in the `cherrycake_locale_textcategories` table.
* **`code`** A unique identifier for the text, you'll be using it later to refer to this text in your code.
* **`description`** Describe this text, and the context where it will be used.
* **`text_en`** The text in english.

## Retrieving multilingual texts

To retrieve a text based on the current locale language, use the [Locale::getText](/version-0.x/reference/core-modules/locale/locale-methods#gettext) method. Imagine the `cherrycake_locale_textcategories` like this:

| id | code    | description                             |
| -- | ------- | --------------------------------------- |
| 1  | general | General texts used throughout the site. |

And the `cherrycake_locale_texts` tables like this:

| id | textCategories\_id | code | description                               | text\_en    | text\_es   |
| -- | ------------------ | ---- | ----------------------------------------- | ----------- | ---------- |
| 1  | 1                  | test | The typical test text used as an example. | Hello world | Hola mundo |

You would access the text like this:

```php
echo $e->Locale->getText("general/test");
$e->Locale->setLocale("spain");
echo $e->Locale->getText("general/test");
```

```
Hello world
Hola mundo
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/localeGuideMultilingualTexts) site.
{% endhint %}

## Adding new languages

To add new languages, just add new columns to the cherrycake\_locale\_texts table. The column name must follow the syntax `text_<language code>` For example, to add a text field for spanish, add the a field named `text_es`.

## Variables in localized texts

You can use simple variables in localized texts to help you build more complex sentences, like this:

| textCategories\_id | code        | text\_en                                  | text\_es                                   |
| ------------------ | ----------- | ----------------------------------------- | ------------------------------------------ |
| 1                  | newMessages | You have {numberOfMessages} new messages. | Tienes {numberOfMessages} mensajes nuevos. |

```php
echo $e->Locale->getText("general/newMessages", [
    "variables" => [
        "numberOfMessages" => 5
    ]
]);
```

```
You have 5 new messages.
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/localeGuideVariablesInMultilingualTexts) site.
{% endhint %}


# Domain based site localization

[Locale](/version-0.x/reference/core-modules/locale) can automatically determine which one of the configured [`availableLocales`](/version-0.x/reference/core-modules/locale#configuration) to use based on the domain the user is visiting. To do this, just add the [`domains`](/version-0.x/reference/core-modules/locale#configuration) key when configuring your `availableLocales`.

For example, imagine the main english version of your web site runs on the domain [`litmind.com`](https://litmind.com), and you want the spanish version of the website to run under [`es.litmind.com`](https://es.litmind.com). Your `Locale.config.php` might look something like this:

```php
<?php

namespace Cherrycake;

$LocaleConfig = [
	"availableLocales" => [
		"main" => [
			"domains" => ["litmind.com"],
			"language" => LANGUAGE_ENGLISH,
			"dateFormat" => DATE_FORMAT_MIDDLE_ENDIAN,
			"temperatureUnits" => TEMPERATURE_UNITS_FAHRENHEIT,
			"currency" => CURRENCY_USD,
			"decimalMark" => DECIMAL_MARK_POINT,
			"measurementSystem" => MEASUREMENT_SYSTEM_IMPERIAL,
			"timeZone" => TIMEZONE_ID_ETC_UTC
		],
		"spain" => [
			"domains" => ["es.litmind.com"],
			"language" => LANGUAGE_SPANISH,
			"dateFormat" => DATE_FORMAT_LITTLE_ENDIAN,
			"temperatureUnits" => TEMPERATURE_UNITS_CELSIUS,
			"currency" => CURRENCY_EURO,
			"decimalMark" => DECIMAL_MARK_COMMA,
			"measurementSystem" => MEASUREMENT_SYSTEM_METRIC,
			"timeZone" => TIMEZONE_ID_EUROPE_MADRID
		]
	],
	"defaultLocale" => "main",
	"canonicalLocale" => "main",
	"availableLanguages" => [LANGUAGE_ENGLISH, LANGUAGE_SPANISH]
];
```

With this setup, the `main` locale will be automatically selected when visiting the site using the `litmind.com`, and the `spain` locale when visiting via `es.litmind.com`.

> Separating your website locales in different domains like this is one of the ways [Google recommends](https://support.google.com/webmasters/answer/182192#locale-specific-urls) to organize multilingual web sites for optimal SEO.

## Automatically redirecting users to the matching locale domain

[Google doesn't recommend](https://support.google.com/webmasters/answer/182192) performing an automatic redirection based on the user's perceived language or the geotargeting based on the client IP, and [Locale](/version-0.x/reference/core-modules/locale) doesn't implement such a mechanism for that reason.

Instead, you might want to give the user the option to switch to another language/localization of your site, specially if you've detected that it's different than the one he is currently visiting.

## Let Google discover the different versions of your site

For SEO purposes, it's quite important to help Google discover the different versions of your site when you have multilingual sites. One of the [recommended ways](https://support.google.com/webmasters/answer/189077) of doing so is by specifying `alternate` meta tags in your HTML `HEAD` section.


# Log guide

The [Log](/version-0.x/reference/core-modules/log) module stores app-related events in a persistent log as they occur, aimed at providing a log of meaningful events that happened in your app, like when a user signs up, an invoice is generated, an API call is received, and whatever other events you deem important enough to be logged for future reference or analysis.

## Setting up the Log database table

Events are stored in the `log` database table using a shared-memory buffer and a programmed [Janitor](/version-0.x/guide/janitor-guide) commit task for optimal performance, resulting in a system capable of ingesting many events per second without a noticeable performance impact.

> You can create the `log` table in your database by importing the `log.sql` file you'll find in the [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), under the `install/database` directory.

## Log events

[Log](/version-0.x/reference/core-modules/log) events are stored as objects that extend the base [LogEvent](/version-0.x/reference/core-classes/logevent) class, so you create a class for every event you want to log.

Imagine you would like to log an event every time a someone searches for a movie in your app. To do so, we would first create the class `LogEventMovieSearch` in the file `classes/LogEventMovieSearch.class.php` like this:

```php
<?php

namespace CherrycakeApp;

class LogEventMovieSearch extends \Cherrycake\Log\LogEvent {
    protected $typeDescription = "Movie search";
}
```

And we trigger the [LogEvent](/version-0.x/reference/core-classes/logevent) like this:

```php
$e->Log->logEvent(new LogEventMovieSearch);
```

[LogEvent](/version-0.x/reference/core-classes/logevent) objects can carry some additional data to better describe the event, in our case, we could add the movie title the user searched for, like this:

```php
$e->Log->logEvent(new LogEventMovieSearch([
	"additionalData" => [
		"movieTitle" => "Blade Runner"
	]
]));
```

## Simplifying Log events with additional data

You can further simplify the way you trigger Log events by overloading your event's [loadInline](/version-0.x/reference/core-classes/item/item-methods#loadinline) method. Let's say instead of passing the whole `additionalData` hash array like we did above, we wanted to be able to just pass the movie title and let the constructor take care of it. We would do it like this:

```php
<?php

namespace CherrycakeApp;

class LogEventMovieSearch extends \Cherrycake\LogEvent {
    protected $typeDescription = "Movie search";
    
    function loadInline($movieTitle = false) {
        parent::loadInline([
            "additionalData" => [
                "movieTitle" => $movieTitle
            ]
        ]);
    }
}
```

So now we can trigger the event in this simplified way, and the movie title will be stored along with it:

```php
$e->Log->logEvent(new LogEventMovieSearch("Blade Runner"));
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/movieSearch) site.
{% endhint %}

## Storing outher ids in Log events

Sometimes you might want to store ids from items in other tables from your database in your Log events.

For example, let's say that whenever a user that has logged in to your app searches for a movie like we did in the example above, its user id gets also stored in the `LogEventMovieSearch`. To do it, we would modify the `LogEventMovieSearch` class like this:

```php
<?php

namespace CherrycakeApp;

class LogEventMovieSearch extends \Cherrycake\Log\LogEvent {
    protected $typeDescription = "Movie search";
    protected $outherIdDescription = "Logged user id";
    
    function loadInline($movieTitle = false) {
        global $e;
        $e->loadCoreModule("Login");
        parent::loadInline([
            "outher_id" => $e->Login->isLogged() ? $e->Login->user->id : false,
            "additionalData" => [
                "movieTitle" => $movieTitle
            ]
        ]);
    }
}
```


# Loading Log events from the database

Since the [LogEvent](/version-0.x/reference/core-classes/logevent) class extends the [Item](/version-0.x/reference/core-classes/item) class, and the [LogEvents](/version-0.x/reference/core-classes/logevents) class extends the [Items](/version-0.x/reference/core-classes/items) class, you can use them to load lists of [LogEvent](/version-0.x/reference/core-classes/logevent) objects from the database to work with.

For example, let's load the last fifty [LogEvent](/version-0.x/reference/core-classes/logevent) objects from the [Log](/version-0.x/reference/core-modules/log) database, using what we learned in the [Item lists](/version-0.x/guide/items-guide/item-lists) section of the [Items guide](/version-0.x/guide/items-guide):

```php
$logEvents = new \Cherrycake\Log\LogEvents([
	"p" => [
		"limit" => 50
	]
]);

foreach ($logEvents as $logEvent) {
	echo
		"[".$e->Locale->formatTimestamp($logEvent->dateAdded, ["isHours" => true, "isSeconds" => true])."] ".
		$logEvent->type.
		"\n";
}
```

The [LogEvents](/version-0.x/reference/core-classes/logevents) class accepts some additional keys on top of the usual [Items::fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) keys:

* **`type`** Retrieves only [LogEvent](/version-0.x/reference/core-classes/logevent) objects of this class name. Must include the full namespace route to the class.
* **`fromTimestamp`** Retrieves [LogEvent](/version-0.x/reference/core-classes/logevent) objects triggered after this timestamp.
* **`toTimestamp`** Retrieves [LogEvent](/version-0.x/reference/core-classes/logevent) objects triggered up to this timestamp.

```
[5/26/20 11:22.24] CherrycakeApp\LogEventMovieSearch
[5/26/20 10:55.28] CherrycakeApp\LogEventMovieSearch
[5/26/20 10:55.25] CherrycakeApp\LogEventMovieSearch
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/movieSearchLog) site.
{% endhint %}


# Stats guide

The [Stats](/version-0.x/reference/core-modules/stats) module stores statistical events in a persistent log as they occur, aimed at providing insight about the activity in your app like the number of received visits in a web page, page views, clicks, hits or other similar statistical data.

## Setting up the Stats database table

Events are stored in the `cherrycake_stats` database table using a shared-memory buffer and a programmed [Janitor](/version-0.x/guide/janitor-guide) commit task for optimal performance, resulting in a system capable of ingesting many events per second without a noticeable performance impact.

> You can create the Stats table in your database by importing the `stats.sql` file you'll find in the [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), under the `install/database` directory.

## Creating a StatsEvent

[Stats](/version-0.x/reference/core-modules/stats) events are stored as objects that extend the base [StatsEvent](/version-0.x/reference/core-classes/statsevent) class. You must create one [StatsEvent](/version-0.x/reference/core-classes/statsevent) class per each statistical data point you want to store.

Let's say you want to keep track of the number of views received by the home page of your web site app every day. To do so we'll create a new class called `StatsEventHomeView` in the `classes/StatsEventHomeView.class.php` file, like this:

```php
<?php

namespace CherrycakeApp;

class StatsEventHomeView extends \Cherrycake\Stats\StatsEvent {
	protected $timeResolution = \Cherrycake\Stats\STATS_EVENT_TIME_RESOLUTION_DAY;
	protected $typeDescription = "Home view";
}
```

Note that we specified [`STATS_EVENT_TIME_RESOLUTION_DAY`](/version-0.x/reference/core-classes/statsevent#constants) as the `timeResolution` for our `StatsEventHomeView`. This will cause this event to be counted in a daily basis, meaning only one row will be stored in the database for each different day, along containing a counter of the number of times the event has been triggered during that day.

You can specify other time resolutions as well, all of them are self-explanatory:

* **`STATS_EVENT_TIME_RESOLUTION_MINUTE`**
* **`STATS_EVENT_TIME_RESOLUTION_HOUR`**
* **`STATS_EVENT_TIME_RESOLUTION_DAY`**
* **`STATS_EVENT_TIME_RESOLUTION_MONTH`**
* **`STATS_EVENT_TIME_RESOLUTION_YEAR`**

You should choose the time resolution that better fits your needs, keeping in mind that events defined with a smaller time resolution will need more rows in the database.

> If you need a precise log of events instead of the statistical approach of counting the times an event is triggered within a time frame, see the [Log guide](/version-0.x/guide/log-guide) module instead.

## Triggering a Stats event

In the part of your code where you want to trigger the stats event, call the [Stats::trigger](/version-0.x/reference/core-modules/stats/stats-methods#trigger-statsevent) method like this:

```php
$e->Stats->trigger(new StatsEventHomeView);
```

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/statsGuideTriggeringEvent) site.
{% endhint %}

## What's the difference between a LogEvent and a StatsEvent?

The [Log](/version-0.x/reference/core-modules/log) module stores an object in the database for each logged event, allowing individual events to hold their own unique data, but causing the database to grow rapidly when lots of [LogEvent](/version-0.x/reference/core-classes/logevent) objects are stored.

[Stats](/version-0.x/reference/core-modules/stats), in the other hand, stores a single object in the database for all the events triggered during a certain period. This doesn't allows for individual [Stats](/version-0.x/reference/core-modules/stats) events to hold their own differentiating data because it only stores the number of times a certain event has been triggered, but makes [Stats](/version-0.x/reference/core-modules/stats) a more suitable solution to store big amounts of events, and it's an ideal solution to store statistical data of any kind.


# Stats events with additional dimensions

Adding additional dimensions to a [StatsEvent](/version-0.x/reference/core-classes/statsevent) class allows you to keep track of the event in relation to a certain identifier. The best way to understand this is via an example:

Imagine you want to trigger a StatsEvent every time a user in your web app logs in. A simple way of doing this would be to create a `StatsEventUserLogin` class just like we saw in the [Stats guide](/version-0.x/guide/stats-guide) main section:

```php
<?php

namespace CherrycakeApp;

class StatsEventUserLogin extends \Cherrycake\Stats\StatsEvent {
	protected $timeResolution = \Cherrycake\Stats\STATS_EVENT_TIME_RESOLUTION_DAY;
	protected $typeDescription = "User login";
}
```

To trigger this StatsEvent in the example we saw in the [Creating a complete login workflow](/version-0.x/guide/login-guide/creating-a-complete-login-workflow) section, we would do it in the `doLogin` method, like this:

```php
function doLogin($request) {
    global $e;
    $result = $e->Login->doLogin($request->email, $request->password);
    if (
        $result == \Cherrycake\Login\LOGIN_RESULT_FAILED_UNKNOWN_USER
        ||
        $result == \Cherrycake\Login\LOGIN_RESULT_FAILED_WRONG_PASSWORD
    ) {    
        $e->Output->setResponse(new \Cherrycake\Actions\ResponseTextHtml([
            "code" => \Cherrycake\Output\RESPONSE_OK,
            "payload" => $e->HtmlDocument->header()."Login error".$e->HtmlDocument->footer()
        ]));
    }
    else {
        $e->Stats->trigger(new StatsEventUserLogin);
        
        $e->Output->setResponse(new \Cherrycake\Actions\Response([
            "code" => \Cherrycake\Outut\RESPONSE_REDIRECT_FOUND,
            "url" => $e->Actions->getAction("loginGuideHome")->request->buildUrl()
        ]));
    }
}
```

But what if we wanted to keep track of the times each individual user logs in? That's exactly what an additional dimension would do. In this case, the additional dimension would be the user's id.

To add the user id as an additional dimension to the `StatsEventUserLogin` class, we would modify it like this:

```php
<?php

namespace CherrycakeApp;

class StatsEventUserLogin extends \Cherrycake\Stats\StatsEvent {
    protected $timeResolution = \Cherrycake\Stats\STATS_EVENT_TIME_RESOLUTION_DAY;
    protected $typeDescription = "User login";
    protected $isSecondaryId = true;
    protected $secondaryIdDescription = "User id";

    function loadInline($data = false) {
        if ($data["userId"] ?? false)
            $this->secondary_id = $data["userId"];		
        return parent::loadInline($data);
    }
}
```

Notice we've added the `$isSecondaryId` and `$secondaryIdDescription` properties, and we overloaded the `StatsEvent::loadInline` method to retrieve the passed `userId` key and assign it to the `secondary_id` property. Don't forget to call the parent constructor at the end there.

So now, when triggering the `StatsEventUserLogin` event, we can pass the user's id like this:

```php
$e->Stats->trigger(new StatsEventUserLogin(["userId" => $e->Login->user->id]));
```

> You can create another additional dimension by setting the `$isTertiaryId` and `$tertiaryIdDescription` properties, and updating the `loadInline` method accordingly.

Using additional dimensions like this will add multiple rows to the database per each time frame and different dimension value, take into account that this will of course cause the stats table to grow a lot bigger.

{% hint style="success" %}
See this example working in the [Cherrycake documentation examples](https://documentation-examples.cherrycake.io/example/statsGuideAdditionalDimensions) site.
{% endhint %}


# Loading Stats events from the database

Just like when [loading SystemLogEvents from the database](/version-0.x/guide/log-guide/loading-systemlog-events-from-the-database), you can use the provided [StatsEvents](/version-0.x/reference/core-classes/statsevents) class to retrieve and work with lists of [StatsEvent](/version-0.x/reference/core-classes/statsevent) objects.

For example, let's load the last fifty `StatsEventHomeView` objects from our [earlier example](/version-0.x/guide/stats-guide), using what we learned in the [Item lists](/version-0.x/guide/items-guide/item-lists) section of the [Items guide](/version-0.x/guide/items-guide):

```php
$statsEventItems = new \Cherrycake\Stats\StatsEvents([
    "p" => [
        "type" => "CherrycakeApp\StatsEventHomeView",
        "limit" => 50
    ]
]);

foreach ($statsEventItems as $statsEvent) {
    echo
        $e->Locale->formatTimestamp($statsEvent->timestamp).
        ": ".$statsEvent->typeDescription.
        ": ".$statsEvent->count.
				"\n";
}
```

As you can see, the [StatsEvents](/version-0.x/reference/core-classes/statsevents/statsevents-methods#fillfromparameters) class accepts some additional keys on top of the usual [Items::fillFromParameters](/version-0.x/reference/core-classes/items/items-methods#fillfromparameters) keys:

* **`type`** Retrieves only [StatsEvent](/version-0.x/reference/core-classes/statsevent) objects of this class name. Must include the full namespace route to the class.
* **`fromTimestamp`** Retrieves [StatsEvent](/version-0.x/reference/core-classes/statsevent) objects triggered after this timestamp.
* **`toTimestamp`** Retrieves [StatsEvent](/version-0.x/reference/core-classes/statsevent) objects triggered up to this timestamp.

```
5/21/20: Home view: 90
5/22/20: Home view: 1
```

{% hint style="success" %}
See examples of loading StatsEvent object from the database in the [Triggering a stats event ](https://documentation-examples.cherrycake.io/example/statsGuideTriggeringEvent)and [Events with additional dimensions](https://documentation-examples.cherrycake.io/example/statsGuideAdditionalDimensions) examples.
{% endhint %}


# Janitor guide

The Janitor module allows an app to program tasks to be executed periodically.

In many cases you'll need some sort of mechanism to automatically execute tasks with certain periodicity, at certain times of the day, every few days or every few minutes. The [Janitor](/version-0.x/reference/core-modules/janitor) module is designed to do exactly that.

Some examples of the kind of tasks you might want to automate with [Janitor](/version-0.x/reference/core-modules/janitor) are:

* Maintenance tasks, like optimizing a database periodically.
* Batch processes, like gathering all the invoices at the end of the day to generate daily reports.
* Database purges, like removing old data from a database to avoid cluttering it.
* Cache flushes, like periodically clearing certain cached data.
* Buffer commits, like committing data stored in a shared memory buffer to a database for persistence.

## Setting up the Janitor database table

Janitor uses the `cherrycake_janitor_log` database table to store information about the executed tasks.

> You can create the Janitor table in your database by importing the `janitor.sql` file you'll find in the [Cherrycake skeleton repository](https://github.com/tin-cat/cherrycake-skeleton), under the `install/database` directory.

## Janitor tasks

To set up a task to be executed by the [Janitor](/version-0.x/reference/core-modules/janitor) module, you first create a new class that extends the [JanitorTask](/version-0.x/reference/core-classes/janitortask) core class.

Imagine we wanted to create a task to update the IMDB rating of the movies in the database every day. To do so, we would create the file `src/JanitorTaskMoviesUpdateImdbRating.class.php` like this:

```php
<?php

namespace CherrycakeApp;
    
class JanitorTaskMoviesUpdateImdbRating extends \Cherrycake\Janitor\JanitorTask {
    protected $name = "Movies update IMDB rating";
    protected $description = "Updates the IMDB rating of all the movies in the database";
    
    protected $config = [
    		"executionPeriodicity" => \Cherrycake\Janitor\JANITORTASK_EXECUTION_PERIODICITY_HOURS,
		    "periodicityHours" => ["00:00"]
    ];

    function run($baseTimestamp) {
        global $e;
        $e->loadCoreModule("Database");
        
        $movies = new Movies(["fillMethod" => "fromParameters"]);
        foreach ($movies as $movie)
            $movie->updateImdbRating();
        
        return [
    			\Cherrycake\Janitor\JANITORTASK_EXECUTION_RETURN_OK,
		    	$movies->count()." movies updated"
        ];
    }
}
```

In the config property, we set the `executionPeriodicity` key to [`JANITORTASK_EXECUTION_PERIODICITY_HOURS`](/version-0.x/reference/core-modules/janitor#constants), and the `periodicityHours` to `["00:00"]`. This will cause this task to run once at each one of the times specified in the `periodicityHours` array. In this case, at midnight precisely.

With [`JANITORTASK_EXECUTION_PERIODICITY_HOURS`](/version-0.x/reference/core-modules/janitor#constants), you can specify more times for tasks to be executed more than once a day. For example, if you set `periodicityHours` to `["00:00", "12:00"]`, the task will be executed every day at midnight and at noon.

There are also other execution periodicities you can use:

* **`JANITORTASK_EXECUTION_PERIODICITY_EACH_SECONDS`** The task will be executed every specified seconds. Seconds are specified in `periodicityEachSeconds` config key.
* **`JANITORTASK_EXECUTION_PERIODICITY_MINUTES`** The task will be executed on the given minutes of each hour. Desired minutes are specified as an array in the `periodicityMinutes` config key. For example: `[0, 15, 30, 45]`
* **`JANITORTASK_EXECUTION_PERIODICITY_HOURS`** The task will be executed on the given hours of each day. Desired hours/minute are specified as an array in the `periodicityHours` config key in the syntax `["hour:minute", ...]` For example: `["00:00", "10:45", "20:15"]`
* **`JANITORTASK_EXECUTION_PERIODICITY_DAYSOFMONTH`** The task will be executed on the given days of each month. Desired days/hour/minute are specified as an array in the `periodicityDaysOfMonth` config key in the syntax `["day@hour:minute", ...]` For example: `["1@12:00", "15@18:30", "20@00:00"]`
* **`JANITORTASK_EXECUTION_PERIODICITY_ALWAYS`** The task will be executed every time Janitor run is called.
* **`JANITORTASK_EXECUTION_PERIODICITY_ONLY_MANUAL`** The task can only be executed when calling the Janitor run process with an specific task parameter.

In our task class, the `run` method is the one that will be executed when the task is due, so it's where you should put your task code. Like in our example, if you need to work with core or app modules there, use [Engine::loadCoreModule](/version-0.x/reference/core-classes/engine/methods#loadcoremodule) or [Engine::loadAppModule](/version-0.x/reference/core-classes/engine/methods#loadappmodule).

Just like you see on the example above, the `run` method must return an array containing at least one element, being one of the available [`JANITORTASK_EXECUTION_RETURN_?`](/version-0.x/reference/core-modules/janitor#constants) constants. You can add a second element containing a description of the task execution result.

## Adding Janitor tasks to be executed

The last step to having your Janitor tasks automatically executed, is creating the `config/Janitor.config.php` file and adding them to the [`appJanitorTasks`](/version-0.x/reference/core-modules/janitor#configuration) configuration key.

In our example, the `config/Janitor.config.php` would look like this:

```php
<?php

namespace Cherrycake;

$JanitorConfig = [
	"appJanitorTasks" => [
		"JanitorTaskMoviesUpdateImdbRating"
	]
];
```

## Cherrycake core Janitor tasks

Cherrycake itself sets up by default the following core Janitor tasks:

* **`JanitorTaskJanitorPurge`** Performs maintenance tasks related to the [Janitor](/version-0.x/reference/core-modules/janitor) module itself, like purging old log items from the database.
* **`JanitorTaskSystemLogPurge`** Performs maintenance tasks related to the [SystemLog](/version-0.x/reference/core-modules/systemlog) module, like purging old log items from the database.
* **`JanitorTaskSystemLogCommit`** Commits the [SystemLog](/version-0.x/reference/core-modules/systemlog) events stored in the cache shared memory to the database for persistence and for optimal performance.
* **`JanitorTaskSessionPurge`** Performs maintenance tasks related to the [Session](/version-0.x/reference/core-modules/session) module, like purging old sessions.
* **`JanitorTaskStatsCommit`** Commits the [Stats](/version-0.x/reference/core-modules/stats) events stored in the cache shared memory to the database for persistence and for optimal performance.
* **`JanitorTaskLogCommit`** Commits the [Log](/version-0.x/reference/core-modules/log) events stored in the cache shared memory to the database for persistence and for optimal performance.

## Setting up the Janitor cron job

To let [Janitor](/version-0.x/reference/core-modules/janitor) do its job, the [CLI action](/version-0.x/guide/cli#cli-actions) named `janitorRun` must be executed every minute automatically by the operating system in the server. This is usually done by setting up a cron job in Linux that does it by using the Cherrycake [Command line interface](/version-0.x/guide/cli).

In Linux, you would set up the Janitor cron job by editing your crontab with the command:

```bash
crontab -e
```

And adding a line like this:

```
* * * * * /var/www/app/cherrycake janitorRun
```

If you've not used the [Cherrycake Skeleton](/version-0.x/guide/getting-started/skeleton) to build your project, take a look at the [Command line interface](/version-0.x/guide/cli) section to learn how to call CLI actions from the Linux command line.

> When using the [Cherrycake Docker project](/version-0.x/guide/getting-started/docker) to run your Cherrycake app, this cron job is already set up and running.

## Checking the status of the Janitor

The Janitor logs all its activity on the `cherrycake_janitor_log`, so you can check there to see what's happening in real time.

You can also execute the `janitorStatus` [CLI command](/version-0.x/guide/cli), which will show you the current status of all the tasks in your app, plus information about the last time they were executed. It looks like this:

```
Task: Janitor purge
Description: Purges old Janitor log items
Result: Ok
Periodicity: Every 86400 seconds
Last execution: 26/5/2020 15:10:59 (Etc/UTC) took 0 ms.
. Log entries older than 31536000 seconds purged: 0

Task: Log commit
Description: Stores cache-queded events into database and purges the queue cache
Result: Ok
Periodicity: Every 60 seconds
Last execution: 26/5/2020 15:12:01 (Etc/UTC) took 0 ms.
. 
Task: Session purge
Description: Purges discarded sessions from the Session module
Result: Ok
Periodicity: Every 86400 seconds
Last execution: 26/5/2020 15:10:59 (Etc/UTC) took 2 ms.
. Sessions older than 86400 seconds without data purged: 0
. Sessions older than 31536000 seconds with data purged: 0

Task: Stats commit
Description: Stores cache-queded stats events into database and purges the queue cache
Result: Ok
Periodicity: Every 60 seconds
Last execution: 26/5/2020 15:12:01 (Etc/UTC) took 1 ms.
. numberOfFlushedItems: 0

Task: System log commit
Description: Stores cache-queded system log events into database and purges the queue cache
Result: Ok
Periodicity: Every 120 seconds
Last execution: 26/5/2020 15:10:59 (Etc/UTC) took 1 ms.
. numberOfFlushedItems: 0

Task: System log purge
Description: Purges old System log items
Result: Ok
Periodicity: Every 240 seconds
Last execution: 26/5/2020 15:10:59 (Etc/UTC) took 1 ms.
. Log entries older than  seconds purged: 0

Task: Movies update IMDB rating
Description: Updates the IMDB rating of all the movies in the database
Result: Ok
Periodicity: Daily at hours 00:00
Last execution: 26/5/2020 15:10:59 (Etc/UTC) took 13 ms.
. 30 movies updated
```


# Janitor tasks configuration files

You can optionally create Janitor tasks that hold some configuration in a separate configuration file, almost like [modules do](/version-0.x/guide/modules-guide#modules-configuration-file).

To do so, set the `isConfigFile` property of your [JanitorTask](/version-0.x/reference/core-classes/janitortask) class like this:

```php
<?php

namespace CherrycakeApp;
    
class JanitorTaskMoviesUpdateImdbRating extends \Cherrycake\Janitor\JanitorTask {
    protected $isConfigFile = true;
    ...
}
```

Janitor task configuration files must be stored in the `config` directory of your app, and must have a name that matches the task name, even with upper and lowercase characters. For example, the configuration file for our `JanitorTaskMoviesUpdateImdbRating` task must be called `/config/JanitorTaskMoviesUpdateImdbRating.config.php`

Janitor task configuration files must declare a hash array named in the syntax `$<JanitorTaskName>Config`. For example, this the configuration file for our `JanitorTaskMoviesUpdateImdbRating` task:

```php
<?php

namespace Cherrycake;

$JanitorTaskMoviesUpdateImdbRatingConfig = [
    "imdbAPIKey" => "mfu9873n94hosdaonfo3289"
];
```

The values you set in the [JanitorTask::config](/version-0.x/reference/core-classes/janitortask/janitortask-properties#config) property of your task class will be used if no configuration file is used, or if the configuration key has not been set in the configuration file.

To get a configuration value from a [JanitorTask](/version-0.x/reference/core-classes/janitortask), use the [JanitorTask::getConfig](/version-0.x/reference/core-classes/janitortask/janitortask-methods#getconfig) method, for example:

```php
$this->getConfig("imdbAPIKey");
```


# Command line interface

Cherrycake apps can run as command line applications that are invoked from an operating system prompt like the Linux shell.

To let your app attend requests from the command line, you set up an [Action](/version-0.x/reference/core-classes/action) just like any other, except this time you use the [ActionCli](/version-0.x/reference/core-classes/action#subclasses) class when mapping it, like this:

```php
$e->Actions->mapAction(
    "helloWorldCli",
    new \Cherrycake\Actions\ActionCli([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "HelloWorld",
        "methodName" => "sayHi"
    ])
);
```

And in your method, you use the [ResponseCli](/version-0.x/reference/core-classes/response#subclasses) class instead of the usual [ResponseTextHtml](/version-0.x/reference/core-classes/response#subclasses) or [ResponseTextPlain](/version-0.x/reference/core-classes/response#subclasses):

```php
function sayHi() {
    global $e;
    $e->Output->setResponse(new \Cherrycake\Actions\ResponseCli([
        "payload" => "Hello World from the Cli interface"
    ]));
}
```

## Executing CLI Actions

If you remember how we created the `index.php` file in the [Getting started](/version-0.x/guide/getting-started#creating-the-index-php) guide, you'll remember that the method we called to make Cherrycake starting working on the received request actions was [Engine:attendWebRequest](/version-0.x/reference/core-classes/engine/methods#attendwebrequest). When creating an app that works in the command line, the method to use is [Engine:attendCliRequest](/version-0.x/reference/core-classes/engine/methods#attendclirequest) instead, like this:

```php
<?php

namespace CherrycakeApp;

require "vendor/autoload.php";

$e = new \Cherrycake\Engine;

if ($e->init(__NAMESPACE__, [
    "isDevel" => true
]))
    $e->attendCliRequest();

$e->end();
```

## Apps that both attend web requests and CLI actions

Sometimes you'll want your app to attend web requests like a normal web application, but also attend some CLI actions that you'll use to perform maintenance work, run batch processes or similar tasks that are triggered by an admin from the command line, and not by a client using a browser.

A common solution is to create a `cli.php` file additionally to the `index.php` file. This cli.php will look more or less equal to your existing `index.php`, but it will call the [Engine:attendCliRequest](/version-0.x/reference/core-classes/engine/methods#attendclirequest) instead of [Engine:attendWebRequest](/version-0.x/reference/core-classes/engine/methods#attendwebrequest) method.

The [Cherrycake Skeleton repository](https://github.com/tin-cat/cherrycake-skeleton) provides a `cli.php` file where you'll see this solution at work.

## Running an app from the command line

To run a Cherrycake app from the command line in Linux, you use the [PHP cli](https://www.php.net/manual/en/features.commandline.introduction.php) executable to run the `cli.php` file (or whatever name you choose for your main `.php` file), and pass the [Action](/version-0.x/reference/core-classes/action) name as the first parameter.

Following our example above, to run `helloWorldCli` [Action](/version-0.x/reference/core-classes/action), we would call Cherrycake from the Linux command line like this:

```bash
php -f ./cli.php helloWorldCli
```

```
Hello World from the Cli interface
```

## Passing parameters to CLI actions

Just like regular Actions can receive GET and POST parameters, CLI actions can receive command line parameters. To map an [ActionCli](/version-0.x/reference/core-classes/action#subclasses) that receives parameters, you pass the `parameters` array when creating the [Request](/version-0.x/reference/core-classes/request) object just like you already did in the [Accept GET or POST parameters](/version-0.x/guide/actions-guide/accept-get-or-post-parameters) of the [Actions Guide](/version-0.x/guide/actions-guide), except this time you use the [`REQUEST_PARAMETER_TYPE_CLI`](/version-0.x/reference/core-classes/requestparameter#constants) parameter type instead of `REQUEST_PARAMETER_TYPE_GET` or `REQUEST_PARAMETER_TYPE_POST`, like this:

```php
$e->Actions->mapAction(
    "userFlushCache",
    new \Cherrycake\Actions\ActionCli([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "Users",
        "methodName" => "flushUserCacheCli",
        "parameters" => [
            new \Cherrycake\Actions\RequestParameter([
                "type" => \Cherrycake\REQUEST_PARAMETER_TYPE_CLI,
                "name" => "userId",
                "securityRules" => [
                    \Cherrycake\SECURITY_RULE_TYPICAL_ID
                ]
            ])
        ]
    ])
);
```

And you receive the parameters just like you do with GET or POST:

```php
function flushUserCacheCli($request) {
    global $e;
    $user = new User([
        "loadMethod" => "fromId",
        "id" => $request->id
    ]);
    $user->clearCache();
    $e->Output->setResponse(new \Cherrycake\Actions\ResponseCli([
        "payload" => "Cache for user ".$request->userId." flushed"
    ]));
}
```

Now, to call a CLI action that accepts parameters from the command line, you use the regular UNIX parameters syntax after the action name, like this:

```bash
php -f ./cli.php userFlushCache --userId=832
```

```
Cache for user 832 flushed
```


# Debugging

[Engine::getStatus](/version-0.x/reference/core-classes/engine#getstatus) and [Engine:getStatusHumanReadable](/version-0.x/reference/core-classes/engine#getstatushumanreadable) will give you a hash array with detailed information on Cherrycake, the loaded modules, the mapped actions and some benchmarks.

> Note that the status information will be incomplete if the [`isDevel`](/version-0.x/reference/core-classes/engine#init-appnamespace-setup) engine option is not set to true.

For a convenient way of getting the status of the engine, just use the [Engine:getStatusHtml](/version-0.x/reference/core-classes/engine#getstatushtml) method at the desired point in your code, like this:

```php
echo $e->getStatusHtml();
```

This will give show you a status report like this:

```javascript
{
    "appNamespace": "CherrycakeApp",
    "appName": "CherrycakeApp",
    "isDevel": true,
    "isUnderMaintenance": false,
    "documentRoot": "/var/www/app/public",
    "appModulesDir": "/var/www/app/modules",
    "appClassesDir": "/var/www/app/classes",
    "timezoneName": "Etc/UTC",
    "timezoneId": "532",
    "executionStartHrTime": 40610742477736,
    "runningHrTime": "2.5756ms",
    "memoryUse": 537832,
    "memoryUsePeak": 570840,
    "memoryAllocated": 2097152,
    "memoryAllocatedPeak": 2097152,
    "hostname": "22134d6f3030",
    "host": "localhost",
    "ip": "192.168.32.1",
    "os": "Linux",
    "phpVersion": "7.4.2",
    "serverSoftware": "nginx/1.17.8",
    "serverGatewayInterface": "CGI/1.1",
    "serverApi": "fpm-fcgi",
    "loadedModules": [
        "Actions",
        "Output",
        "Errors",
        "Security",
        "Cache",
        "HelloWorld"
    ],
    "moduleLoadingHistory": [
        "Cherrycake/Actions / Base module / loaded at 0.1108ms / init took 2.2079ms",
        "Cherrycake/Output / Required by Actions / loaded at 0.1976ms / init took 0.0444ms",
        "Cherrycake/Errors / Required by Actions / loaded at 0.3398ms / init took 0.0468ms",
        "Cherrycake/Security / Required by Actions / loaded at 0.4855ms / init took 0.2553ms",
        "Cherrycake/Cache / Required by Security / loaded at 0.6055ms / init took 0.0985ms",
        "CherrycakeApp/HelloWorld / Base module / loaded at 2.4278ms / init took 0.0049ms"
    ],
    "actions": {
        "mappedActions": {
            "css": "Css::dump css (set=none version=none)",
            "janitorRun": "Janitor::run janitor/run (key=none task=none isForceRun=none)",
            "janitorStatus": "Janitor::status janitor/status (key=none)",
            "TableAdminGetRows": "TableAdmin::getRows TableAdmin/[String]/getRows (additionalFillFromParameters=none)",
            "javascript": "Javascript::dump js (set=none version=none)",
            "home": "HelloWorld::show /"
        }
    }
}
```

A more usual way of using [Engine:getStatusHtml](/version-0.x/reference/core-classes/engine#getstatushtml) is to call it after all execution has been done, and just before the engine is about to end. Here's a way to do it in your `/public/index.php` file:

```php
<?php

namespace CherrycakeApp;

require "vendor/autoload.php";

$e = new \Cherrycake\Engine;

if ($e->init(__NAMESPACE__, [
    "isDevel" => true
]))
    $e->attendWebRequest();

echo $e->getStatusHtml();

$e->end();
```

Here's some interesting information you'll find in the output of [Engine:getStatusHtml](/version-0.x/reference/core-classes/engine#getstatushtml):

* `runningHrTime` The amount of time it took PHP to run the current request, up to the point where you called the getStatus method.
* `moduleLoadingHistory` The list of modules that were loaded when you called the getStatus method, in the order they were loaded, and including this extra information:
  * Whether the module was loaded as a base module, as a dependency of another module or programmatically.
  * The point in time after the execution started where the module was loaded.
  * The amount of time it took the module to load and init, including loading any other module dependencies.
* `mappedActions` The list of mapped actions when you called the getStatus method, including the module::class they call, their route and the parameters they accept.


# Core modules


# Actions

Manages the queries to the engine. It answers to queries by evaluating the query path and parameters and finding a matching mapped Action.

> See the [Actions guide](/version-0.x/guide/actions-guide) to learn how to work with the Actions module.

## Configuration

* **`defaultActionCacheTtl`** The default cache provider name to use. Default: `engine`
* **`defaultActionCacheTtl`** The default TTL. Default: `CACHE_TTL_NORMAL`
* **`defaultActionCachePrefix`** The default cache prefix. Default: `Actions`
* **`sleepSecondsWhenActionSensibleToBruteForceAttacksFails`** An array containing the minimum and maximum number of seconds to wait when an action marked as sensible to brute force attacks has been executed and failed. Default: `[0, 3]`


# Actions methods

## getAction( actionName ) <a href="#getaction" id="getaction"></a>

Returns the action with the given actionName.

* **`actionName`** String

**Returns:** [Action](/version-0.x/reference/core-classes/action) object or false if the action has not been mapped.

## init

Initializes the module, loads the dependent module classes and calls the `mapActions` method on all available modules using [Engine::callMethodOnAllModules](/version-0.x/reference/core-classes/engine#callmethodonallmodules-methodname).

## isAction( actionName ) <a href="#isaction" id="isaction"></a>

Checks if the action with the given actionName has been mapped.

* **`actionName`** String

**Returns:** Boolean

## mapAction( actionName, action ) <a href="#mapaction" id="mapaction"></a>

Maps an action for a module.

* **`actionName`** String
* **`action`** [Action](/version-0.x/reference/core-classes/action) object

```php
$e->Actions->mapAction(
    "home",
    new \Cherrycake\Action([
        "moduleType" => \Cherrycake\ACTION_MODULE_TYPE_APP,
        "moduleName" => "Home",
				"methodName" => "homePage",
				"request" => new \Cherrycake\Request([
            "pathComponents" => false,
            "parameters" => false
        ])
    ]);
);
```

## run

Parses the received query to find the corresponding action and runs it


# Browser

Module that identifies the client's browser identity and capabilities.

This module is strongly based on Browser.php by Chris Schuld (<http://chrisschuld.com/>), 99% of the code by him.


# Cache

Provides a standardized interface to implement caching and shared memory mechanisms into an App by connecting to multiple external cache providers.

> See the [Cache guide](/version-0.x/guide/cache-guide) to learn how to work with the Cache module.

## Configuration

* **`providers`** A hash array of the available [cache providers](/version-0.x/guide/cache-guide#cache-providers), where the key is the name of the cache provider, and the value is a hash array with the following possible keys:
  * **`providerClassName`** The name of the cache provider class, from the available ones:
    * `CacheProviderApc`
    * `CacheProviderApcu`
    * `CacheProviderMemcached`
    * `CacheProviderRedis`
  * **`config`** A hash array of configuration options for the cache provider, where each different cache provider has different available config keys:
    * For `CacheProviderApc`: No configuration needed.
    * For `CacheProviderApcu`: No configuration needed.
    * For `CacheProviderMemcached`:
      * **`isPersistentConnection`**
      * **`isCompression`**
      * **`servers`** An array of the servers to add to the server Memcached pool, as documented in <https://www.php.net/manual/en/memcached.addservers.php>
    * For `CacheProviderRedis`:
      * **`scheme`** The connection scheme. Default: `tcp`
      * **`host`** The host name or IP of the Redis server. Default: `localhost`
      * **`port`** The server port. Default: `6379`
      * **`database`** The Redis database number to use. Default: `0`
      * **`prefix`** The prefix to use for all cache keys. Used to avoid key collisions with other apps that might be running in the server. Defaults to none.
      * **`isPersistentConnection`** Whether to keep the connection to Redis active between requests. Default: `true`

## Constants

* `CACHE_TTL_1_MINUTE`
* `CACHE_TTL_5_MINUTES`
* `CACHE_TTL_10_MINUTES`
* `CACHE_TTL_30_MINUTES`
* `CACHE_TTL_1_HOUR`
* `CACHE_TTL_2_HOURS`
* `CACHE_TTL_6_HOURS`
* `CACHE_TTL_12_HOURS`
* `CACHE_TTL_1_DAY`
* `CACHE_TTL_2_DAYS`
* `CACHE_TTL_3_DAYS`
* `CACHE_TTL_5_DAYS`
* `CACHE_TTL_1_WEEK`
* `CACHE_TTL_2_WEEKS`
* `CACHE_TTL_1_MONTH`
* `CACHE_TTL_MINIMAL` 10 seconds
* `CACHE_TTL_CRITICAL` 1 minute
* `CACHE_TTL_SHORT` 5 minutes
* `CACHE_TTL_NORMAL` 1 hour
* `CACHE_TTL_UNCRITICAL` 1 day
* `CACHE_TTL_LONG` 1 week
* `CACHE_TTL_LONGEST` 1 month


# Cache methods

## buildCacheKey( cacheKeyNamingOptions ) <a href="#buildcachekey" id="buildcachekey"></a>

Returns a cache key to uniquely identify a cached object, to be used in caching operations.

* **`cacheKeyNamingOptions`** A hash array of options to build the cache key, with the following possible keys:
  * **`prefix`** A prefix that will added to the beginning of the cache key. Used to prevent collisions.
  * **`uniqueId`** A specifically provided unique identification for the cached object. Used when you want to manually give a unique identifier to a cached object. This overrides any specified `specificPrefix`, `hash` or `key`.
  * **`specificPrefix`** A secondary prefix to further prevent collisions when using `hash` or `key`.
  * **`hash`** A string to be hashed as the cache key instead of using "key". For example: An SQL query.
  * **`key`** An arbitrary key to uniquely identify the cache key.

**Returns:** The cache key in the form of a string.


# Css

Provides a way to work with CSS stylesheets in a web application, with additional features and performance improvements.

> See the [Css and Javascript guide](/version-0.x/guide/css-and-javascript-guide) to learn how to work with the Css module.

## Configuration

* **`cacheProviderName`** The name of the cache provider to use. Default: `engine`
* \*\*`cacheTtl`\*\*The TTL to use for the cache. Default `CACHE_TTL_LONGEST`
* **`isHttpCache`** Whether to send HTTP Cache headers or not. Default: `false`
* **`httpCacheMaxAge`** The TTL of the HTTP Cache. Default: `CACHE_TTL_LONGEST`
* **`lastModifiedTimestamp`** The timestamp of the last modification to the CSS files, or any other string that will serve as a unique identifier to force browser cache reloading when needed. Default: `false`
* **`defaultSetOrder`** The default order to assign to sets when no order is specified. Default: `100`
* **`isMinify`** Whether to minify the CSS code or not
* **`responsiveWidthBreakpoints`** A hash array of the thresholds that will be used for responsive media queries, where each key is the breakpoint name, and each value the number of pixels. Default:
  * `tiny` `500`
  * `small` `700`
  * `normal` `980`
  * `big` `1300`
  * `huge` `1700`
* **`sets`** A hash array specifying the different Css sets this app has, where each key is the set name, and each value is a hash array with the following possible keys:
  * **`order`** The numeric order of this set in relation to other sets. Used to control CSS overloading.
  * **`directory`** The directory containing the CSS files.
  * **`isIncludeAllFilesInDirectory`** Whether to automatically add all the `*.css` files found in the specified `directory` to this set or not.
  * **`variablesFile`** A PHP file that will be included before any CSS pattern parsing. It can be used to store styling variables.
  * **`isGenerateTextColorsCssHelpers`** Using the `$textColors` variable defined in the specified `variablesFile` , automatically generates CSS classes in the syntax `.textColor_[color name]` that assign the corresponding CSS text-color property. The `$textColors` variable must be a hash array where the key is the color name, and the value is a [Color](/version-0.x/reference/core-classes/color) object.
  * **`isGenerateBackgroundColorsCssHelpers`** Using the `$backgroundColors` variable defined in the specified `variablesFile` , automatically generates CSS classes in the syntax `.backgroundColor_[color name]` that assign the corresponding CSS background-color property. The `$backgroundColors` variable must be a hash array where the key is the color name, and the value is a [Color](/version-0.x/reference/core-classes/color) object.
  * **`isGenerateBackgroundGradientsCssHelpers`** Using the `$gradients` variable defined in the specified `variablesFile` , automatically generates CSS classes in the syntax `.backgroundGradient_[color name]` that assign the corresponding CSS for a background gradient. The `$gradients` variable must be a hash array where the key is the color name, and the value is a [Gradient](/version-0.x/reference/core-classes/gradient) object.


# Css methods

## addFileToSet( setName, fileName ) <a href="#addfiletoset" id="addfiletoset"></a>

Adds a file to a Css set.

* **`setName`** The name of the set
* **`fileName`The file name, relative to the set's configured directory.**

## getSetUrl( setNames ) <a href="#getseturl" id="getseturl"></a>

Builds a URL to request the given set contents.

* **`setNames`** Optional name of the Css set, or an array of them. If set to `false`, all available sets are used. Default: `false`

**Returns:** The URL of the requested Css sets.


# Database

Provides a standardized interface to connect to database servers like MySQL and MariaDB.

> See the [Database guide](/version-0.x/guide/database-guide) to learn how to work with the Database module.

## Configuration

* **`providers`** A hash array of the available [database providers](/version-0.x/guide/database-guide#database-providers), where the key is the name of the database provider, and the value is a hash array with the following possible keys:
  * **`providerClassName`** The name of the cache provider class, from the available ones:
    * `DatabaseProviderMysql` To connect to MySQL or MariaDB database servers.
  * **`config`** A hash array of configuration options for the database provider, where each different cache provider has different available config keys:
    * For `DatabaseProviderMysql`:
      * **`host`** The host name or IP of the server.
      * **`user`** The user name
      * **`password`** The password
      * **`database`** The name of the database
      * **`charset`** The character set to use. One of the available here: <https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html>.
      * **`cacheKeyPrefix`** The cache prefix to use when caching data from the database. Default: `Database`
      * **`cacheDefaultTtl`** The default [TTL](/version-0.x/guide/cache-guide#time-to-live) to use when caching data from the database. Default: `CACHE_TTL_NORMAL`
      * **`cacheProviderName`** The default cache provider name to use when caching data from the database. Default: `engine`

## Constants

* **`DATABASE_FIELD_TYPE_INTEGER`**
* **`DATABASE_FIELD_TYPE_TINYINT`**
* **`DATABASE_FIELD_TYPE_FLOAT`**
* **`DATABASE_FIELD_TYPE_DATE`**
* **`DATABASE_FIELD_TYPE_DATETIME`**
* **`DATABASE_FIELD_TYPE_TIMESTAMP`**
* **`DATABASE_FIELD_TYPE_TIME`**
* **`DATABASE_FIELD_TYPE_YEAR`**
* **`DATABASE_FIELD_TYPE_STRING`**
* **`DATABASE_FIELD_TYPE_TEXT`**
* **`DATABASE_FIELD_TYPE_BLOB`**
* **`DATABASE_FIELD_TYPE_BOOLEAN`**
* **`DATABASE_FIELD_TYPE_IP`**
* **`DATABASE_FIELD_TYPE_SERIALIZED`**
* **`DATABASE_FIELD_TYPE_COLOR`**
* **`DATABASE_FIELD_DEFAULT_VALUE`**
* **`DATABASE_FIELD_DEFAULT_VALUE_DATE`**
* **`DATABASE_FIELD_DEFAULT_VALUE_DATETIME`**
* **`DATABASE_FIELD_DEFAULT_VALUE_TIMESTAMP`**
* **`DATABASE_FIELD_DEFAULT_VALUE_TIME`**
* **`DATABASE_FIELD_DEFAULT_VALUE_YEAR`**
* **`DATABASE_FIELD_DEFAULT_VALUE_IP`**
* **`DATABASE_FIELD_DEFAULT_VALUE_AVAILABLE_URL_SHORT_CODE`**


# Email

Module to send email.

Uses [PHPMailer](https://github.com/PHPMailer/PHPMailer).


# Errors

Module to manage application and core errors.


# HtmlDocument

Helps you create standard HTML headers and footers.

> See the [HtmlDocument guide](/version-0.x/guide/htmldocument-guide) to learn how to work with the HtmlDocument module.

## Configuration

* **`title`** The page title
* **`description`** The page description
* \*\*`copyright`\*\*The page copyright info
* **`keywords`** An array of the page keywords
* **`languageCode`** The language code of the page, from the ISO 639-1 standard (<https://www.w3schools.com/tags/ref_language_codes.asp>). Default: `en`
* **`charset`** The page character set. Default: `utf-8`
* **`isAllowRobotsIndex`** Whether to allow robots to index the document. Default: `true`
* \*\*`isAllowRobotsFollow`\*\*Whether to allow robots to follow links on the document. Default: `true`
* **`isDeferJavascript`** Whether to defer loading of JavaScript or not. Default: `false`
* **`googleAnalyticsTrackingId`** The Google Analytics id, if any.
* **`matomoTrackingId`** The Matomo (Piwik) tracking id, if any.
* **`matomoServerUrl`** The Matomo (Piwik) server URL, if any.
* **`mobileViewport`** Configuration for the site when viewed in a mobile device, via the `viewport` meta
  * `width` The width of the viewport: A number of pixels or `device-width`. Default: `device-width`
  * `userScalable` Whether or not to let the user pinch to zoom in/out. Default: `true`
  * `initialScale` Optional, the initial scale
  * `maximumScale` Optional, the maximum scale
* **`microsoftApplicationInfo`** Application info for Microsoft standards (i.e: When adding the web as a shortcut in Windows >8)
  * `name` The name of the app
  * `tileColor` The color of the tile on Windows >8, in HTML hexadecimal format (i.e: `#dd2153`)
  * `tileImage` URL of an image to use as a tile image for Windows >8. Must be in png format.
* **`appleApplicationInfo`** Application info for Apple standards (i.e: When adding the web as a shortcut in iOs devices, or to hint the users about the App store APP for this site)
  * `name` The name of the app
  * `iTunesAppId`
  * `icons` A hash array of icon sizes where the key is in the \[width]x\[height] syntax and the value is the icon URL in png format. The standard keys to use here are:`57x57` ,`114x114` ,`72x72` ,`144x144` ,`60x60` ,`120x120` ,`76x76` and `152x152`. Default: `false`
* **`iTunesAppId`** The id of a corresponding App in the Apple store. Default: `false`
* **`favIcons`** A hash array of icon sizes where the key is in the \[width]x\[height] syntax and the value is the icon URL in png format. The standard keys to use here are:`196x196`, `160x160`, `96x96`, `16x16` and `32x32`. Default: `false`
* **`cssSets`** An array of the Css set names to link in the HTML document in a single request, or, to add different Css requests instead of one, an array where each item represents a single request, and is an array of Css set names that will be included in each single request. If set to `false`, all available sets will be linked in a single request. Default: `false`
* **`javascriptSets`** An array of the Javascript set names to link in the HTML document in a single request, or, to add different Javascript requests instead of one, an array where each item represents a single request, and is an array of Javascript set names that will be included in each single request. If set to `false`, all available sets will be linked in a single request. Default: `false`
* \*\*`googleFonts`\*\*An array of the Google fonts to include, where each item is a hash array containing the following keys:
  * `family` The font family (i.e: `Duru Sans`)
  * `weight` The font weight (i.e: `300`)
  * `subset` The subset (i.e: `latin`)


# HtmlDocument methods

## footer

Builds a standard HTML footer, from the \</body> to the \</html> tags. Works with the Javascript module to implement deferred JavaScript capabilities.

**Returns:** The HTML footer

## header( setup ) <a href="#header" id="header"></a>

Builds a standard HTML header, from the `<html ... >` to the `<body ...>` tags. It works with the [Css](/version-0.x/reference/core-modules/css) and [Javascript](/version-0.x/reference/core-modules/javascript) modules to include the proper CSS/JavaScript calls.

* **`setup`** An optional hash array of the following optional setup keys:
  * **`bodyAdditionalCssClasses`** Additional CSS classes for the body element. Default: `false`

**Returns:** The HTML header


# ItemAdmin

A module to admin Items.

It allows the creation of HTML forms in conjunction with the UiComponentItemAdmin, and also simplifies the process of receiving data for an Item via a request, validating the values and storing them.

## Constants

* `FORM_ITEM_TYPE_NUMERIC`
* `FORM_ITEM_TYPE_STRING`
* `FORM_ITEM_TYPE_TEXT`
* `FORM_ITEM_TYPE_BOOLEAN`
* `FORM_ITEM_TYPE_RADIOS`
* `FORM_ITEM_TYPE_SELECT`
* `FORM_ITEM_TYPE_DATABASE_QUERY`
* `FORM_ITEM_TYPE_COUNTRY`
* `FORM_ITEM_META_TYPE_MULTILEVEL_SELECT`
* `FORM_ITEM_META_TYPE_LOCATION`


# Janitor

Allows an app to program tasks to be executed periodically.

> See the [Janitor guide](/version-0.x/guide/janitor-guide) to learn how to work with the Janitor module.

## Constants

* **`JANITORTASK_EXECUTION_RETURN_WARNING`** Return code for [JanitorTask](/version-0.x/reference/core-classes/janitortask) run when task returned a warning.
* **`JANITORTASK_EXECUTION_RETURN_ERROR`** Return code for [JanitorTask](/version-0.x/reference/core-classes/janitortask) run when task returned an error.
* **`JANITORTASK_EXECUTION_RETURN_CRITICAL`** Return code for [JanitorTask](/version-0.x/reference/core-classes/janitortask) run when task returned a critical error.
* **`JANITORTASK_EXECUTION_RETURN_OK`** Return code for [JanitorTask](/version-0.x/reference/core-classes/janitortask) run when task was executed without errors.
* **`JANITORTASK_EXECUTION_PERIODICITY_ONLY_MANUAL`** The task can only be executed when calling the Janitor run process with an specific task parameter. It won't be executed on regular "all-tasks" calls to Janitor.
* **`JANITORTASK_EXECUTION_PERIODICITY_ALWAYS`** The task must be executed every time Janitor run is called.
* **`JANITORTASK_EXECUTION_PERIODICITY_EACH_SECONDS`** The task must be executed every specified seconds. Seconds specified in `periodicityEachSeconds` config key.
* **`JANITORTASK_EXECUTION_PERIODICITY_MINUTES`** The task must be executed on the given minutes of each hour. Desired minutes are specified as an array in the `periodicityMinutes` config key with the syntax: `[0, 15, 30, 45]`
* **`JANITORTASK_EXECUTION_PERIODICITY_HOURS`** The task must be executed on the given hours of each day. Desired hours/minute are specified as an array in the `periodicityHours` config key with the syntax: `["hour:minute", "hour:minute", "hour:minute"]`
* **`JANITORTASK_EXECUTION_PERIODICITY_DAYSOFMONTH`** The task must be executed on the given days of each month. Desired days/hour/minute are specified as an array in the `periodicityDaysOfMonth` config key with the syntax: `["day@hour:minute", "day@hour:minute", "day@hour:minute"]` (Take into account days of month that do not exist)

## Configuration

* **`logDatabaseProviderName`** The name of the DatabaseProvider to use for storing Janitor log. Defaults to `main`.
* **`logTableName`** The name of the table used to store Janitor log. Defaults to `cherrycake_janitor_log`
* **`coreJanitorTasks`** An array of names of the Cherrycake core [JanitorTask](/version-0.x/reference/core-classes/janitortask) classes to run. Defaults to an array with the following elements:
  * `JanitorTaskJanitorPurge`
  * `JanitorTaskSystemLogPurge`
  * `JanitorTaskSystemLogCommit`
  * `JanitorTaskSessionPurge`
  * `JanitorTaskStatsCommit`
  * `JanitorTaskLogCommit`
* **`appJanitorTasks`** An array of names of App JanitorTask classes to run.


# Janitor methods

## run( request ) <a href="#run" id="run"></a>

Determines which tasks need to be executed now and executes them. If a task name is passed via [Request](/version-0.x/reference/core-classes/request) in the `task` parameter, only that task will be executed, if due to be executed. If, additionally, the `isForceRun` parameter is passed as `true`, the task name will be executed even if it's not due to be executed.

* **`request`** A [Request](/version-0.x/reference/core-classes/request) object, passed by the [Actions](/version-0.x/reference/core-modules/actions-1) module when calling this method as the result of an action.


# Javascript

Provides a way to work with JavaScript in a web application, with additional features and performance improvements.

> See the [Css and Javascript guide](/version-0.x/guide/css-and-javascript-guide) to learn how to work with the Javascript module.

## Configuration

* **`cacheProviderName`** The name of the cache provider to use. Default: `engine`
* \*\*`cacheTtl`\*\*The TTL to use for the cache. Default `CACHE_TTL_LONGEST`
* **`isHttpCache`** Whether to send HTTP Cache headers or not. Default: `false`
* **`httpCacheMaxAge`** The TTL of the HTTP Cache. Default: `CACHE_TTL_LONGEST`
* **`lastModifiedTimestamp`** The timestamp of the last modification to the CSS files, or any other string that will serve as a unique identifier to force browser cache reloading when needed. Default: `false`
* **`defaultSetOrder`** The default order to assign to sets when no order is specified. Default: `100`
* **`isMinify`** Whether to minify the JavaScript code or not
* **`sets`** A hash array specifying the different JavaScript sets this app has, where each key is the set name, and each value is a hash array with the following possible keys:
  * **`order`** The numeric order of this set in relation to other sets. Used to control JavaScript dependency.
  * **`directory`** The directory containing the JavaScript files.
  * **`isIncludeAllFilesInDirectory`** Whether to automatically add all the `*.js` files found in the specified `directory` to this set or not.
  * **`variablesFile`** A PHP file that will be included before any JavaScript pattern parsing.


# Javascript methods

## addFileToSet( setName, fileName ) <a href="#addfiletoset" id="addfiletoset"></a>

Adds a file to a Css set.

* **`setName`** The name of the set
* **`fileName`The file name, relative to the set's configured directory.**

## getSetUrl( setNames ) <a href="#getseturl" id="getseturl"></a>

Builds a URL to request the given set contents.

* **`setNames`** Optional name of the Javascript set, or an array of them. If set to `false`, all available sets are used. Default: `false`

**Returns:** The URL of the requested Javascript sets.


# Locale

The Locale module provides a mechanism to build apps that adapt to users using different languages, timezones, currencies and other local unit standards.

> See the [Locale guide](/version-0.x/guide/locale-guide) to learn how to work with the Locale module.

## Configuration

* **`availableLocales`** A hash array of available localizations the app supports, where each key is the locale name, and each value a hash array with the keys below. By default, a locale named `main` is defined with the following default values.
  * **`domains`** An array of domains that will trigger this localization when the request to the app comes from one of them, or false if this is the only locale to be used always. Default: `false`
  * **`language`** The language used in this localization, one of the available `LANGUAGE_?` constants. Default: `LANGUAGE_ENGLISH`
  * **`dateFormat`** The date format used in this localization, one of the available `DATE_FORMAT_?` constants. Default: `DATE_FORMAT_MIDDLE_ENDIAN`
  * **`temperatureUnits`** The temperature units used in this localization, one of the available `TEMPERATURE_UNITS_?` constants. Default: `TEMPERATURE_UNITS_FAHRENHEIT`
  * **`currency`** The currency used in this localization, one of the available `CURRENCY_?` constants. Default: `CURRENCY_USD`
  * **`decimalMark`** The type character used when separating decimal digits in this localization, one of the available `DECIMAL_MARK_?` constants. Default: `DECIMAL_MARK_POINT`
  * **`measurementSystem`** The measurement system used in this localization, one of the available `MEASUREMENT_SYSTEM_?` constants. Default: `MEASUREMENT_SYSTEM_IMPERIAL`
  * **`timeZone`** The timezone id used in this localization, from the `cherrycake_location_timezones` table of the [Cherrycake skeleton database](/version-0.x/guide/getting-started#setting-up-the-skeleton-database). Default: `532` (532 is the id for the Etc/UTC time zone)
* **`defaultLocale`** The locale name to use when it can not be auto-detected. Default: `main`
* **`canonicalLocale`** The locale to consider canonical, used i.e. in the [HtmlDocument](/version-0.x/reference/core-modules/htmldocument) module to set the `rel="canonical"` meta tag, in order to let search engines understand that there are different pages in different languages that represent the same content.
* **`availableLanguages`** An array of the languages that are available for the app. The specified`textsTableName` should contain at least the proper `text_<language code>` fields for this languages. From the available `LANGUAGE_`? constants. Default: `[LANGUAGE_ENGLISH]`
* **`geolocationMethod`** The method to use to determine the user's geographical location, one of the available `GEOLOCATION_METHOD_?` constants.
* **`textsTableName`** The name of the table where multilingual localized texts are stored. See the `cherrycake_locale_texts` table in the [Cherrycake skeleton database](/version-0.x/guide/getting-started#setting-up-the-skeleton-database). Default: `cherrycake_locale_texts`
* **`textsDatabaseProviderName`** The name of the database provider where the localized multilingual texts are found. Default: `main`
* **`textCategoriesTableName`** The name of the table where text categories are stored. See the `cherrycake_locale_textCategories` table in the [Cherrycake skeleton database](/version-0.x/guide/getting-started#setting-up-the-skeleton-database). Default: `cherrycake_locale_textCategories`
* **`textCacheProviderName`** The name of the cache provider that will be used to cache localized multilingual texts. Default: `engine`
* **`textCacheKeyPrefix`** The prefix of the keys when storing texts into cache. Default: `LocaleText`
* **`textCacheDefaultTtl`** The default TTL for texts stored into cache. Default: `CACHE_TTL_NORMAL`
* **`timeZonesTableName`** The name of the table where the timezones are stored. See the `cherrycake_location_timezones` table in the [Cherrycake skeleton database](/version-0.x/guide/getting-started#setting-up-the-skeleton-database). Default: `cherrycake_location_timezones`
* **`timeZonesDatabaseProviderName`** The name of the database provider where the timezones are found. Default: `main`
* **`timeZonesCacheProviderName`** The name of the cache provider that will be user to cache timezones. Default: `engine`
* **`timeZonesCacheKeyPrefix`** The prefix of the keys when storing timezones into cache. Default:`LocaleTimeZone`
* **`timeZonesCacheDefaultTtl`** The default TTL for timezones stored into cache. Default: `CACHE_TTL_NORMAL`

## Constants

* **`LANGUAGE_ENGLISH`**
* **`LANGUAGE_SPANISH`**
* **`DATE_FORMAT_LITTLE_ENDIAN`** Almost all the world, like "20/12/2010", "9 November 2003", "Sunday, 9 November 2003", "9 November 2003"
* **`DATE_FORMAT_BIG_ENDIAN`** Asian countries, Hungary and Sweden, like "2010/12/20", "2003 November 9", "2003-Nov-9, Sunday"
* **`DATE_FORMAT_MIDDLE_ENDIAN`** United states and Canada, like "12/20/2010", "Sunday, November 9, 2003", "November 9, 2003", "Nov. 9, 2003", "Nov/9/2003"
* **`TEMPERATURE_UNITS_FAHRENHEIT`**
* **`TEMPERATURE_UNITS_CELSIUS`**
* **`CURRENCY_USD`**
* **`CURRENCY_EURO`**
* **`DECIMAL_MARK_POINT`**
* **`DECIMAL_MARK_COMMA`**
* **`MEASUREMENT_SYSTEM_IMPERIAL`**
* **`MEASUREMENT_SYSTEM_METRIC`**
* **`HOURS_FORMAT_12H`**
* **`HOURS_FORMAT_24H`**
* **`TIMESTAMP_FORMAT_BASIC`** Basic formatting, like `5/18/2020`
* **`TIMESTAMP_FORMAT_HUMAN`** Human readable formatting, like `may 18th, 2020`
* **`TIMESTAMP_FORMAT_RELATIVE_HUMAN`** Formatting relative to now, like `10 hours ago`
* **`ORDINAL_GENDER_MALE`**
* **`ORDINAL_GENDER_FEMALE`**
* **`GEOLOCATION_METHOD_CLOUDFLARE`** Uses [Cloudflare IP geolocation](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation) by reading the `CF-IPCountry` HTTP header added by Cloudflare when this option is enabled.


# Locale methods

## convertTimestamp( timestamp, toTimeZone, fromTimeZone ) <a href="#converttimestamp" id="converttimestamp"></a>

Converts a given timestamp from one timezone to another.

* **`timestamp`** The timestamp to convert. Expected to be in the given `fromTimezone`.
* **`toTimeZone`** The desired timezone, one of the PHP constants as specified in <http://php.net/manual/en/timezones.php>. If none specified, the current [Locale](/version-0.x/reference/core-modules/locale) timezone is used.
* **`fromTimeZone`** The timezone on which the given `timestamp` is considered to be in. If not specified the default cherrycake timezone is used, as set in [Engine::init](/version-0.x/reference/core-classes/engine/methods#init)

**Returns:** The converted timestamp, or `false` if it couldn't be converted.

## formatCurrency( amount, setup ) <a href="#formatcurrency" id="formatcurrency"></a>

Formats the given amount as a currency.

* **`amount`**
* **`setup`** An optional hash array with setup options, with the following possible keys:
  * **`currency`** The currency to format the given amount to. One of the available [`CURRENCY_?`](/version-0.x/reference/core-modules/locale#constants). If not specified, the current [Locale](/version-0.x/reference/core-modules/locale) setting is used.

**Returns:** The formatted amount.

## formatDate( dateTimestamp, setup ) <a href="#formatdate" id="formatdate"></a>

Formats the given date.

* **`dateTimestamp`** The timestamp to use, in UNIX timestamp format. The hours, minutes and seconds are considered irrelevant.
* **`setup`** An optional hash array with setup options, just like the [Locale::formatTimestamp](#formattimestamp) method.

**Returns:** The formatted date.

## formatNumber( number, setup ) <a href="#formatnumber" id="formatnumber"></a>

Formats the given number.

* **`number`**
* **`setup`** An optional hash array with options, with the following possible keys:
  * **`decimals`** The number of decimals to show. Default: `0`
  * **`decimalMark`** The decimal mark to use, either DECIMAL\_MARK\_POINT or DECIMAL\_MARK\_COMMA. Defaults to the current locale setting.
  * **`isSeparateThousands`** Whether to separate thousands or not. Default: `false`
  * **`multiplier`** A multiplier, or false if no multiplier should be applied. Default: `false`

**Returns:** The formatted number.

## formatTimestamp( timestamp, setup ) <a href="#formattimestamp" id="formattimestamp"></a>

Formats the given date/time according to current locale settings.

* **`timestamp`** The timestamp to use, in UNIX timestamp format. Considered to be in the engine's default timezone configured in [Engine::init](/version-0.x/reference/core-classes/engine/methods#init), except if the `fromTimeZone` is given via `setup`.
* **`setup`** A hash array of setup options with the following possible keys:
  * **`fromTimezone`** Considers the given timestamp to be in this timezone. If not specified, the timestamp is considered to be in the current [Locale](/version-0.x/reference/core-modules/locale) timestamp. Default: `false`.
  * **`toTimezone`** Converts the given timestamp to this timezone. If not specified, the given timestamp is converted to the current [Locale](/version-0.x/reference/core-modules/locale) timestamp except if the `fromTimeZone` setup key has been set to `false`. Default: `false`.
  * **`language`** If specified, this language will be used instead of the detected one. One of the available [`LANGUAGE_?`](/version-0.x/reference/core-modules/locale#constants).
  * **`style`** The formatting style, one of the available [`TIMESTAMP_FORMAT_?`](/version-0.x/reference/core-modules/locale#constants) constants.
  * **`isShortYear`** Whether to abbreviate the year whenever possible. For example: `17` instead of `2017.` Default: `true`
  * **`isDay`** Whether to include the day. Default: `true`
  * **`isHours`** Whether to include hours and minutes. Default: `false`
  * **`hoursFormat`** The format of the hours. One of the available [`HOURS_FORMAT_?`](/version-0.x/reference/core-modules/locale#constants). Default: `HOURS_FORMAT_24`
  * **`isSeconds`** Whether to include seconds. Default: `false`
  * **`isAvoidYearIfCurrent`** Whether to avoid the year if it's the current one. Default: `false`
  * **`isBrief`** Whether to use a brief formatting whenever possible. Default: false.
  * **`format`** If specified this format as used in the date PHP function is used instead of internal formatting. Default: `false`

**Returns:** The formatted timestamp.

## getLanguageCode( language ) <a href="#getlanguagecode" id="getlanguagecode"></a>

Gets the code of a language.

* **`language`** The language, one of the available [`LANGUAGE_?`](/version-0.x/reference/core-modules/locale#constants) constants.

**Returns:** The language code, or `false` if the specified language is not configured.

## getLanguageName( language, setup ) <a href="#getlanguagename" id="getlanguagename"></a>

Gets the name of a language.

* **`language`** The language, one of the available [`LANGUAGE_?`](/version-0.x/reference/core-modules/locale#constants) constants.
* **`setup`** An optional hash array of setup options, with the following possible keys:
  * **`forceLanguage`** Use this language instead of the passed in `language`

**Returns:** The language name, `false` if the specified language is not configured.

## getMainDomain( localeName )

Gets the main domain name for the current locale, or for the specified locale

* **`localeName`** The name of the locale for which to get the main domain

**Returns:** The main domain for the specified locale, or for the current locale if no `locale` specified. `false` if the locale was not found.

## getText( code, setup ) <a href="#gettext" id="gettext"></a>

Gets a text from the multilingual texts database.

* **`code`** The code of the text. Can also be specified in the `<category code>/<text code>` syntax to differentiate texts stored with the same code in different categories.
* **`setup`** An optional hash array of setup options, with the following possible keys:
  * **`variables`** A hash array of the variables that must be replaced taking the text as a pattern. Every occurrence of `{<key>}` will be replaced with the matching value, where the value can be a string, or a hash array of values for different languages, where each key is one of the available [`LANGUAGE_?`](/version-0.x/reference/core-modules/locale#constants) constants.
  * **`forceLanguage`** Force the retrieval of the text on this language. If not specified, the detected language is used.
  * **`forceTextCacheTtl`** Use this TTL for the text cache instead of the module configuration variable `textCacheDefaultTtl`.
  * **`isPurifyVariables`** Whether to purify values from specified variables for security purposes or not. Defaults to `true`.

**Returns:** The text.

## setLocale( localeName )

Sets the locale to use

* **`localeName`** The name of the locale to use, as specified in the [`availableLocales`](/version-0.x/reference/core-modules/locale#configuration) config key.

**Returns:** `true` if the locale could be set, `false` if the locale wasn't configured in the [`availableLocales`](/version-0.x/reference/core-modules/locale#configuration) config key.


# Log

The Log module stores app-related events in a persistent log as they occur, aimed at providing a log of meaningful events that happened in the app.

> See the [Log guide](/version-0.x/guide/log-guide) to learn how to work with the Log module.

## Configuration

* **`databaseProviderName`** The name of the database provider where the `log` table is found. Default: `main`.
* **`cacheProviderName`** The name of the cache provider that will be used to temporally store events as they happen, to be later added to the database by the `JanitorTaskLog`. Default: `engine`.
* **`cacheKeyUniqueId`** The unique cache key to use when storing events into cache. Default: `QueuedLogEvents`
* **`isQueueInCache`** Whether to store events in a buffer using cache for improved performance instead of storing them in the database straightaway.


# Log methods

## logEvent( logEvent ) <a href="#logevent" id="logevent"></a>

Logs the given `LogEvent`.

* **`logEvent`** The [LogEvent](/version-0.x/reference/core-classes/logevent) object to log.

**Returns:** A boolean indicating whether the event could be logged or not


# Login

The Login module provides a standardized method for implementing secure user identification workflows for web apps.

> See the [Login guide](/version-0.x/guide/login-guide) to learn how to work with the Login module.

## Configuration

* **`userClassName`** The name of the app class that represents a user on the App. Must implement the `\Cherrycake\LoginUser` interface.
* **`passwordAuthenticationMethod`** One of the available `LOGIN_PASSWORD_ENCRYPTION_METHOD_?`constants for password authentication methods. Default:`LOGIN_PASSWORD_ENCRYPTION_METHOD_PBKDF2`
* **`isLoadUserOnInit`** Whether to check for a logged user and get it on this module's init sequence. Default: `true`
* **`sleepOnErrorSeconds`** Seconds to delay execution when a wrong login is requested, to make things difficult for bombing attacks. Default: `1`

## Constants

* `LOGIN_PASSWORD_ENCRYPTION_METHOD_PBKDF2`
* `LOGIN_RESULT_OK`
* `LOGIN_RESULT_FAILED`
* `LOGIN_RESULT_FAILED_UNKNOWN_USER`
* `LOGIN_RESULT_FAILED_WRONG_PASSWORD`
* `LOGOUT_RESULT_OK`
* `LOGOUT_RESULT_FAILED`


# Login methods

## doLogin( userName, password ) <a href="#dologin" id="dologin"></a>

Checks the given credentials in the database, and logs in the user if they're found to be correct.

* **`userName`** The string field that uniquely identifies the user on the database, the one used by the user to login. Usually, an email or a username.
* **`password`** The password entered by the user to login.

**Returns:** One of the available [`LOGIN_RESULT_?`](/version-0.x/reference/core-modules/login#constants) constants signifying the result of the login operation.

## encryptPassword( password ) <a href="#encryptpassword" id="encryptpassword"></a>

Encrypts the given password with the configured password encryption method.

* **`password`** The password to encrypt

**Returns:** The encrypted string, or false if the password could not be encrypted

## isLogged

Checks whether there is a logged user or not.

**Returns:** True if the current user is logged or false if it's not.

## logoutUser

Logs out the current user.

**Returns:** One of the available [`LOGOUT_RESULT_?`](/version-0.x/reference/core-modules/login#constants) constants signifying the result of the logout operation.


# Output

Manages the final output produced by the app.

## Constants

* **`RESPONSE_OK`**
* **`RESPONSE_NOT_FOUND`**
* **`RESPONSE_NO_PERMISSION`**
* **`RESPONSE_INTERNAL_SERVER_ERROR`**
* **`RESPONSE_REDIRECT_MOVED_PERMANENTLY`**
* **`RESPONSE_REDIRECT_FOUND`**

##


# Output methods

## setResponse( response ) <a href="#setresponse" id="setresponse"></a>

Sets the Response object that will be sent to the client

* **`response`** [Response](/version-0.x/reference/core-classes/response) object

## sendResponse( response ) <a href="#sendresponse" id="sendresponse"></a>

Sends the current response. If a response is passed, sets it as the current response and then sends it.

* **`response`** Optional [Response](/version-0.x/reference/core-classes/response) object

##


# Patterns

Provides a patterns parser that uses PHP code to integrate your code seamlessly with your template files, providing advanced Cherrycake capabilities to your template structures.

> See the [Patterns guide](/version-0.x/guide/patterns-guide) to learn how to work with the Patterns module.

## Configuration

* **`directory`** The directory where patterns are stored.
* **`defaultCacheProviderName`** The default cache provider name to use for cached patterns.
* **`defaultCachePrefix`** The default TTL to use for cached patterns.
* **`defaultCacheTtl`** The default TTL to use for cached patterns.
* **`cachedPatterns`** A hash array of the patterns that will be cached, where each key is the name of the pattern, and each value is a hash array with the following possible keys:
  * **`cacheProviderName`** The cache provider name to use for this pattern. If not specified, it will use the one specified in the`defaultCacheProviderName` config key.
  * **`cachePrefix`** The cache prefix to use for this pattern. If not specified, it will use the one specified in the `defaultCachePrefix` config key.
  * **`cacheTtl`** The cache TTL to use for this pattern. If not specified, it will use the one specified in the `defaultCacheTtl` config key.


# Patterns methods

## clearCache( patternName, directoryOverride ) <a href="#clearcache" id="clearcache"></a>

Removes a pattern from cache.

* **`patternName`** The name of the pattern file
* **`directoryOverride`** If the cached pattern was originally retrieved also using `directoryOverride`, the same value needs to be specified here.

## parse\*\*( patternName, setup )\*\* <a href="#parse" id="parse"></a>

Parses a pattern

* **`patternName`** The name of the pattern file
* **`setup`** Optional hash array
  * **`directoryOverride`** When specified, the pattern is taken from this directory instead of the default configured directory.
  * **`noParse`** When set to true, the pattern is returned without any parsing.
  * **`fileToIncludeBeforeParsing`** A file or an array of files to include whenever parsing this set files, usually for defining variables that can be later used inside the pattern.
  * **`variables`** A hash array of variables passed to be available when parsing the pattern.

**Returns:** The parsed pattern, or false if failed.

## out( patternName, setup, code ) <a href="#out" id="out"></a>

Parses a pattern and sets the result as the output response payload.

* **`patternName`** The name of the pattern file
* **`setup`** Optional hash array: The options to be passed to the [parse](/version-0.x/reference/core-modules/patterns#parse-patternname-setup) method
* **`code`** Optional integer: The response code, one of the available RESPONSE\_\*


# Security

Provides security mechanisms used by other modules to detect, prevent, log and block attacks like SQL injection, XSS and CSRF.

> CSRF features require the [Session](/version-0.x/reference/core-modules/session) module.

## Constants

### Rules

* `SECURITY_RULE_NOT_NULL` The value must be not null, typically used to check whether a parameter has been passed or not. An empty field in a form will not trigger this rule.
* `SECURITY_RULE_NOT_EMPTY` The value must not be empty, typically used to check whether a parameter has been passed or not. An empty field in a form will trigger this rule.
* `SECURITY_RULE_INTEGER` The value must be an integer (-n to +n without decimals)
* `SECURITY_RULE_POSITIVE` The value must be positive (0 to +n)
* `SECURITY_RULE_MAX_VALUE` The value must be a number less than or equal the specified value
* `SECURITY_RULE_MIN_VALUE` The value must be a number greater than or equal the specified value
* `SECURITY_RULE_MAX_CHARS` The value must be less than or equal the specified number of chars
* `SECURITY_RULE_MIN_CHARS` The value must be bigger than or equal the specified number of chars
* `SECURITY_RULE_BOOLEAN` The value must be either a 0 or a 1
* `SECURITY_RULE_SLUG` The value must have the typical URL slug code syntax, containing only numbers and letters from A to Z both lower and uppercase, and -\_ characters
* `SECURITY_RULE_URL_SHORT_CODE` The value must have the typical URL short code syntax, containing only numbers and letters from A to Z both lower and uppercase
* `SECURITY_RULE_URL_ROUTE` The value must have the typical URL slug code syntax, like `SECURITY_RULE_SLUG` plus the "/" character
* `SECURITY_RULE_LIMITED_VALUES` The value must be exactly one of the specified values.
* `SECURITY_RULE_UPLOADED_FILE` The value must be a valid uploaded file. A value can be specified that must be an array of keys with setup options for the [checkUploadedFile](#checkuploadedfile-file-p) method.
* `SECURITY_RULE_UPLOADED_FILE_IMAGE` The value must be an uploaded image. A value can be specified that must be an array of keys with setup options for the [checkUploadedFile](#checkuploadedfile-file-p) method.
* `SECURITY_RULE_SQL_INJECTION` The value must not contain SQL injection suspicious strings
* `SECURITY_RULE_TYPICAL_ID` Same as `SECURITY_RULE_NOT_EMPTY` + `SECURITY_RULE_INTEGER` + `SECURITY_RULE_POSITIVE`

### Filters

* `SECURITY_FILTER_XSS` The value is purified to try to remove XSS attacks
* `SECURITY_FILTER_STRIP_TAGS` HTML tags are removed from the value
* `SECURITY_FILTER_TRIM` Spaces at the beginning and at the end of the value are trimmed
* `SECURITY_FILTER_JSON` Decodes json data

###

###


# Security methods

## checkUploadedFile( file, p ) <a href="#checkuploadedfile" id="checkuploadedfile"></a>

Checks an uploaded file for security attacks and moves it to a safe place if it is considered secure. It moves the file to a safe place, specified by the returned Result property "`finalPath`".

* When checking uploaded images (`isRequireImage` or `allowedImageTypes` has been set), image types other than jpg, gif or png are converted to png.
* When uploading compressed image formats like jpg, since this method generates a new image from the uploaded one for security purposes, the final compression is always set to the maximum possible setting. This will cause compressed images like jpg files to take more disk space than their originals in most cases.
* **`file`** The file array given by PHP after receiving an uploaded file, received via $\_FILES\[name of the file]
* **`setup`** Optional hash array
  * **`isRequireImage`** Requires the file to be an image. If `allowedImageTypes` is specified, this is forced to true.
  * **`allowedFileExtensions`** If value is specified with an array of extensions, only those file extensions are allowed. For example: `["pdf", "rtf"]`. If `allowedImageTypes` is specified and this is not, file extensions matching the specific `allowedImageTypes` will be required automatically.
  * **`allowedImageTypes`** If value is specified with an array of IMG\_?, only those image types are allowed (See <https://www.php.net/manual/en/image.constants.php>). If not specified, all image types supported by GD are accepted.

**Returns:** A [Result](/version-0.x/reference/core-classes/result) object with the following payloads:

* **`description`** A description of what went wrong
* **`finalPath`** The complete path where the file was moved if it was considered safe


# Session

Provides a session tracking and storage mechanism.

It uses the `cherrycake_session` table in the [Cherrycake skeleton database](/version-0.x/guide/getting-started#setting-up-the-skeleton-database) to store sessions, and caches them on the provided `sessionCacheProviderName`.

Session ids are generated by hashing 128 random bytes with a SHA512 algorithm, giving 128 hexits that constitute an effectively unpredictable session id to avoid session hijacking or collision.

Session id collisions are not checked because the probability of getting a collision is so low (1 in 16^128, or 1 in 1.3x10^154, a number *way* bigger than the estimated number of atoms in the observable universe) that it's preferable to have that security bug instead of having to perform that additional check on each newly created session.

A data storage mechanism is provided to store basic information within each session. The data is stored as a serialized array on the `data` field. When requesting an update of this data, the cache is flushed so it will generate an additional database hit on the next request.

> The sessions table must be maintained often in order to remove old sessions. Otherwise, a point will be reached where all possible session ids are used and the module will remove the oldest session from the database in order to make room for the new one, effectively generating stress on the database. This will most probably happen a while after the maximum entropy point has been reached and all the stars in the universe have gone extinct.

The `JanitorTaskSession` is required to be run in order to do this maintenance work, so be sure to [add it](/version-0.x/guide/janitor-guide) to your `Janitor.config.php`.

> See the [Session guide](/version-0.x/guide/session-guide) to learn how to work with the Session module.

## Configuration

* **`sessionDatabaseProviderName`** The name of the database provider to use for storing sessions. Default: `main`
* **`sessionTableName`** The name of the table used to store sessions. Default: `cherrycake_session`
* **`sessionCacheProviderName`** The name of the cache provider to use to store sessions and the counter of created sessions. Default: `engine`
* **`sessionCacheTtl`** The TTL of cached sessions, one of the available [`CACHE_TTL_?`](/version-0.x/reference/core-modules/cache#constants). Default: `CACHE_TTL_SHORT`.
* **`cachePrefix`** The cache prefix to use when storing sessions into cache. Default: `Session`
* **`cookieName`** The name of the cookie. Recommended to be changed. Defaut: `cherrycake`
* **`cookiePath`** The path of the cookie. If set to "/", it will be available within the entire domain. Default: `/`
* **`cookieSecure`** If set to true, the cookie will only be sent when the current request is secure (SSL). Default: `false`
* **`cookieHttpOnly`** If set to true, the cookie only will be sent when an HTTP request is made. Default: `false`
* **`sessionDuration`** The duration of the session in seconds. If set to zero, the session will last until the browser is closed. Default: `2592000` (one month)
* **`isSessionRenew`** When set to true, the duration of the session will be renewed to a new `sessionDuration` every time a request is made. If set to false, the cookie will expire after `sessionDuration`, no matter how many times the session is requested. Default: `true`




---

[Next Page](/llms-full.txt/1)

