Is doctrine Entity validation enough? - php

I have an Entity class which already has constrains:
/**
* #ORM\Column(type="string", length=255)
*/
private $X;
/**
* #ORM\Column(type="integer")
*/
private $Y;
In my controller i'm getting post data from form and using setMethods on entity class:
$property = new PropertyEntity();
$property->setX($request->request->get('X'));
$property->setY($request->request->get('Y'));
next step - save to db.
Do I need to do additional validation on post data ? I though I need to use validation library but i'm not sure if it will only add unnecessary overhead since "#ORM" is already form type is already doing some validation.
Any general idea how and where to write validation ?(pseudocode is enough)

Good question!
ORM mapping map the PHP class to the doctrine metadata (Model).
Assert is a mechanism to validate objects received from form (View/Controller).
This means that you can use assert on objects that are not entities or that you cannot use a mapped field in your formType
You can make validation in the annotation of the field. example:
/**
* #Assert\NotBlank
* #ORM\Column(type="string", length=255)
*/
private $X;
/**
* #Assert\NotBlank
* #ORM\Column(type="integer")
*/
private $Y;
Don't forget to add:
use Symfony\Component\Validator\Constraints as Assert;
More validation constraints are in this link:
https://symfony.com/doc/current/validation.html#basic-constraints

Related

Symfony Doctrine ORM not a valid entity or mapped super class

I'm just making a new Entity as usual, but something goes wrong and console report this error and I couldn't generate the entity setter/getter:
[Doctrine\ORM\Mapping\MappingException]
Class "AppBundle\Entity\Admin_Actions" is not a valid entity or mapped super class.
Here is my Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="admin_actions")
*/
class Admin_Actions
{
/**
* #ORM\Column(name="id",type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(name="uid",type="string",length=100)
*/
private $uid;
/**
* #ORM\Column(name="type",type="integer")
*/
private $type;
/**
* #ORM\Column(name="linedate",type="datetime")
*/
private $linedate;
}
If I do doctrine:mapping:info:
[Exception]
You do not have any mapped Doctrine ORM entities according to the current configuration. If you have
entities or mapping files you should check your mapping configuration for errors.
I've just waste an hour trying to investigate the problem and I've already tried to rewrite it from new but I'm missing something. What's wrong with this?
May be datetime field has same name as function/implementation in doctrine, I have got same mistake by naming a table "condition" which may be condition function in MySql query

Use UniqueEntity on a Gedmo\Blameable field

I am using Gedmo extension in addition with Symfony 3.2 and Doctrine 2.5.6 and I'm encountering an issue. I can't make Gedmo\Blameable and UniqueEntity constraint work together. Indeed, the blamed field is still null at validation time. Is there any way to make it work or a possible work-around ?
Here is my entity
/**
* #UniqueEntity(
* fields={"author", "question"},
* errorPath="question",
* message="This author already has an answer for that Question"
* )
* #ORM\Entity
*/
class TextAnswer
{
/**
* #ORM\ManyToOne(targetEntity="User")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
* #Gedmo\Blameable(on="create")
*/
private $author;
/**
* #Assert\NotNull()
* #ORM\ManyToOne(targetEntity="Question", inversedBy="textAnswers")
* #ORM\JoinColumn(name="question_id", referencedColumnName="id")
*/
private $question;
}
Thanks
EDIT : SOLUTION
Rather than manually setting the user (which removes Gedmo\Blameable interests), I created my own entity validator.
I give it doctrine and token storage as arguments so it can make a query on db to validate my criteria with the currently connected user (that will be later used by Gedmo\Blameable).
The BlameableListener is invoked during the Doctrine's flush operation, which normally happens after the entity has been validated. That's why $author is null at validation time.
The most straightforward workaround is to set $author yourself beforehand.

Doctrine/Symfony: Entity with non-mapped property

How can I add a property to an Entity Class, which should not be mapped to the database?
I need the property for a temporary value. Therefore the property should not be fetched from or persisted to the database. it neither should be a sql-calculated value, i need to set (and get) this within php code only.
Writing a property without annotation should not be linked to your Database as example of an entity User.
class User
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="array")
*/
protected $username;
protected $notPersistedProperty
}
Hope this helped.

Best practise for placing custom Entity methods in Symfony

I'm creating Symfony project. And now I'm trying to find best practice for adding custom methods.. What is yours?
Visual explanation:
users table
id | name | surname
---+------+--------
1 | John | Smith
2 | Matt | Malone
Entity\User.php
namespace TestBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;
/**
* User
* #ORM\Table(name="users")
* #ORM\Entity
*/
class User
{
/**
* #ORM\Column(name="id", type="string", length=36)
* #ORM\Id
* #ORM\GeneratedValue(strategy="UUID")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #ORM\Column(name="surname", type="string", length=255, nullable=true)
*/
private $surname;
/**
* OneToMany
*/
private $userCompanies;
{{ Setters and Getters }}
}
Where I should store custom method, like:
function getFullName()
{
return sprintf("%s %s", $this->getName(), $this->getSurname());
}
Or more complex:
function getCurrentUserCompany()
{
foreach ($this->getUserCompanies() as $company) {
if ($company->isActive()) {
return $company;
}
}
return null;
}
Please note, that all data returned via JSON
So far I tried extending class, but annotations not working as expected. Placing custom methods in same file looks trashy, since there will be more than one of them.
But.. but if there is repositoryClass - maby there is place for custom methods as well?
Thanks!
If it's about methods that are used mainly for display purposes then they are very similar to the getters, in my opinion they best fit is in the Entity itself, so inside your User.php class.
The repository is for defining methods for getting the entity from your storage level (DB, cache...), but the view level (your twig) should take the data from the entity itself.
If you need something more complicated or you need to reuse it, like a date filter, then it's better to create a Twig extension.
Methods like that belong to entity class and there is no reason to split code. If many entity classes share some methods, you can always create shared base abstract class or trait for them.
If you really want separated files for sake of your aesthetic, then use traits, but remember that it's not proper and conventional use of them.

Symfony2 Override Constraints

I have BaseEntity class:
class BaseEntity
{
/**
* The name.
*
* #var string
*
* #ORM\Column(name="name", type="string", length=255, unique=true, nullable=false)
* #Assert\Length(min=2, max=255, minMessage="default.name.short", maxMessage="default.name.long")
* #Assert\NotBlank(message = "default.name.not_blank")
*/
private $name;
}
and
class UserEntity extends BaseEntity
{
/**
* {#inheritDoc}
*
* #Assert\Length(min=2, max=255, minMessage="user.name.short", maxMessage="default.name.long")
* #Assert\NotBlank(message = "user.name.not_blank")
*/
private $name;
}
Now, When I post a new UserEntity into the form with long or short name Symfony gives me 2 errors: (for long:)
default.name.long
user.name.long
But I want it to show only ONE error, so :
- user.name.long
e.g. I want to override, but do not add another one
I think what you are looking for a validator group. So you can split up you validation rules into groups.
There is a excellent documentation about this feature:
http://symfony.com/doc/current/validation/groups.html
Maybe a Custom Validation Constraint could help you if you could (depending of your application logic) remove those two validations and make your own.
Something like this maybe?
http://symfony.com/doc/current/cookbook/validation/custom_constraint.html
If you're happy to set up at least some of your validation rules via a YAML file rather than annotations, you can override the base class's validation settings without needing to edit the class file itself.
Your YAML file would look something like this and would need to be in a location like src/YourApp/YourBundle/Resources/config/validation.yml to be picked up automatically:
BaseEntity:
properties:
name:
- NotBlank:
message: user.name.not_blank
- Length:
min: 2
minMessage: user.name.short
max: 255
maxMessage: default.name.long
If you want to put your validation file in a non-standard location, see https://stackoverflow.com/a/24210501/328817

Categories