-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[WIP] Documenting the Validator component #3710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Validator | ||
========= | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
introduction | ||
resources |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
.. index:: | ||
single: Validator | ||
single: Components; Validator | ||
|
||
The Validator Component | ||
======================= | ||
|
||
The Validator component provides tools to validate values following the | ||
`JSR-303 Bean Validation specification`_. | ||
|
||
Installation | ||
------------ | ||
|
||
You can install the component in 2 different ways: | ||
|
||
* :doc:`Install it via Composer </components/using_components>` (``symfony/validator`` on `Packagist`_); | ||
* Use the official Git repository (https://github.com/symfony/Validator). | ||
|
||
Usage | ||
----- | ||
|
||
The Validator component allows you to use very advanced validation rules, but | ||
it is also really easy to do easy validation tasks. For instance, if you want | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say "do easy validation tasks with it"... Don´t you think the sentence is a bit weird right now? |
||
to validate a string is at least 10 character long, the only code you need is:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn´t it be validate that a string...? |
||
|
||
use Symfony\Component\Validator\Validation; | ||
use Symfony\Component\Validator\Constraints\Length; | ||
|
||
$validator = Validation::createValidator(); | ||
|
||
$violations = $validator->validateValue('Bernhard', new Length(array('min' => 10))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would be good to put an example that fails to show some more detail on the output There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The string is 8 characters long, while the constraints expects a minimum of 10 character. So it already fails. However, I agree that we should put some "show error" logic in here (I copied this example from the README). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually, it's already in there.... |
||
|
||
if (0 !== count($violations)) { | ||
// there are errors, now you can show them | ||
foreach ($violations as $violation) { | ||
echo $violation->getMessage().'<br>'; | ||
} | ||
} | ||
|
||
Retrieving a Validator Instance | ||
------------------------------- | ||
|
||
The :class:`Symfony\\Component\\Validator\\Validator` class is the main access | ||
point of the Validator component. To create a new instance of this class, it | ||
is recommend to use the :class:`Symfony\\Component\Validator\Validation` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is recommended to use |
||
class. | ||
|
||
You can get a very basic ``Validator`` by calling | ||
:method:`Validation::createValidator() <Symfony\\Component\\Validator\\Validation::createValidator>`:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidator(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you please provide a tip saying how it is done in symfony or maybe the service factory is shared but each time it creates a validator or how it is done, would be a good complement. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe let's also mention what the deps that configure a validator are: public function __construct(
MetadataFactoryInterface $metadataFactory,
ConstraintValidatorFactoryInterface $validatorFactory,
TranslatorInterface $translator,
$translationDomain = 'validators',
array $objectInitializers = array()
) |
||
|
||
The created validator can be used to validate strings, array, numbers, but it | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. arrays instead of array |
||
can't validate classes. To be able to do that, you have to configure the ``Validator`` | ||
class. To do that, you can use the :class:`Symfony\\Component\\Validator\\ValidatorBuilder`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To do that is said twice... I am not native but what about something like "In order to achieve that" |
||
This class can be retrieved by using the | ||
:method:`Validation::createValidatorBuilder() <Symfony\\Component\\Validator\\Validation::createValidatorBuilder>` | ||
method:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
// ... build a custom instance of the Validator | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better than ... is to add a simple example There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as you don't know what it does, I don't think it's valuable at this point. |
||
->getValidator(); | ||
|
||
What things you can configure will be documented in the following sections. | ||
|
||
Sections | ||
-------- | ||
|
||
* :doc:`/components/validator/resources` | ||
* :doc:`/components/validator/metadata` | ||
* :doc:`/components/validator/validating_values` | ||
|
||
.. _`JSR-303 Bean Validation specification`: http://jcp.org/en/jsr/detail?id=303 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
.. index:: | ||
single: Validator; Loading Resources | ||
|
||
Loading Resources | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A better name would be Resources are loaded to know the constraints, not the opposite. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had a discussion about this myself too :) I want to have a clear split in the documention:
I think "Mapping Constraints" covers part 1 and 2, so it is not a clear split. "Loading Resources", on its way is maybe too specific. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree with @wouterj it makes sense, i guess he still needs to complete the PR to see the second part more clearly |
||
================= | ||
|
||
The Validator uses metadata to validate a value. This metadata defines how a | ||
class, array or any other value should be validated. When validating a class, | ||
each class contains its own specific metadata. When validating another value, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The metadata can also be passed to the validate methods There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not when validating a class |
||
the metadata must be passed to the validate methods. | ||
|
||
Class metadata should be defined somewhere in a configuration file, or in the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should -> can There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well, it should be defined in a configuration file or the object isn't validated :) |
||
class itself. The ``Validator`` needs to be able to retrieve this metadata | ||
from the file or class. To do that, it uses a set of loaders. | ||
|
||
.. seealso:: | ||
|
||
You'll learn how to define the metadata in :doc:`metadata`. | ||
|
||
The StaticMethodLoader | ||
---------------------- | ||
|
||
The most basic loader is the | ||
:class:`Symfony\\Component\\Validator\\Mapping\\Loader\\StaticMethodLoader`. | ||
This loader will call a static method of the class in order to get the | ||
metadata for that class. The name of the method is configured using the | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addMethodMapping` | ||
method of the Validator builder:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
->addMethodMapping('loadValidatorMetadata') | ||
->getValidator(); | ||
|
||
Now, the retrieved ``Validator`` tries to find the ``loadValidatorMetadata()`` | ||
method of the class to validate to load its metadata. | ||
|
||
.. tip:: | ||
|
||
You can call this method multiple times to add multiple supported method | ||
names. You can also use | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addMethodMappings` | ||
to set an array of supported method names. | ||
|
||
The FileLoaders | ||
--------------- | ||
|
||
The component also provides 2 file loaders, one to load Yaml files and one to | ||
load XML files. Use | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addYamlMapping` or | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addXmlMapping` to | ||
configure the locations of these files:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
->addYamlMapping('config/validation.yml') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe let's go with the example of the min length and display what is inside the config/validation.yml in terms of this example, i think it should help readers a lot to get up to following the documentation with this example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that'll be in the next chapter (as said in the intro...) |
||
->getValidator(); | ||
|
||
.. tip:: | ||
|
||
Just like with the method mappings, you can also use | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addYamlMappings` and | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::addXmlMappings` | ||
to configure an array of file paths. | ||
|
||
The AnnotationLoader | ||
-------------------- | ||
|
||
At last, the component provides an | ||
:class:`Symfony\\Component\\Validator\\Mapping\\Loader\\AnnotationLoader`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe let's add a note that it works together with the reader and the loader just loads the annotations but does not read them, for that it needs that collaborator |
||
This loader uses an annotation reader to parse the annotations of a class. | ||
Annotations are placed in doc block comments (`/** ... */`) and start with an | ||
``@``. For instance:: | ||
|
||
// ... | ||
|
||
/** | ||
* @Assert\NotBlank() | ||
*/ | ||
protected $name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why protected? is this how all examples are provided in the documentation? just curious since i recently saw a note on changing visibility in other parts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I always use protected when writing the documentation. We might create a normalization PR to fix that though :) |
||
|
||
To enable the annotation loader, call the | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::enableAnnotationMapping` | ||
method. It takes an optional annotation reader instance, which defaults to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it will give an error if the dependency is not required explicitly as it is a suggested dependency when used standalone https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/composer.json#L28 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so maybe let's add a note that this must be specified in their project root composer.json , oh sorry just saw the thing below, nevermind 👶 |
||
``Doctrine\Common\Annotations\AnnotationReader``:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
->enableAnnotationMapping() | ||
->getValidator(); | ||
|
||
To disable the annotation loader after it was enabled, call | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::disableAnnotationMapping`. | ||
|
||
.. note:: | ||
|
||
In order to use the annotation loader, you should have installed the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sentence sounds weird to me, I would say you should have xxx and yyy packages installed from Packagist, but again I am not native :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I'm not a native either, but the current thing sounds better to me. What's the correct way @weaverryan ? :) |
||
``doctrine/annotations`` and ``doctrine/cache`` packages from Packagist. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i wonder if the autoload.php for some projects is still needed to load the annotation reader, or if any comment should be made here, just to ensure or avoid some pitfalls for not being able to make it work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good idea! |
||
Using Multiple Loaders | ||
---------------------- | ||
|
||
The component provides a | ||
:class:`Symfony\\Component\\Validator\\Mapping\\Loader\\LoaderChain` class to | ||
chain multiple loaders. This means you can configure as many loaders as you | ||
want at the same time. | ||
|
||
The ``ValidatorBuilder`` will already take care of this when you configure | ||
multiple mappings:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
->enableAnnotationMapping() | ||
->addMethodMapping('loadValidatorMetadata') | ||
->addXmlMapping('config/validation.xml') | ||
->getValidator(); | ||
|
||
Caching | ||
------- | ||
|
||
Using many loaders to load metadata from different places is very easy when | ||
creating the metadata, but it can easily slow down your application since each | ||
file needs to be parsed, validated and converted to a | ||
:class:`Symfony\\Component\\Validator\\Mapping\\ClassMetadata` instance. To | ||
solve this problems, you can configure a cacher which will be used to cache | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should just be cache and no cacher but i give you the reasons sometimes the classes are not named Cacher There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. problems -> problem There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's still a cacher. We don't talk about the name here, just what it does. My name is Wouter, yet I'm still a person... In the same way, something called YamlFile can be a cacher. And using "cache" here seems like we configure the cache system behind it, strictly spoken we configure the adapter. |
||
the ``ClassMetadata`` after it was loaded. | ||
|
||
The Validator component comes with a | ||
:class:`Symfony\\Component\\Validator\\Mapping\\Cache\\ApcCache` | ||
implementation. You can easily create other cachers by creating a class which | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cachers by implementing :class... |
||
implements :class:`Symfony\\Component\\Validator\\Mapping\\Cache\\CacheInterface`. | ||
|
||
.. note:: | ||
|
||
The loaders already use a singleton load mechanism. That means that the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means instead of that means? |
||
loaders will only load and parse a file once and put that in a property, | ||
which will then be used the next time it is asked for metadata. However, | ||
the Validator still needs to merge all metadata of one class from every | ||
loader when it is requested. | ||
|
||
To set a cacher, call the | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::setMetadataCache` of | ||
the Validator builder:: | ||
|
||
use Symfony\Component\Validator\Validation; | ||
use Symfony\Component\Validator\Mapping\Cache\ApcCache; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the doctrine cache, is that by default? what is it used for and the differences between it and the apc cache. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doctrinecache is integrated in Symfony 2.5 (see also the PR description) |
||
|
||
$validator = Validation::createValidatorBuilder() | ||
// ... add loaders | ||
->setMetadataCache(new ApcCache('some_apc_prefix')); | ||
->getValidator(); | ||
|
||
Using a Custom MetadataFactory | ||
------------------------------ | ||
|
||
All loaders and the cacher are passed to an instance of | ||
:class:`Symfony\\Component\\Validator\\Mapping\\ClassMetadataFactory`. This | ||
class is responsible for creating a ``ClassMetadata`` instance from all the | ||
configured resources. | ||
|
||
You can also use a custom metadata factory implementation by creating a class | ||
which implements | ||
:class:`Symfony\\Component\\Validator\\MetadataFactoryInterface`. You can set | ||
this custom implementation using | ||
:method:`Symfony\\Component\\Validator\\ValidatorBuilder::setMetadataFactory`:: | ||
|
||
use Acme\Validation\CustomMetadataFactory; | ||
use Symfony\Component\Validator\Validation; | ||
|
||
$validator = Validation::createValidatorBuilder() | ||
->setMetadataFactory(new CustomMetadataFactory(...)); | ||
->getValidator(); | ||
|
||
.. caution:: | ||
|
||
Since you are using a custom metadata factory, you can't configure loaders | ||
and cachers using the ``add*Mapping()`` methods anymore. You now have to | ||
inject them into your custom metadata factory yourself. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we doing everywhere the https:// and not the git@github.com? just curious
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
git@github.com
requires setting up SSH for your account, which does not provide any value when accessing public reposiitories in a read-only way (it used to be reserved to collaborators btw, but I think this has changed)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah and it is far a better practice to get people into contributing and learning. We shouldn't assume all are read-only people 👶
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the component repos are read-only, so it's only for read-only people. And if you want to contribute, you look into the contributing docs and not this docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the https url is not a read-only URL either (and anyway, even contributors should not push to the symfony repo directly but to their fork, as everything goes through PRs even for the core team)