static function createBackend($options = [], $backend = null) {
		$options = self::normalizeOptions($options);
		
		// Backend type
		if (isset($options[self::PARAM_TYPE])) {
			$backendType = (string) $options[self::PARAM_TYPE];
			unset($options[self::PARAM_TYPE]);
		} else {
			$backendType = self::DEFAULT_BACKEND;
		}
		
		// Profiler
		if (isset($options[self::PARAM_PROFILER])) {
			$profiler = (bool) $options[self::PARAM_PROFILER];
			unset($options[self::PARAM_PROFILER]);
		} else {
			$profiler = false;
		}
		
		// Tags ability
		if (isset($options[self::PARAM_TAGS])) {
			$tagsForced = (bool) $options[self::PARAM_TAGS];
			unset($options[self::PARAM_TAGS]);
		} else {
			$tagsForced = false;
		}
		
		// Tags backend
		if (isset($options[self::PARAM_TAGS_BACKEND])) {
			$tagsBackendOptions = $options[self::PARAM_TAGS_BACKEND];
			$tagsBackendOptions = self::normalizeOptions($tagsBackendOptions);
			unset($options[self::PARAM_TAGS_BACKEND]);
		}
		
		// Serialize
		if (isset($options[self::PARAM_SERIALIZE])) {
			$serialize = $options[self::PARAM_SERIALIZE];
			unset($options[self::PARAM_SERIALIZE]);
		}
		
		// If has not been specified
		if ($backend === null) {
			$backendClass = self::BACKENDS_NAMESPACE . '\\' . ucfirst($backendType);
			$backend      = new $backendClass($options);
		}
		
		// Wrap to a profiler
		if ($profiler) {
			if (! $backend instanceof ProfileableInterface) {
				$backend = new Profileable($backend);
			}
			
			$backend->setProfilerStatus(true);
		}
		
		// Wrap to a serializer
		if (isset($serialize)) {
			if (strtolower($serialize) === 'json') {
				$backend = new SerializerJson($backend);
			}
		}
		
		if (! $tagsForced || ($backend instanceof TaggableInterface && ! isset($tagsBackendOptions))) {
			return $backend;
		}
		
		$tagsDecorator = new Taggable($backend);
		
		if (isset($tagsBackendOptions)) {
			if (isset($tagsBackendOptions[self::PARAM_TYPE])) {
				$tagsBackend = self::createBackend($tagsBackendOptions);
			} else {
				$tagsBackend = self::createBackend($tagsBackendOptions, $backend);
			}
			
			$tagsDecorator->setTagHolderBackend($tagsBackend);
		}
		
		return $tagsDecorator;
	}
static function createBackend($options = [], $backend = null) {
		$options = self::normalizeOptions($options);
		
		// Backend type
		if (isset($options[self::PARAM_TYPE])) {
			$backendType = (string) $options[self::PARAM_TYPE];
			unset($options[self::PARAM_TYPE]);
		} else {
			$backendType = self::DEFAULT_BACKEND;
		}
		
		// Profiler
		if (isset($options[self::PARAM_PROFILER])) {
			$profiler = (bool) $options[self::PARAM_PROFILER];
			unset($options[self::PARAM_PROFILER]);
		} else {
			$profiler = false;
		}
		
		// Tags ability
		if (isset($options[self::PARAM_TAGS])) {
			$tagsForced = (bool) $options[self::PARAM_TAGS];
			unset($options[self::PARAM_TAGS]);
		} else {
			$tagsForced = false;
		}
		
		// Tags backend
		if (isset($options[self::PARAM_TAGS_BACKEND])) {
			$tagsBackendOptions = $options[self::PARAM_TAGS_BACKEND];
			$tagsBackendOptions = self::normalizeOptions($tagsBackendOptions);
			unset($options[self::PARAM_TAGS_BACKEND]);
		}
		
		// Serialize
		if (isset($options[self::PARAM_SERIALIZE])) {
			$serialize = $options[self::PARAM_SERIALIZE];
			unset($options[self::PARAM_SERIALIZE]);
		}
		
		// If has not been specified
		if ($backend === null) {
			$backendClass = self::BACKENDS_NAMESPACE . '\\' . ucfirst($backendType);
			$backend      = new $backendClass($options);
		}
		
		// Wrap to a profiler
		if ($profiler) {
			if (! $backend instanceof ProfileableInterface) {
				$backend = new Profileable($backend);
			}
			
			$backend->setProfilerStatus(true);
		}
		
		// Wrap to a serializer
		if (isset($serialize)) {
			if (strtolower($serialize) === 'json') {
				$backend = new SerializerJson($backend);
			}
		}
		
		if (! $tagsForced || ($backend instanceof TaggableInterface && ! isset($tagsBackendOptions))) {
			return $backend;
		}
		
		$tagsDecorator = new Taggable($backend);
		
		if (isset($tagsBackendOptions)) {
			if (isset($tagsBackendOptions[self::PARAM_TYPE])) {
				$tagsBackend = self::createBackend($tagsBackendOptions);
			} else {
				$tagsBackend = self::createBackend($tagsBackendOptions, $backend);
			}
			
			$tagsDecorator->setTagHolderBackend($tagsBackend);
		}
		
		return $tagsDecorator;
	}
static function createBackend ( $ options = [ ] , $ backend = null ) { $ options = self :: normalizeOptions ( $ options ) ; // Backend type if ( isset ( $ options [ self :: PARAM_TYPE ] ) ) { $ backendType = ( string ) $ options [ self :: PARAM_TYPE ] ; unset ( $ options [ self :: PARAM_TYPE ] ) ; } else { $ backendType = self :: DEFAULT_BACKEND ; } // Profiler if ( isset ( $ options [ self :: PARAM_PROFILER ] ) ) { $ profiler = ( bool ) $ options [ self :: PARAM_PROFILER ] ; unset ( $ options [ self :: PARAM_PROFILER ] ) ; } else { $ profiler = false ; } // Tags ability if ( isset ( $ options [ self :: PARAM_TAGS ] ) ) { $ tagsForced = ( bool ) $ options [ self :: PARAM_TAGS ] ; unset ( $ options [ self :: PARAM_TAGS ] ) ; } else { $ tagsForced = false ; } // Tags backend if ( isset ( $ options [ self :: PARAM_TAGS_BACKEND ] ) ) { $ tagsBackendOptions = $ options [ self :: PARAM_TAGS_BACKEND ] ; $ tagsBackendOptions = self :: normalizeOptions ( $ tagsBackendOptions ) ; unset ( $ options [ self :: PARAM_TAGS_BACKEND ] ) ; } // Serialize if ( isset ( $ options [ self :: PARAM_SERIALIZE ] ) ) { $ serialize = $ options [ self :: PARAM_SERIALIZE ] ; unset ( $ options [ self :: PARAM_SERIALIZE ] ) ; } // If has not been specified if ( $ backend === null ) { $ backendClass = self :: BACKENDS_NAMESPACE . '\\' . ucfirst ( $ backendType ) ; $ backend = new $ backendClass ( $ options ) ; } // Wrap to a profiler if ( $ profiler ) { if ( ! $ backend instanceof ProfileableInterface ) { $ backend = new Profileable ( $ backend ) ; } $ backend -> setProfilerStatus ( true ) ; } // Wrap to a serializer if ( isset ( $ serialize ) ) { if ( strtolower ( $ serialize ) === 'json' ) { $ backend = new SerializerJson ( $ backend ) ; } } if ( ! $ tagsForced || ( $ backend instanceof TaggableInterface && ! isset ( $ tagsBackendOptions ) ) ) { return $ backend ; } $ tagsDecorator = new Taggable ( $ backend ) ; if ( isset ( $ tagsBackendOptions ) ) { if ( isset ( $ tagsBackendOptions [ self :: PARAM_TYPE ] ) ) { $ tagsBackend = self :: createBackend ( $ tagsBackendOptions ) ; } else { $ tagsBackend = self :: createBackend ( $ tagsBackendOptions , $ backend ) ; } $ tagsDecorator -> setTagHolderBackend ( $ tagsBackend ) ; } return $ tagsDecorator ; }
Create the backend

Parameters:
param name   | datatype | default  | description
===============================================
type         | string   | memcache | Type of the backend (memcache, files...)
profiler     | bool     | false    | Queries must be profileable (implements the "ZExt\Profiler\ProfileableInterface")
tags         | bool     | false    | Backend must support the operations with a tags (save with tags, get by tags...)
tags_backend | array    | null     | Tags must be stored in a separated backend with personal params (regardless of tags supporting by backend)
serialize    | string   | null     | Serialize a data (eg. into json)

Other params will be passed to the backend's constructor (see backend constructors phpdocs)

@param  array | Traversable $options
@param  \ZExt\Cache\Backend\BackendInterface $backend
@return \ZExt\Cache\Backend\BackendInterface
Create the backend