Simple Symfony2 / Doctrine Validation not working - symfony

This just doesn't make sense. I can't seem to get a simple Symfony2 validation working.
$insert = new MyEntity();
$insert->setTest1( 'test' );
$validator = $this->get('validator');
$errors = $validator->validate($insert);
...but $errors is always an object with an empty constraints array. It never fails the validation.
My configuration (Yaml):
MyBundle\Entity\MyEntity:
properties:
test1:
- MinLength: 10
- Email
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
test1:
type: string
length: 255
column: test_1
test2:
type: integer
column: test_2
lifecycleCallbacks: { }

You're mixing doctrine's mapping and symfony's validation in a single yml file.
The validation configuration in yml is loaded from the files:
Acme/YourBundle/Resources/config/validation.yml // YAML
Acme/YourBundle/Resources/config/validation.xml // XML
And the mapping information should be placed in one of:
Acme/YourBundle/Resources/config/doctrine/MyEntity.orm.yml // YAML
Acme/YourBundle/Resources/config/doctrine/MyEntity.orm.xml // XML
Acme/YourBundle/Resources/config/doctrine/orm/MyEntity.orm.yml // YAML
Acme/YourBundle/Resources/config/doctrine/orm/MyEntity.orm.xml // XML

Related

Empty relations when serializing with JMSSerializer

I am having troubles while writing a controller-action inside a Symfony project, that should return data (in this particular case orders of a web-shop). Yeah ... It's a kind of a REST-API. That route just get's called from some JavaScript. And the data has to be visualized on the client-side.
The Problem:
I cannot find out, why the serialization of related entities results in empty objects. In this example it is the user of an order, which is empty.
This is a sample output:
orders: [
{
id: 2,
created: '2016-05-04T11:40:27+00:00',
user: {},
}
]
When I do something like
$orders = $this->getDoctrine()->getRepository('AppBundle:Order')
->findAllCompleted();
$serializationContext->setSerializeNull(true);
$serializationContext->setGroups(['statistics']);
$json = $serializer->serialize($orders, 'json', $serializationContext);
$response = new Response($json, $statusCode, [
'Content-Type' => 'application/json',
]);
return $response;
... i get a nice JSON response from the server, but every related entity of each order, like let's say user is {} (empty).
Even if I dump the related entity before it gets serialized like so:
[...]
$myOrder = array_filter($orders, function($order) {
if ($order->getId() == 2) {
return true;
}
return false;
});
dump($myOrder[0]->getUser());
die();
... it results in an empty (unhydrated) entity.
But if I change this debugging code to:
$myOrder = array_filter($orders, function($order) {
if ($order->getId() == 2) {
return true;
}
return false;
});
dump($myOrder[0]->getUser()->getUsername());
die();
... I get a clear output (string) with the value of the username of that entity.
So I think the issue is about a non hydrated entity, and not the serializer or its wrong configuration.
How can I get the JMSSerializer to take care of the hydration of those related entities?
I didn't find any hint in the docs ...
BTW, this are the JMS entity configs of order and user.
AppBundle\Entity\User:
exclusion_policy: ALL
properties:
userMeta:
expose: true
address:
expose: true
username:
expose: true
email:
expose: true
isReseller:
expose: true
acceptPublicOrders:
expose: true
vatNumber:
expose: true
taxRate:
expose: true
AppBundle\Entity\Order:
exclusion_policy: NONE
properties:
id:
groups: ['statistics']
user:
groups: ['statistics']
configuration:
groups: ['statistics']
created:
groups: ['statistics']
invoiceItems:
groups: ['statistics']
exclude: true
I think your problem is caused by doctrine lazy loading maybe you can try to change the fetch mode of the User association to EAGER in your Order entity
#ManyToOne(targetEntity="Cart", cascade={"all"}, fetch="EAGER")
By default i think it doesn't fetch the associations unless you call it directly like you did here
dump($myOrder[0]->getUser()->getUsername());
https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-onetoone
Or this if you use DQL
14.7.6.6. Temporarily change fetch mode in DQL
http://doctrine-orm.readthedocs.io/en/latest/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql
Edit : i was wrong
I made some tests everything worked fine with lazy loading or eager until i tried with groups, even if the fields are exposed you don't use the Default group so it only take the things with the 'statistics' group on it
Try to add the default group here
$serializationContext->setGroups(['Default','statistics']);
Or add the statistics group on your user fields both worked for me

Gedmo Translatable yaml mapping

Is it possible to map Gedmo with yaml ? I'm using yaml file in my project and I would like to use Translatable from doctrine extensions but I have a problem with it.
I have something like that (one entity / one translation table) :
class CategoryTranslation extends \Gedmo\Translatable\Entity\MappedSuperclass\AbstractTranslation
{
/**
* All required columns are mapped through inherited superclass
*/
}
but, when I run "doctrine:schema:update --dump-sql" command, I've got an error :
There is no column with name 'locale' on table 'category_translation'.
I have the feeling that yaml mapping "can't see" Gedmo AbstractTranslation class...
Do you have an idea of the problem ?
Thank you !
EDIT :
To avoid discussions in comments, I post an answer.
MyProject\MyBundle\Entity\Category:
type: entity
table: category
repositoryClass: MyProject\MyBundle\Repository\CategoryRepository
gedmo:
tree:
type: nested
translation:
locale: locale
entity: MyProject\MyBundle\Entity\Translation\CategoryTranslation
fields:
label:
type: string
length: 255
gedmo:
- translatable
With this config, I had to create a Translation.CategoryTranslation.orm.yml file because there is no database migration. And, there problem is really here :
MyProject\MyBundle\Entity\Translation\CategoryTranslation:
type: entity
table: category_translation
repositoryClass: Gedmo\Translatable\Entity\Repository\TranslationRepository
indexes:
category_translation_idx:
columns: [ locale, object_class, field, foreign_key ]
id:
id:
type: integer
generator:
strategy: AUTO
fields:
locale:
type: string
length: 8
object_class:
type: string
length: 255
field:
type: string
length: 32
foreign_key:
type: string
length: 64
content:
type: text
By doing this, the database migration works. I have a new table named category_translation. But, when I try to add a new translation, there is an error in my sql request generated by doctrine. Object_class field and foreign_key are null.
Here, the SQL request generated by doctrine :
INSERT INTO category_translation (locale, object_class, field, foreign_key, content) VALUES (?, ?, ?, ?, ?)' with params [\"fr\", null, \"name\", null, \"toto\"]:\n\nSQLSTATE[23000]: Integrity constraint violation: 1048 Column 'object_class' cannot be null"}

Alice Faker library choose random from array

I am trying to generate a dummy data using AliceBundle for Symfony Framework. Everything seems to be working fine except I am looking for a way to randomly assign data from an array to a property called type. Looking at the faker library I can see that I can generate that using randomElement($array = array ('a','b','c'))
I am trying to convert that into YML and I think that is equivalent of
<randomElement(['a','b','c'])>
But this produces an error
[Nelmio\Alice\Throwable\Exception\FixtureBuilder\ExpressionLanguage\LexException]
Could not lex the value "['a'".
This is my complete yml
AppBundle\Entity\Job:
job{1..5}:
title: <jobTitle()>
description: <paragraph(3)>
length: "3_months_full_time"
type: <randomElement(['a','b','c'])>
bonus: <paragraph(3)>
expired_at: "2016-12-21"
job_user: "#emp*"
This works for me:
parameters:
profileArray: ['PUBLIC', 'PRIVATE', 'AUTHENTICATED']
JobPlatform\AppBundle\Entity\Profile:
profiles_{1..100}:
user: '#user_<current()>'
visibility: <randomElement($profileArray)>
I ended up creating a custom provider
namespace AppBundle\DataFixtures\Faker\Provider;
class JobTypeProvider
{
public static function jobType()
{
$types = array("paid", "unpaid", "contract");
$typeIndex = array_rand($types);
return $types[$typeIndex];
}
}
Add that to services.yml
app.data_fixtures_faker_provider.job_type_provider:
class: AppBundle\DataFixtures\Faker\Provider\JobTypeProvider
tags: [ { name: nelmio_alice.faker.provider } ]
And then use it in yml file
AppBundle\Entity\Job:
job{1..50}:
title: <jobTitle()>
description: <paragraph(3)>
length: <jobLength()>
job_industry: "#title*"
type: <jobType()>
bonus: <paragraph(3)>
expired_at: "2016-12-21"
job_user: "#emp*"
Notice type: , this is being generated from service now.

Symfony child entity only being validated as Type, skipping it's own validation

I'm using the Symfony Validator on it's own, without the forms component.
I have an entity which contains a child entity, currently I can validate that that field is an instance of the child entity, but I need it to also validate the child for it's constraints.
#validation.yml
# This is the entity I'm validating against, it checks the type but doesn't then validate
# it against the child entity below.
Greg\PropertyBundle\Entity\Property:
properties:
property_id:
- NotBlank: ~
- Type:
type: string
addresses:
- All:
- Type:
type: Greg\PropertyBundle\Entity\Address
# child entity
Greg\PropertyBundle\Entity\Address:
properties:
city:
- NotBlank: ~
- Type:
type: string
To call the validator I'm passing it in with DI to one of my services and doing this:
// Validate the data
$errorList = $this->validator->validate($data);
I have also tried it by passing in the following flags:
$errorList = $this->validator->validate($data, null, true, true);
By default validation is not delegated for objects in properties. If you want to invoke validation
process for children objects then you should use specific constraint "Valid".
So your validation script will be:
#validation.yml
# This is the entity I'm validating against, it checks the type but doesn't then validate
# it against the child entity below.
Greg\PropertyBundle\Entity\Property:
properties:
property_id:
- NotBlank: ~
- Type:
type: string
addresses:
- All:
- Type:
type: Greg\PropertyBundle\Entity\Address
# addresses is array of entities, so use "traverse" option to validate each entity in that array
- Valid: { traverse: true }
# child entity
Greg\PropertyBundle\Entity\Address:
properties:
city:
- NotBlank: ~
- Type:
type: string
More details about "Valid" constraint you can find here:
http://symfony.com/doc/current/reference/constraints/Valid.html

How do I set enum data type in doctrine 2

In annotation based mapping, as per the documentation of doctrine, we can do as shown below:
/** #Column(type="string", columnDefinition="ENUM('visible', 'invisible')") */
My question is how do I represent this in yaml meta data file for doctrine?
I want to do something like this:
fields:
status:
type: string
columnDefinition: ....
I am using symfony 2 as framework
Just use:
fields:
status:
type: string
columnDefinition: ENUM('visible', 'invisible')
status:
type: enum
values: ['visible', 'invisible']
https://www.doctrine-project.org/projects/doctrine1/en/latest/manual/yaml-schema-files.html#enums

Resources