.. _ch-object-management:

================
Object Framework
================

.. sectionauthor:: Robert Lemke <robert@neos.io>

The lifecycle of objects is managed centrally by the object framework. It offers
convenient support for Dependency Injection and provides some additional features such as
a caching mechanism for objects. Because all packages are built on this foundation it is
important to understand the general concept of objects in Flow.
Note that the object management features of Flow are by default only enabled for classes in
packages belonging to one of the `neos-*`` package types. All other classes are not
considered by default. If you need that (see :ref:`sect-enabling-non-flow-packages`).

.. tip::

	A very good start to understand the idea of Inversion of Control and Dependency
	Injection is reading `Martin Fowler's article`_ on the topic.

Creating Objects
================

In simple, self-contained applications, creating objects is as simple as using the ``new``
operator. However, as the program gets more complex, a developer is confronted with
solving dependencies to other objects, make classes configurable (maybe through a factory
method) and finally assure a certain scope for the object (such as ``Singleton`` or
``Prototype``). Howard Lewis Ship explained this circumstances nicely in `his blog`_
(quite some time ago):

	Once you start thinking in terms of large numbers of objects, and a whole lot of just
	in time object creation and configuration, the question of *how* to create a new object
	doesn't change (that's what ``new`` is for) ... but the questions *when* and *who*
	become 	difficult to tackle. Especially when the *when* is very dynamic, due to
	just-in-time instantiation, and the *who* is unknown, because there are so many places
	a particular object may be used.

The Object Manager is responsible for object building and dependency resolution (we'll
discover shortly why dependency injection makes such a difference to your application
design). In order to fulfill its task, it is important that all objects are instantiated
only through the object framework.

.. important::

	As a general rule of thumb for those not developing the Flow core itself but your very
	own packages:

	**Use Dependency Injection whenever possible for retrieving singletons.**

Object Scopes
-------------

Objects live in a specific scope. The most commonly used are *prototype* and *singleton*:

+---------------------+------------------------------------------------------------------+
| Scope               | Description                                                      |
+=====================+==================================================================+
| singleton           | The object instance is unique during one request - each          |
|                     | injection by the Object Manager or explicit call of              |
|                     | ``get()`` returns the same instance. A request can be an         |
|                     | HTTP request or a run initiated from the command line.           |
+---------------------+------------------------------------------------------------------+
| prototype (default) | The object instance is not unique - each injection or call of    |
|                     | the Object Factory's ``create`` method returns a fresh instance. |
+---------------------+------------------------------------------------------------------+
| session             | The object instance is unique during the whole user session -    |
|                     | each injection or ``get()`` call returns the same instance.      |
+---------------------+------------------------------------------------------------------+


.. admonition:: Background: Objects in PHP

	In PHP, objects of the scope ``prototype`` are created with the ``new`` operator::

		$myFreshObject = new \MyCompany\MyPackage\MyClassName();

	In contrast to Prototype, the Singleton design pattern ensures that only one instance of a
	class exists at a time. In PHP the Singleton pattern is often implemented by providing a
	static function (usually called ``getInstance``), which returns a unique instance of the
	class::

		/**
		 * Implementation of the Singleton pattern
		 */
		class ASingletonClass {

			protected static $instance;

			static public function getInstance() {
				if (!is_object(self::$instance)) {
					self::$instance = $this;
				}
				return self::$instance;
			}
		}

	Although this way of implementing the singleton will possibly not conflict with the Object
	Manager, it is counterproductive to the integrity of the system and might raise problems
	with unit testing (sometimes Singleton is referred to as an *Anti Pattern*).
	The above examples are *not recommended* for the use within Flow applications.

The scope of an object is determined from its configuration (see also :ref:`sect-configuring-objects`).
The recommended way to specify the scope is the ``@scope`` attribute or annotation::

	namespace MyCompany\MyPackage;

  use Neos\Flow\Annotations as Flow;

	/**
	 * @Flow\Scope("singleton")
	 */
	#[Flow\Scope("singleton")]
	class SomeClass {
	}


Note that only either the annotation or attribute is needed, not both. Prototype is the
default scope and is therefore assumed if no ``Scope`` attribute or other configuration
was found.

Creating Prototypes
-------------------

To create prototype objects, just use the ``new`` operator as you are used to::

	$myFreshObject = new \MyCompany\MyPackage\MyClassName();

When you do this, some magic is going on behind the scenes which still makes sure the object
you get back is managed by the object framework. Thus, all dependencies are properly injected
into the object, lifecycle callbacks are fired, and you can use Aspect-Oriented Programming, etc.

.. admonition:: Behind the scenes of the Object Framework

	In order to provide the functionality that you can just use ``new`` to create new
	prototype objects, a lot of advanced things happen behind the scenes.

	Flow internally copies all classes to another file, and appends ``_Original`` to their
	class name. Then, it creates a new class under the original name where all the magic is
	happening.

	However, you as a user do not have to deal with that. The only thing you need to remember
	is using ``new`` for creating new Prototype objects. And you might know this from PHP ;-)



Retrieving Singletons
---------------------

The Object Manager maintains a registry of all instantiated singletons and ensures that
only one instance of each class exists. The preferred way to retrieve a singleton object
is dependency injection.

*Example: Retrieving the Object Manager through dependency injection* ::

	namespace MyCompany\MyPackage;

	use Neos\Flow\ObjectManagement\ObjectManagerInterface;

	/**
	 * A sample class
	 */
	class SampleClass {

		protected ObjectManagerInterface $objectManager;

		/**
		 * The Object Manager will automatically be passed (injected) by the object
		 * framework on instantiating this class.
		 */
		public function __construct(ObjectManagerInterface $objectManager) {
			$this->objectManager = $objectManager;
		}
	}


Once the ``SampleClass`` is being instantiated, the object framework will automagically
pass a reference to the Object Manager (which is an object of scope *singleton*) as an
argument to the constructor. This kind of dependency injection is called
*Constructor Injection* and will be explained - together with other kinds of injection -
in one of the later sections.

Although dependency injection is what you should strive for, it might happen that you need
to retrieve object instances directly. The ``ObjectManager`` provides methods for
retrieving object instances for these rare situations. First, you need an instance of the
``ObjectManager`` itself, again by taking advantage of constructor injection::

	public function __construct(ObjectManagerInterface $objectManager) {
		$this->objectManager = $objectManager;
	}

.. note:: In the text, we commonly refer to the ``ObjectManager``. However, in your code, you should
   always use the ``ObjectManagerInterface`` if you need an instance of the Object Manager injected.

To explicitly retrieve an object instance use the ``get()`` method::

	$myObjectInstance = $objectManager->get('MyCompany\MyPackage\MyClassName');

It is *not* possible to pass arguments to the constructor of the object, as the object might
be already instantiated when you call ``get()``. If the object needs constructor arguments,
these must be :ref:`configured in Objects.yaml <sect-objects-yaml>`.

Lifecycle methods
-----------------

The lifecycle of an object goes through different stages. It boils down to the following
order:

#. Solve dependencies for constructor injection
#. Create an instance of the object class, injecting the constructor dependencies
#. Solve and inject dependencies for setter injection
#. Live a happy object-life and solve exciting tasks
#. Dispose the object instance

Your object might want to take some action after certain of the above steps. Whenever one
of the following methods exists in the object class, it will be invoked after the related
lifecycle step:

#. No action after this step
#. During instantiation the function ``__construct()`` is called (by PHP itself),
   dependencies are passed to the constructor arguments
#. After all dependencies have been injected (through constructor- or setter injection)
   the object's ``initializeObject()`` method is called. The name of this method is configurable
   inside *Objects.yaml*. ``initializeObject()`` is also called if no dependencies were injected.
#. During the life of an object no special lifecycle methods are called
#. Before destruction of the object, the function ``shutdownObject()`` is called. The name of
   this method is also configurable.
#. On disposal, the function ``__destruct()`` is called (by PHP itself)

We strongly recommend that you use the ``shutdownObject`` method instead of PHP's
``__destruct`` method for shutting down your object. If you used ``__destruct`` it might
happen that important parts of the framework are already unavailable. Here's a simple
example with all kinds of lifecycle methods:

*Example: Sample class with lifecycle methods* ::

	class Foo {

		protected $bar;
		protected $identifier = 'Untitled';

		public function __construct() {
			echo ('Constructing object ...');
		}

		public function injectBar(\MyCompany\MyPackage\BarInterface $bar) {
			$this->bar = $bar;
		}

		public function setIdentifier($identifier) {
			$this->identifier = $identifier;
		}

		public function initializeObject() {
			echo ('Initializing object ...');
		}

		public function shutdownObject() {
			echo ('Shutting down object ...')
		}

		public function __destruct() {
			echo ('Destructing object ...');
		}
	}

Output::

	Constructing object ...
	Initializing object ...
	Shutting down object ...
	Destructing object ...

Object Registration and API
===========================

Object Framework API
--------------------

The object framework provides a lean API for registering, configuring and retrieving
instances of objects. Some of the methods provided are exclusively used within Flow
package or in test cases and should possibly not be used elsewhere. By offering
Dependency Injection, the object framework helps you to avoid creating rigid
interdependencies between objects and allows for writing code which is hardly or even not
at all aware of the framework it is working in. Calls to the Object Manager should
therefore be the exception.

For a list of available methods please refer to the API documentation of the interface
``Neos\Flow\ObjectManagement\ObjectManagerInterface``.

Object Names vs. Class Names
----------------------------

We first need to introduce some namings: A *class name* is the name of a PHP class, while an
*object name* is an identifier which is used inside the object framework to identify a certain
object.

By default, the *object name* is identical to the PHP class which contains the
object's code. A class called ``MyCompany\MyPackage\MyImplementation`` will be
automatically available as an object with the exact same name. Every part of the system
which asks for an object with a certain name will therefore - by default - get an instance
of the class of that name.

It is possible to replace the original implementation of an
object by another one. In that case the class name of the new implementation will
naturally differ from the object name which stays the same at all times. In these cases it
is important to be aware of the fine difference between an *object name* and a *class name*.

All PHP interfaces for which only one implementation class exist are also automatically
registered as *object names*, with the implementation class being returned when asked
for an instance of the interface.

Thus, you can also ask for interface implementations::

	$objectTypeInstance = $objectManager->get('MyCompany\MyPackage\MyInterface');

.. note::

  If zero or more than one class implements the interface, the Object Manager will
  throw an exception.

The advantage of programming against interfaces is the increased
flexibility: By referring to interfaces rather than classes it is possible to write code
depending on other classes without the need to be specific about the implementation. Which
implementation will actually be used can be set at a later point in time by simple means
of configuration.

With Flow version 6.2 it's also possible to use "virtual object names" that don't represent
an interface or class name (see :ref:`sect-virtual-objects`).

Object Dependencies
===================

The intention to base an application on a combination of packages and objects is to force
a clean separation of domains which are realized by dedicated objects. The less each
object knows about the internals of another object, the easier it is to modify or replace
one of them, which in turn makes the whole system flexible. In a perfect world, each of
the objects could be reused in a variety of contexts, for example independently from
certain packages and maybe even outside the Flow framework.

Dependency Injection
--------------------

An important prerequisite for reusable code is already met by encouraging encapsulation
through object orientation. However, the objects are still aware of their environment as
they need to actively collaborate with other objects and the framework itself: An
authentication object will need a logger for logging intrusion attempts and the code of a
shop system hopefully consists of more than just one class. Whenever an object refers to
another directly, it adds more complexity and removes flexibility by opening new
interdependencies. It is very difficult or even impossible to reuse such hardwired classes
and testing them becomes a nightmare.

By introducing *Dependency Injection*, these interdependencies are minimized by inverting
the control over resolving the dependencies: Instead of asking for the instance of an
object actively, the depending object just gets one *injected* by the Object Manager.
This methodology is also referred to as the "`Hollywood Principle`_": *Don't call us,
we'll call you.* It helps in the development of code with loose coupling and high
cohesion --- or in short: It makes you a better programmer.

In the context of the previous example it means that the authentication object announces
that it needs a logger which implements a certain PHP interface (for example the
``Psr\Log\LoggerInterface``).
The object itself has no control over what kind of logger (file-logger,
sms-logger, ...) it finally gets and it doesn't have to care about it anyway as long as it
matches the expected API. As soon as the authentication object is instantiated, the object
manager will resolve these dependencies, prepare an instance of a logger and
inject it to the authentication object.

.. admonition:: Reading Tip

	`An article`_ by Jonathan Amsterdam discusses the difference between creating an object
	and requesting one (i.e. using ``new`` versus using dependency injection). It
	demonstrates why ``new`` should be considered as a low-level tool and outlines issues
	with polymorphism. He doesn't mention dependency injection though ...

Dependencies on other objects can be declared in the object's configuration
(see :ref:`sect-configuring-objects`) or they can be solved automatically (so called autowiring).
Generally there are two modes of dependency injection supported by Flow:
*Constructor Injection* and *Setter Injection*.

.. note::
	Please note that Flow removes all injected properties before serializing an object.
	Then after deserializing injections happen again. That means that injected properties are
	fresh instances and do not keep any state from before the serialization. That holds true
	also for prototypes. If you want to keep a prototype instance with its state throughout
	a serialize/unserialize cycle you should not inject the Prototype but rather create it in
	constructor of the object.

Constructor Injection
---------------------

With constructor injection, the dependencies are passed as constructor arguments to the
depending object while it is instantiated. Here is an example of an object ``Foo`` which
depends on an object ``Bar``:

*Example: A simple example for Constructor Injection* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $bar;

		public function __construct(\MyCompany\MyPackage\BarInterface $bar) {
			$this->bar = $bar;
		}

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

So far there's nothing special about this class, the type hint just makes sure that an instance of
a class implementing the ``\MyCompany\MyPackage\BarInterface`` is passed to the constructor.
However, this is already a quite flexible approach because the type of ``$bar`` can be
determined from outside by just passing one or the another implementation to the
constructor.

Now the Flow Object Manager does some magic: By a mechanism called *Autowiring* all
dependencies which were declared in a constructor will be injected automagically if the
constructor argument provides a type definition (i.e.
``\MyCompany\MyPackage\BarInterface`` in the above example). Autowiring is activated by
default (but can be switched off), therefore all you have to do is to write your
constructor method.

The object framework can also be configured manually to inject a certain object or object
type. You'll have to do that either if you want to switch off autowiring or want to
specify a configuration which differs from would be done automatically.

*Example: Objects.yaml file for Constructor Injection*

.. code-block:: yaml

	MyCompany\MyPackage\Foo:
	  arguments:
	    1:
	      object: 'MyCompany\MyPackage\Bar'

The three lines above define that an object instance of ``\MyCompany\MyPackage\Bar`` must
be passed to the first argument of the constructor when an instance of the object
``MyCompany\MyPackage\Foo`` is created.

Setter Injection
----------------

With setter injection, the dependencies are passed by calling *setter methods* of the
depending object right after it has been instantiated. Here is an example of the ``Foo``
class which depends on a ``Bar`` object - this time with setter injection:

*Example: A simple example for Setter Injection* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $bar;

		public function setBar(\MyCompany\MyPackage\BarInterface $bar) {
			$this->bar = $bar;
		}

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

Analog to the constructor injection example, a ``BarInterface`` compatible object is
injected into the ``Foo`` object. In this case, however, the injection only takes
place after the class has been instantiated and a possible constructor method has been
called. The necessary configuration for the above example looks like this:

*Example: Objects.yaml file for Setter Injection*

.. code-block:: yaml

	MyCompany\MyPackage\Foo:
	  properties:
	    bar:
	      object: 'MyCompany\MyPackage\BarInterface'

Unlike constructor injection, setter injection like in the above example does not offer
the autowiring feature. All dependencies have to be declared explicitly in the object
configuration.

To save you from writing large configuration files, Flow supports a second
type of setter methods: By convention all methods whose name start with ``inject`` are
considered as setters for setter injection. For those methods no further configuration is
necessary, dependencies will be autowired (if autowiring is not disabled):

*Example: The preferred way of Setter Injection, using an inject method* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $bar;

		public function injectBar(\MyCompany\MyPackage\BarInterface $bar) {
			$this->bar = $bar;
		}

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

Note the new method name ``injectBar`` - for the above example no further configuration is
required. Using ``inject*`` methods is the preferred way for setter
injection in Flow.

.. note::

	If both, a ``set*`` and an ``inject*`` method exist for the same property, the
	``inject*`` method has precedence.

Constructor- or Setter Injection?
---------------------------------

The natural question which arises at this point is *Should I use constructor- or setter
injection?* There is no answer across-the-board --- it mainly depends on the situation
and your preferences. The authors of the Java-based `Spring Framework`_ for example
prefer Setter Injection for its flexibility. The more puristic developers of
`PicoContainer`_ strongly plead for using Constructor Injection for its cleaner
approach. Reasons speaking in favor of constructor injections are:

* Constructor Injection makes a stronger dependency contract
* It enforces a determinate state of the depending object:
  using setter Injection, the injected object is only available after the constructor
  has been called

However, there might be situations in which constructor injection is not possible or
even cumbersome:

* If an object has many dependencies and maybe even many optional dependencies, setter
  injection is a better solution.
* Subclasses are not always in control over the arguments passed to the constructor or
  might even be incapable of overriding the original constructor.
  Then setter injection is your only chance to get dependencies injected.
* Setter injection can be helpful to avoid circular dependencies between objects.
* Setters provide more flexibility to unit tests than a fixed set of constructor
  arguments

Property Injection
------------------

Setter injection is the academic, clean way to set dependencies from outside. However,
writing these setters can become quite tiresome if all they do is setting the property.
For these cases Flow provides support for *Property Injection*:

*Example: Example for Property Injection* ::

	namespace MyCompany\MyPackage;

  use Neos\Flow\Annotations as Flow;

	class Foo {

		/**
		 * An instance of a BarInterface compatible object.
		 *
		 * @var \MyCompany\MyPackage\BarInterface
		 * @Flow\Inject
		 */
		protected $bar;

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

You could say that property injection is the same like setter injection --- just without the
setter. The ``Inject`` annotation tells the object framework that the property is
supposed to be injected and the ``@var`` annotation specifies the type. Note that property
injection even works (and should only be used) with protected properties. The *Objects.yaml*
configuration for property injection is identical to the setter injection configuration.

.. note::

	If a setter method exists for the same property, it has precedence.

Setting properties directly, without a setter method, surely is convenient - but is it
clean enough? In general it is a bad idea to allow direct access to mutable properties
because you never know if at some point you need to take some action while a property is
set. And if thousands of users (or only five) use your API, it's hard to change your
design decision in favor of a setter method.

However, we don't consider injection methods as part of the public API. As you've seen,
Flow takes care of all the object dependencies and the only other code working with
injection methods directly are unit tests. Therefore we consider it safe to say that you
can still switch back from property injection to setter injection without problems if it
turns out that you really need it.

Lazy Dependency Injection
-------------------------

Using Property Injection is, in its current implementation, the most performant way
to inject a dependency. As an important additional benefit you also get Lazy
Dependency Injection: instead of loading the class of the dependency, instantiating
and intializing it, a ``proxy`` is injected instead. This object waits until it
will be accessed the first time. Once you start using the dependency, the proxy
will build or retrieve the real dependency, call the requested method and return
the result. On all following method calls, the real object will be used.

By default all dependencies injected through Property Injection are lazy. Usually
this process is fully transparent to the user, unless you start passing around
dependencies to other objects:

*Example: Passing a dependency around* ::

	namespace MyCompany\MyPackage;

  use Neos\Flow\Annotations as Flow;

	class Foo {

		/**
		 * A dependency, injected lazily:
		 *
		 * @var \MyCompany\MyPackage\BarInterface
		 * @Flow\Inject
		 */
		protected $bar;

		...

		public function doSomething() {
			$this->baz->doSomethingElse($this->bar);
		}

	}

	class Baz {

		public function doSomethingElse(Bar $bar) {
			...
		}

	}

The above example will break: at the time you pass ``$this->bar`` to the
``doSomethingElse()`` method, it is not yet a ``Bar`` object but a
``DependencyProxy`` object. Because ``doSomethingElse()`` has a type hint requiring
a ``Bar`` object, PHP will issue a fatal error.

There are two ways to solve this:

* activating the dependency manually
* turning off lazy dependency injection for this property

*Example: Manually activating a dependency* ::

	namespace MyCompany\MyPackage;

  use Neos\Flow\Annotations as Flow;

	class Foo {

		/**
		 * A dependency, injected lazily:
		 *
		 * @var \MyCompany\MyPackage\BarInterface
		 * @Flow\Inject
		 */
		protected $bar;

		...

		public function doSomething() {
			if ($this->bar instanceof \Neos\Flow\ObjectManagement\DependencyInjection\DependencyProxy) {
				$this->bar->_activateDependency();
			}
			$this->baz->doSomethingElse($this->bar);
		}

	}

In the example above, ``$this->bar`` is activated before it is passed to the next
method. It's important to check if the object still is a proxy because otherwise
calling ``_activateDependency()`` will fail.

*Example: Turning off lazy dependency injection* ::

	namespace MyCompany\MyPackage;

  use Neos\Flow\Annotations as Flow;

	class Foo {

		/**
		 * A dependency, injected eagerly
		 *
		 * @var \MyCompany\MyPackage\BarInterface
		 * @Flow\Inject(lazy = false)
		 */
		protected $bar;

		...

		public function doSomething() {
			$this->baz->doSomethingElse($this->bar);
		}

	}

In the second solution, lazy dependency injection is turned off. This way you can
be sure that ``$this->bar`` always contains the object you expected, but you don't
benefit from the speed optimizations.

Settings Injection
------------------

No, this headline is not misspelled. Flow offers some convenient feature which allows for
automagically injecting the settings of the current package without the need to configure
the injection. If a class contains a method called ``injectSettings`` and autowiring is
not disabled for that object, the Object Builder will retrieve the settings of the package
the object belongs to and pass it to the ``injectSettings`` method.

*Example: the magic injectSettings method* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $settings = array();

		public function injectSettings(array $settings) {
			$this->settings = $settings;
		}

		public function doSomething() {
			var_dump($this->settings);
		}
	}

The ``doSomething`` method will output the settings of the ``MyPackage`` package.

In case you only need a specific setting, there's an even more convenient way to inject a single
setting value into a class property or constructor argument:

.. code-block:: php

	namespace Acme\Demo;

  use Neos\Flow\Annotations as Flow;

	class SomeClass {

		#[Flow\InjectConfiguration(path: "email", package: "SomeOther.Package")]
		protected string $email;

		public function __construct(
		  #[Flow\InjectConfiguration(path: "administrator.name")]
		  readonly protected string $name
		  )
		  {}
	}

The ``InjectConfiguration`` attribute also supports for injecting all settings of a package. And it can also be used
to inject any other registered configuration type:

.. code-block:: php

	namespace Acme\Demo;

	class SomeClass {

		#[Flow\InjectConfiguration(package: "SomeOther.Package")]
		protected array $allSettingsOfSomeOtherPackage;

		#[Flow\InjectConfiguration(type: "Views")]
		protected array $viewsConfiguration;
	}

Required Dependencies
---------------------

All dependencies defined in a constructor are, by its nature, required. If a dependency
can't be solved by autowiring or by configuration, Flow's object builder will throw an
exception.

Also *autowired setter-injected dependencies* are, by default, required. If the object
builder can't autowire an object for an injection method, it will throw an exception.

Dependency Resolution
---------------------

The dependencies between objects are only resolved during the instantiation process.
Whenever a new instance of an object class needs to be created, the object configuration
is checked for possible dependencies. If there is any, the required objects are built and
only if all dependencies could be resolved, the object class is finally instantiated and
the dependency injection takes place.

During the resolution of dependencies it might happen that circular dependencies occur. If
an object ``A`` requires an object ``B`` to be injected to its constructor and then again object ``B``
requires an object ``A`` likewise passed as a constructor argument, none of the two classes can
be instantiated due to the mutual dependency. Although it is technically possible (albeit
quite complex) to solve this type of reference, Flow's policy is not to allow circular
constructor dependencies at all. As a workaround you can use setter injection instead
for either one or both of the objects causing the trouble.

.. _sect-configuring-objects:

Configuring objects
===================

The behavior of objects significantly depends on their configuration. During the
initialization process all classes found in the various *Classes/* directories are
registered as objects and an initial configuration is prepared. In a second step, other
configuration sources are queried for additional configuration options. Definitions found
at these sources are added to the base configuration in the following order:

* If they exist, the *<PackageName>/Configuration/Objects.yaml* will be included.
* Additional configuration defined in the global *Configuration/Objects.yaml* directory is applied.
* Additional configuration defined in the global *Configuration/<ApplicationScope>/Objects.yaml* directory is applied.

Currently there are three important situations in which you want to configure objects:

* Override one object implementation with another
* Set the active implementation for an object type
* Explicitly define and configure dependencies to other objects

.. _sect-objects-yaml:

Configuring Objects Through Objects.yaml
----------------------------------------

If a file named *Objects.yaml* exists in the *Configuration* directory
of a package, it will be included during the configuration process. The YAML file should
stick to Flow's general rules for YAML-based configuration.

*Example: Sample Objects.yaml file*

.. code-block:: yaml

	#                                                                        #
	# Object Configuration for the MyPackage package                         #
	#                                                                        #

	# @package MyPackage

	MyCompany\MyPackage\Foo:
	  arguments:
	    1:
	      object: 'MyCompany\MyPackage\Baz'
	    2:
	      value: "some string"
	    3:
	      value: false
	  properties:
	    bar:
	      object: 'MyCompany\MyPackage\BarInterface'
	    enableCache:
	      setting: MyPackage.Cache.enable

Configuring Objects Through Annotations
---------------------------------------

A very convenient way to configure certain aspects of objects are annotations. You write
down the configuration directly where it takes effect: in the class file. However, this
way of configuring objects is not really flexible, as it is hard coded. That's why only
those options can be set through annotations which are part of the class design and won't
change afterwards. Currently ``scope``, ``inject`` and ``autowiring`` are the only
supported annotations.

It's up to you defining the scope in the class directly or doing it in a *Objects.yaml*
configuration file – both have the same effect. We recommend using annotations in this
case, as the scope usually is a design decision which is very unlikely to be changed.

*Example: Sample scope annotation* ::

	/**
	 * This is my great class.
	 *
	 * @Flow\Scope("singleton")
	 */
	class SomeClass {

	}

*Example: Sample autowiring annotation for a class* ::

	/**
	 * This turns off autowiring for the whole class:
	 *
	 * @Flow\Autowiring(false)
	 */
	class SomeClass {

	}

*Example: Sample autowiring annotation for a method* ::

	/**
	 * This turns off autowiring for a single method:
	 *
	 * @param \Neos\Foo\Bar $bar
	 * @Flow\Autowiring(false)
	 */
	public function injectMySpecialDependency(\Neos\Foo\Bar $bar) {

	}

Overriding Object Implementations
---------------------------------

One advantage of componentry is the ability to replace objects by others
without any bad impact on those parts depending on them.


A prerequisite for replaceable objects is that their classes implement a common
`interface`_ which defines the public API of the original object. Other objects
which implement the same interface can then act as a true replacement for the
original object without the need to change code anywhere in the system. If this
requirement is met, the only necessary step to replace the original
implementation with a substitute is to alter the object configuration and set
the class name to the new implementation.

To illustrate this circumstance, consider the following classes.

*Example: The Greeter object type* ::

	namespace MyCompany\MyPackage;

	interface GreeterInterface {
		public function sayHelloTo($name);
	}

	class Greeter implements GreeterInterface {
		public function sayHelloTo($name) {
			echo 'Hello ' . $name;
		}
	}

During initialization the above ``Greeter`` class will automatically be
registered as the default implementation of
``MyCompany\MyPackage\GreeterInterface`` and is available to other objects. In
the class code of another object you might find the following lines.

*Example: Using the Greeter object type* ::

	// Use setter injection for fetching an instance
	// of \MyCompany\MyPackage\GreeterInterface:
	public function injectGreeter(\MyCompany\MyPackage\GreeterInterface $greeter) {
		$this->greeter = $greeter;
	}

	public function someAction() {
		$this->greeter->sayHelloTo('Heike');
	}

If we want to use the much better object
``\Neos\OtherPackage\GreeterWithCompliments``, the solution is to let the new
implementation implement the same interface.

*Example: The improved Greeter object type* ::

	namespace Neos\OtherPackage;

	class GreeterWithCompliments implements \MyCompany\MyPackage\GreeterInterface {
		public function sayHelloTo($name) {
			echo('Hello ' . $name . '! You look so great!');
		}
	}

Then we have to set which implementation of the ``MyCompany\MyPackage\GreeterInterface``
should be active and are done:

*Example: Objects.yaml file for object type definition*

.. code-block:: yaml

	MyCompany\MyPackage\GreeterInterface:
	  className: 'Neos\OtherPackage\GreeterWithCompliments'

The the same code as above will get the improved ``GreeterWithCompliments``
instead of the simple ``Greeter`` now.


Configuring Injection
---------------------

The object framework allows for injection of straight values, objects (i.e. dependencies)
or settings either by passing them as constructor arguments during instantiation of the
object class or by calling a setter method which sets the wished property accordingly. The
necessary configuration for injecting objects is usually generated automatically by the
*autowiring* capabilities of the Object Builder. Injection of straight values or settings,
however, requires some explicit configuration.

Injection Values
~~~~~~~~~~~~~~~~

Regardless of what injection type is used (constructor or setter injection), there are
three kinds of value which can be injected:

* *value*: static value of a simple type. Can be string, integer, boolean or array and is
  passed on as is.
* *object*: object name which represents a dependency.
  Dependencies of the injected object are resolved and an instance of the object is
  passed along.
* *setting*: setting defined in one of the *Settings.yaml* files. A path separated by dots
  specifies which setting to inject.

Constructor Injection
~~~~~~~~~~~~~~~~~~~~~

Arguments for constructor injection are defined through the *arguments* option. Each
argument is identified by its position, counting starts with 1.

*Example: Sample class for Constructor Injection* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $bar;
		protected $identifier;
		protected $enableCache;

		public function __construct(\MyCompany\MyPackage\BarInterface $bar, $identifier,
			    $enableCache) {
			$this->bar = $bar;
			$this->identifier = $identifier;
			$this->enableCache = $enableCache;
		}

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

*Example: Sample configuration for Constructor Injection*

.. code-block:: yaml

	MyCompany\MyPackage\Foo:
	  arguments:
	    1:
	      object: 'MyCompany\MyPackage\Bar'
	    2:
	      value: "some string"
	    3:
	      setting: "MyPackage.Cache.enable"

.. note::

	It is usually not necessary to configure injection of objects explicitly. It is much
	more convenient to just declare the type of the constructor arguments (like
	``MyCompany\MyPackage\BarInterface`` in the above example) and let the autowiring
	feature configure and resolve the dependencies for you.

Setter Injection
~~~~~~~~~~~~~~~~

The following class and the related *Objects.yaml* file demonstrate the syntax for the
definition of setter injection:

*Example: Sample class for Setter Injection* ::

	namespace MyCompany\MyPackage;

	class Foo {

		protected $bar;
		protected $identifier = 'Untitled';
		protected $enableCache = false;

		public function injectBar(\MyCompany\MyPackage\BarInterface $bar) {
			$this->bar = $bar;
		}

		public function setIdentifier($identifier) {
			$this->identifier = $identifier;
		}

		public function setEnableCache($enableCache) {
			$this->enableCache = $enableCache;
		}

		public function doSomething() {
			$this->bar->doSomethingElse();
		}
	}

*Example: Sample configuration for Setter Injection*

.. code-block:: yaml

	MyCompany\MyPackage\Foo:
	  properties:
	    bar:
	      object: 'MyCompany\MyPackage\Bar'
	    identifier:
	      value: 'some string'
	    enableCache:
	      setting: 'MyPackage.Cache.enable'

As you can see, it is important that a setter method with the same name as the property,
preceded by ``inject`` or ``set`` exists. It doesn't matter though, if you choose ``inject`` or
``set``, except that ``inject`` has the advantage of being autowireable. As a rule of thumb we
recommend using ``inject`` for required dependencies and values and ``set`` for optional
properties.

.. TODO: is the last sentence still true? (Optional properties...)

Injection of Objects Specified in Settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In some cases it might be convenient to specify the name of the object to be injected in
the *settings* rather than in the objects configuration. This can be achieved by
specifying the settings path instead of the object name:

*Example: Injecting an object specified in the settings*

.. code-block:: yaml

	MyCompany\MyPackage\Foo:
	  properties:
	    bar:
	      object: 'MyCompany.MyPackage.fooStuff.barImplementation'

*Example: Settings.yaml of MyPackage*

.. code-block:: yaml

	MyCompany:
	  MyPackage:
	    fooStuff:
	      barImplementation: 'MyCompany\MyPackage\Bars\ASpecialBar'

Nested Object Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~

While autowiring and automatic dependency injection offers a great deal of convenience, it
is sometimes necessary to have a fine grained control over which objects are injected with
which third objects injected.

Consider a Flow cache object, a ``VariableCache`` for example: the cache itself depends
on a cache backend which on its part requires a few settings passed to its constructor -
this readily prepared cache should now be injected into another object. Sounds complex?
With the objects configuration it is however possible to configure even that nested object
structure:

*Example: Nesting object configuration*

.. code-block:: yaml

	MyCompany\MyPackage\Controller\StandardController:
	  properties:
	    cache:
	      object:
	        name: 'Neos\Cache\VariableCache'
	        arguments:
	          1:
	            value: MyCache
	          2:
	            object:
	              name: 'Neos\Cache\Backend\File'
	              properties:
	                cacheDirectory:
	                  value: /tmp/

Disabling Autowiring
~~~~~~~~~~~~~~~~~~~~

Injecting dependencies is a common task. Because Flow can detect the type of dependencies
a constructor needs, it automatically configures the object to ensure that the necessary
objects are injected. This automation is called *autowiring* and is enabled by default for
every object. As long as autowiring is in effect, the Object Builder will try to autowire
all constructor arguments and all methods named after the pattern ``inject*``.

If, for some reason, autowiring is not wanted, it can be disabled by setting an option in
the object configuration:

*Example: Turning off autowiring support in Objects.yaml*

.. code-block:: yaml

	MyCompany\MyPackage\MyObject:
	  autowiring: false

Autowiring can also be switched off through the ``@Flow\Autowiring(false)`` annotation or
the ``#[Flow\Autowiring(false)]`` attribute - either in the documentation block of a whole
class or of a single method. For the latter the annotation or attribute only has an effect
when used for a constructor or a method whose name starts with ``inject``.

Finally, autowiring for constructors can also be disabled through a setting. The setting
accepts an array of fully qualified class names, where each entry is a regular expression:

.. code-block:: yaml

	Neos:
	  Flow:
	    object:
	      dependencyInjection:
	        excludeClassesFromConstructorAutowiring:
	          - '^Neos\\SomePackage\\Domain\\.*\\Command\\.*$'

Classes of scope prototype which expect objects to be passed to their constructor
are usually considered for autowiring which results in a proxy class being generated.
This option allows to exclude classes from this process. This is useful for classes
like data transfer objects, read models, commands, events and value objects which
usually don't rely on dependency injection.

.. note::

	Flow cannot reliably detect weather a prototype class depends on autowiring for
	constructor arguments or not. Use this option to optimize your application to avoid
	the small but measurable overhead of proxy generation for those kinds of classes.
	Note that if there are other reasons than constructor injection which require a
	proxy class to be generated, the proxy class will be generated no matter what.

Custom Factories
----------------

Complex objects might require a custom factory which takes care of all important settings
and dependencies. As we have seen previously, a logger consists of a frontend, a backend
and configuration options for that backend. Instead of creating and configuring these
objects on your own, you should use the ``Neos\Flow\Log\PsrLoggerFactory`` which provides a
convenient ``get`` method taking care of all the rest::

	$myCache = $loggerFactory->get('systemLogger');

It is possible to specify for each object if it should be created by a custom factory
rather than the Object Builder. Consider the following configuration:

*Example: Sample configuration for a Custom Factory*

.. code-block:: yaml

	Neos\Flow\Log\PsrSystemLoggerInterface:
	  scope: singleton
	  factoryObjectName: Neos\Flow\Log\PsrLoggerFactory
	  factoryMethodName: get

From now on the LoggerFactory's ``get`` method will be called each time an object of
type ``PsrSystemLoggerInterface`` needs to be instantiated. If arguments were passed to the
``ObjectManagerInterface::get()`` method or defined in the configuration, they will be
passed through to the custom factory method:

*Example: YAML configuration for a Custom Factory with default arguments*

.. code-block:: yaml

	Neos\Flow\Log\PsrSystemLoggerInterface:
	  scope: singleton
	  factoryObjectName: Neos\Flow\Log\PsrLoggerFactory
	  factoryMethodName: get
	  arguments:
	    1:
	      value: 'systemLogger'

*Example: YAML configuration for a static custom factory method*

.. code-block:: yaml

	Acme\Foo\Object:
	  scope: prototype
	  factoryMethodName: Acme\Foo\ObjectFactory::fromValue
	  arguments:
	    1:
	      settings: 'Acme.Foo.Object.ConfigurableValue'

Note that if you only specify the `factoryMethodName`, it needs to be the fully qualified name.

*Example: PHP code using the custom factory* ::

	$myCache = $objectManager->get(\Neos\Flow\Log\PsrSystemLoggerInterface::class);

``$objectManager`` is a reference to the ``Neos\Flow\ObjectManagement\ObjectManager``.
The required arguments are automatically built from the values defined in the
object configuration.

Name of Lifecycle Methods
-------------------------

The default name of a lifecycle methods is ``initializeObject`` and ``shutdownObject``.
If these methods exist, the initialization method will be called after the object has been
instantiated or recreated and all dependencies are injected and the shutdown method is
called before the Object Manager quits its service.

As the initialization method is being called after creating an object *and* after
recreating/reconstituting an object, there are cases where different code should be
executed. That is why the initialization method gets a parameter, which is one of the
``\Neos\Flow\ObjectManagement\ObjectManagerInterface::INITIALIZATIONCAUSE_*`` constants:

``\Neos\Flow\ObjectManagement\ObjectManagerInterface::INITIALIZATIONCAUSE_CREATED``
  If the object is newly created (i.e. the constructor has been called)
``\Neos\Flow\ObjectManagement\ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED``
  If the object has been recreated/reconstituted (i.e. the constructor has not been
  called)

The name of both methods is configurable per object for situations you don't have control
over the name of your initialization method (maybe, because you are integrating legacy
code):

*Example: Objects.yaml configuration of the initialization and shutdown method*

.. code-block:: yaml

	MyCompany\MyPackage\MyObject:
	  lifecycleInitializationMethod: myInitializeMethodName
	  lifecycleShutdownMethod: myShutdownMethodName

Static Method Result Compilation
================================

Some part of a Flow application may rely on data which is static during runtime,
but which cannot or should not be hardcoded.

One example is the validation rules generated by the MVC framework for arguments of
a controller action: the base information (PHP methods for the actions, type hints
and arguments of these methods) is static. However, the validation rules should be
determined automatically by the framework instead of being configured or hardcoded
elsewhere. On the other hand, generating validation rules during runtime unnecessarily
slows down the application. The solution is static method result compilation.

A method which generates data based on information already known at compile time
can usually be made static. Consider the following example::

	/**
	 * Returns a map of action method names and their parameters.
	 *
	 * @return array Array of method parameters by action name
	 */
	public function getActionMethodParameters() {
		$methodParameters = $this->reflectionService->getMethodParameters(get_class($this), $this->actionMethodName);
		foreach ($methodParameters as $parameterName => $parameterInfo) {
		  ...
		}
		return $methodParameters;
	}

In the example above, ``getActionMethodParameters()`` returns data needed during
runtime which could easily be pre-compiled.

By annotating the method with ``@Flow\CompileStatic`` and transforming it into a
static method which does not depend on runtime services like persistence, security
and so on, the performance in production context can be improved::

	/**
	 * Returns a map of action method names and their parameters.
	 *
	 * @param \Neos\Flow\ObjectManagement\ObjectManagerInterface $objectManager
	 * @return array Array of method parameters by action name
	 * @Flow\CompileStatic
	 */
	static protected function getActionMethodParameters($objectManager) {
		$reflectionService = $objectManager->get(\Neos\Flow\Reflection\ReflectionService::class);
		$className = get_called_class();
		$methodParameters = $reflectionService->getMethodParameters($className, get_class_methods($className));
		foreach ($methodParameters as $parameterName => $parameterInfo) {
		  ...
		}
		return $methodParameters;
	}

The results of methods annotated with ``CompileStatic`` will only be compile in
``Production`` context. When Flow is started in a different context, the method
will be executed during each run.

.. _sect-enabling-non-flow-packages:

Enabling Other Package Classes For Object Management
====================================================

As stated in the beginning of this part, all classes in packages not in one of the ``neos-*``
types is not recognized for object management by default. If you still want that you can include
those classes via configuration in settings. The configuration consists of a map of package keys to
arrays of expressions which match classes to be included. In the following example we include all
classes of the ``Acme.Objects`` package::

  Neos:
    Flow:
      object:
        includeClasses:
          'Acme.Objects' : ['.*']

.. note::
	If you use the ``includeClasses`` setting on a flow package (which is already enabled for object
	management) then only the classes that match at least one of the filter expressions are going to
	be object managed. This can also be used to remove classes inside flow packages from object
	management by specifying a non-matching expression or an empty array.

.. note::
	The static method must except exactly one argument which is the Flow
	Object Manager. You cannot use a type hint at this point (for the ``$objectManager``
	argument) because the argument passed could actually be a ``DependencyProxy`` and
	not the real ObjectManager. Please refer to the section about Lazy Dependency
	Injection for more information about ``DependencyProxy``.

.. _sect-virtual-objects:

Virtual Objects
===============

With the ``Objects.yaml`` configuration, the default behavior of classes can be changed globally. Sometimes
it can be useful to configure the same class for multiple different use cases. For example two logger implementations
that use the same instance but are configured separately.

With Flow version 6.2 and above it's possible to configure "Virtual Objects". The syntax is the same as described above
(see :ref:`sect-configuring-objects`) with two differences:

* The object name has to contain a colon (to tell it apart from regular object names)
* The ``className`` configuration is required (since it can't be inferred from the object name)

*Example: Objects.yaml for two virtual logger objects*

.. code-block:: yaml

	'Some.Package:SystemLogger':
	  className: Psr\Log\LoggerInterface
	  scope: singleton
	  factoryObjectName: Neos\Flow\Log\PsrLoggerFactoryInterface
	  factoryMethodName: get
	  arguments:
	    1:
	      value: systemLogger

	'Some.Package:SecurityLogger':
	  className: Psr\Log\LoggerInterface
	  scope: singleton
	  factoryObjectName: Neos\Flow\Log\PsrLoggerFactoryInterface
	  factoryMethodName: get
	  arguments:
	    1:
	      value: securityLogger

With those objects configured, the respective loggers can be instantiated via::

	$systemLogger = $objectManager->get('Some.Package:SystemLogger');
	$securityLogger = $objectManager->get('Some.Package:SecurityLogger');


Injecting Virtual Objects
-------------------------

To inject a Virtual Object you can simply use the ``name`` property of the ``Inject`` annotation
to refer to the Virtual Object name:

*Example: SomeClass.php*

.. code-block:: php

	class SomeClass {
	    /**
	     * @Flow\Inject(name="Some.Package:SystemLogger")
	     * @var LoggerInterface
	     */
	    protected $systemLogger;

Alternatively you can use constructor- or setter injection with a corresponding configuration:

*Example: Objects.yaml*

.. code-block:: yaml

	# ...
	'Some\Package\SomeClass':
	  properties:
	    'systemLogger':
	      object: 'Some.Package:SystemLogger'

*Example: SomeClass.php*

.. code-block:: php

	class SomeClass {

	    public function injectSystemLogger(LoggerInterface $systemLogger): void
	    {
	        $this->systemLogger = $systemLogger;
	    }


.. _Martin Fowler's article: http://martinfowler.com/articles/injection.html
.. _his blog:                http://tapestryjava.blogspot.com/2004/08/dependency-injection-mirror-of-garbage.html
.. _Hollywood Principle:     http://en.wikipedia.org/wiki/Hollywood_Principle
.. _An article:              http://www.ddj.com/dept/java/184405016
.. _Spring Framework:        http://www.springframework.org
.. _PicoContainer:           http://www.picocontainer.org
.. _interface:               http://www.php.net/manual/en/language.oop5.interfaces.php
