Skip to content

Commit

Permalink
Migrate more documentation towards attributes
Browse files Browse the repository at this point in the history
The previous rework missed some details / left the documentation in an
inconsistent state. Searching for "annotation" case insensitively allows
to find discrepancies and forgotten things.
  • Loading branch information
greg0ire committed Oct 19, 2022
1 parent 06eafd8 commit 151f0c7
Show file tree
Hide file tree
Showing 19 changed files with 90 additions and 135 deletions.
Expand Up @@ -32,59 +32,39 @@ The entity class:
namespace Geo\Entity;
/**
* @Entity
*/
use Geo\ValueObject\Point;
#[Entity]
class Location
{
/**
* @Column(type="point")
*
* @var \Geo\ValueObject\Point
*/
private $point;
/**
* @Column(type="string")
*
* @var string
*/
private $address;
/**
* @param \Geo\ValueObject\Point $point
*/
public function setPoint(\Geo\ValueObject\Point $point)
#[Column(type: 'point')]
private Point $point;
#[Column()]
private string $address;
public function setPoint(Point $point): void
{
$this->point = $point;
}
/**
* @return \Geo\ValueObject\Point
*/
public function getPoint()
public function getPoint(): Point
{
return $this->point;
}
/**
* @param string $address
*/
public function setAddress($address)
public function setAddress(string $address): void
{
$this->address = $address;
}
/**
* @return string
*/
public function getAddress()
public function getAddress(): string
{
return $this->address;
}
}
We use the custom type ``point`` in the ``@Column`` docblock annotation of the
We use the custom type ``point`` in the ``#[Column]`` attribute of the
``$point`` field. We will create this custom mapping type in the next chapter.

The point class:
Expand All @@ -97,29 +77,18 @@ The point class:
class Point
{
/**
* @param float $latitude
* @param float $longitude
*/
public function __construct($latitude, $longitude)
{
$this->latitude = $latitude;
$this->longitude = $longitude;
public function __construct(
private float $latitude,
private float$longitude,
) {
}
/**
* @return float
*/
public function getLatitude()
public function getLatitude(): float
{
return $this->latitude;
}
/**
* @return float
*/
public function getLongitude()
public function getLongitude(): float
{
return $this->longitude;
}
Expand Down
Expand Up @@ -29,15 +29,15 @@ implement the ``NotifyPropertyChanged`` interface from the
<?php
use Doctrine\Persistence\NotifyPropertyChanged;
use Doctrine\Persistence\PropertyChangedListener;
abstract class DomainObject implements NotifyPropertyChanged
{
private $listeners = array();
public function addPropertyChangedListener(PropertyChangedListener $listener) {
$this->listeners[] = $listener;
}
/** Notifies listeners of a change. */
protected function onPropertyChanged($propName, $oldValue, $newValue) {
if ($this->listeners) {
Expand All @@ -55,12 +55,12 @@ listeners:
.. code-block:: php
<?php
// Mapping not shown, either in annotations, xml or yaml as usual
// Mapping not shown, either in attributes, annotations, xml or yaml as usual
class MyEntity extends DomainObject
{
private $data;
// ... other fields as usual
public function setData($data) {
if ($data != $this->data) { // check: is it actually modified?
$this->onPropertyChanged('data', $this->data, $data);
Expand All @@ -73,5 +73,3 @@ The check whether the new value is different from the old one is
not mandatory but recommended. That way you can avoid unnecessary
updates and also have full control over when you consider a
property changed.


4 changes: 1 addition & 3 deletions docs/en/cookbook/strategy-cookbook-introduction.rst
Expand Up @@ -154,7 +154,7 @@ As you can see, we have a method "setBlockEntity" which ties a potential strateg
* This var contains the classname of the strategy
* that is used for this blockitem. (This string (!) value will be persisted by Doctrine ORM)
*
* This is a doctrine field, so make sure that you use an @column annotation or setup your
* This is a doctrine field, so make sure that you use an @[Column] attribute or setup your
* yaml or xml files correctly
* @var string
*/
Expand Down Expand Up @@ -251,5 +251,3 @@ This might look like this:
In this example, even some variables are set - like a view object
or a specific configuration object.


25 changes: 10 additions & 15 deletions docs/en/cookbook/validation-of-entities.rst
Expand Up @@ -36,12 +36,12 @@ are allowed to:
public function assertCustomerAllowedBuying()
{
$orderLimit = $this->customer->getOrderLimit();
$amount = 0;
foreach ($this->orderLines as $line) {
$amount += $line->getAmount();
}
if ($amount > $orderLimit) {
throw new CustomerOrderLimitExceededException();
}
Expand All @@ -53,20 +53,17 @@ code, enforcing it at any time is important so that customers with
a unknown reputation don't owe your business too much money.

We can enforce this constraint in any of the metadata drivers.
First Annotations:
First Attributes:

.. code-block:: php
<?php
/**
* @Entity
* @HasLifecycleCallbacks
*/
#[Entity]
#[HasLifecycleCallbacks]
class Order
{
/**
* @PrePersist @PreUpdate
*/
#[PrePersist, PreUpdate]
public function assertCustomerAllowedBuying() {}
}
Expand Down Expand Up @@ -101,19 +98,17 @@ validation callbacks.
<?php
class Order
{
/**
* @PrePersist @PreUpdate
*/
#[PrePersist, PreUpdate]
public function validate()
{
if (!($this->plannedShipDate instanceof DateTime)) {
throw new ValidateException();
}
if ($this->plannedShipDate->format('U') < time()) {
throw new ValidateException();
}
if ($this->customer == null) {
throw new OrderRequiresCustomerException();
}
Expand Down
11 changes: 6 additions & 5 deletions docs/en/reference/advanced-configuration.rst
Expand Up @@ -12,6 +12,7 @@ steps of configuration.
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AttributeDriver;
use Doctrine\ORM\ORMSetup;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
Expand All @@ -28,7 +29,7 @@ steps of configuration.
$config = new Configuration;
$config->setMetadataCache($metadataCache);
$driverImpl = ORMSetup::createDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCache($queryCache);
$config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
Expand Down Expand Up @@ -124,18 +125,18 @@ used in the examples. For information on the usage of the
AnnotationDriver, XmlDriver or YamlDriver please refer to the dedicated
chapters ``Annotation Reference``, ``XML Mapping`` and ``YAML Mapping``.

The annotation driver can be configured with a factory method on
The attribute driver can be configured with a factory method on
the ``Doctrine\ORM\Configuration``:

.. code-block:: php
<?php
use Doctrine\ORM\ORMSetup;
$driverImpl = ORMSetup::createDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
$driverImpl = new AttributeDriver(['/path/to/lib/MyProject/Entities']);
$config->setMetadataDriverImpl($driverImpl);
The path information to the entities is required for the annotation
The path information to the entities is required for the attribute
driver, because otherwise mass-operations on all entities through
the console could not work correctly. All of metadata drivers
accept either a single directory as a string or an array of
Expand All @@ -152,7 +153,7 @@ Metadata Cache (***RECOMMENDED***)
$config->getMetadataCache();
Gets or sets the cache adapter to use for caching metadata
information, that is, all the information you supply via
information, that is, all the information you supply via attributes,
annotations, xml or yaml, so that they do not need to be parsed and
loaded from scratch on every single request which is a waste of
resources. The cache implementation must implement the PSR-6
Expand Down
4 changes: 2 additions & 2 deletions docs/en/reference/association-mapping.rst
Expand Up @@ -83,8 +83,8 @@ A many-to-one association is the most common association between objects. Exampl
The above ``#[JoinColumn]`` is optional as it would default
to ``address_id`` and ``id`` anyways. You can omit it and let it
use the defaults.
Likewise, inside the ``#[ManyToOne]`` annotation you can omit the
``targetEntity`` attribute and it will default to ``Address``.
Likewise, inside the ``#[ManyToOne]`` attribute you can omit the
``targetEntity`` argument and it will default to ``Address``.

Generated MySQL Schema:

Expand Down
29 changes: 15 additions & 14 deletions docs/en/reference/basic-mapping.rst
Expand Up @@ -50,8 +50,9 @@ mapping metadata:
- :doc:`PHP code <php-mapping>`
- :doc:`YAML <yaml-mapping>` (deprecated and will be removed in ``doctrine/orm`` 3.0.)

This manual will usually show mapping metadata via docblock annotations, though
many examples also show the equivalent configuration in YAML and XML.
This manual will usually show mapping metadata via attributes, though
many examples also show the equivalent configuration in annotations,
YAML and XML.

.. note::

Expand Down Expand Up @@ -157,10 +158,10 @@ Property Mapping

The next step is mapping its properties to columns in the table.

To configure a property use the ``Column`` docblock annotation. The ``type``
attribute specifies the :ref:`Doctrine Mapping Type <reference-mapping-types>`
to use for the field. If the type is not specified, ``string`` is used as the
default.
To configure a property use the ``Column`` attribute. The ``type``
argument specifies the :ref:`Doctrine Mapping Type
<reference-mapping-types>` to use for the field. If the type is not
specified, ``string`` is used as the default.

.. configuration-block::

Expand Down Expand Up @@ -360,8 +361,7 @@ Identifiers / Primary Keys
--------------------------

Every entity class must have an identifier/primary key. You can select
the field that serves as the identifier with the ``@Id``
annotation.
the field that serves as the identifier with the ``#[Id]`` attribute.

.. configuration-block::

Expand Down Expand Up @@ -437,7 +437,7 @@ Here is the list of possible generation strategies:
thus generated) by your code. The assignment must take place before
a new entity is passed to ``EntityManager#persist``. NONE is the
same as leaving off the @GeneratedValue entirely.
- ``CUSTOM``: With this option, you can use the ``@CustomIdGenerator`` annotation.
- ``CUSTOM``: With this option, you can use the ``#[CustomIdGenerator]`` attribute.
It will allow you to pass a :doc:`class of your own to generate the identifiers.<_annref_customidgenerator>`

Sequence Generator
Expand Down Expand Up @@ -522,11 +522,12 @@ need to access the sequence once to generate the identifiers for
Composite Keys
~~~~~~~~~~~~~~

With Doctrine ORM you can use composite primary keys, using ``@Id`` on more then
one column. Some restrictions exist opposed to using a single identifier in
this case: The use of the ``@GeneratedValue`` annotation is not supported,
which means you can only use composite keys if you generate the primary key
values yourself before calling ``EntityManager#persist()`` on the entity.
With Doctrine ORM you can use composite primary keys, using ``#[Id]`` on
more than one column. Some restrictions exist opposed to using a single
identifier in this case: The use of the ``#[GeneratedValue]`` attribute
is not supported, which means you can only use composite keys if you
generate the primary key values yourself before calling
``EntityManager#persist()`` on the entity.

More details on composite primary keys are discussed in a :doc:`dedicated tutorial
<../tutorials/composite-primary-keys>`.
Expand Down
7 changes: 3 additions & 4 deletions docs/en/reference/caching.rst
Expand Up @@ -109,8 +109,9 @@ Metadata Cache
~~~~~~~~~~~~~~

Your class metadata can be parsed from a few different sources like
YAML, XML, Annotations, etc. Instead of parsing this information on
each request we should cache it using one of the cache drivers.
YAML, XML, Attributes, Annotations etc. Instead of parsing this
information on each request we should cache it using one of the cache
drivers.

Just like the query and result cache we need to configure it
first.
Expand Down Expand Up @@ -199,5 +200,3 @@ not letting your users' requests populate the cache.

You can read more about cache slams
`in this blog post <http://notmysock.org/blog/php/user-cache-timebomb.html>`_.


6 changes: 3 additions & 3 deletions docs/en/reference/configuration.rst
Expand Up @@ -55,7 +55,7 @@ access point to ORM functionality provided by Doctrine.
'dbname' => 'foo',
);
$config = ORMSetup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$config = ORMSetup::createAttributeMetadataConfiguration($paths, $isDevMode);
$entityManager = EntityManager::create($dbParams, $config);
.. note::
Expand Down Expand Up @@ -83,9 +83,9 @@ Or if you prefer YAML:
.. note::
If you want to use yml mapping you should add yaml dependency to your `composer.json`:

::

"symfony/yaml": "*"

Inside the ``ORMSetup`` methods several assumptions are made:
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/events.rst
Expand Up @@ -980,7 +980,7 @@ Load ClassMetadata Event

``loadClassMetadata`` - The ``loadClassMetadata`` event occurs after the
mapping metadata for a class has been loaded from a mapping source
(annotations/xml/yaml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
(attributes/annotations/xml/yaml) in to a ``Doctrine\ORM\Mapping\ClassMetadata`` instance.
You can hook in to this process and manipulate the instance.
This event is not a lifecycle callback.

Expand Down

0 comments on commit 151f0c7

Please sign in to comment.