graphaware / neo4j-php-ogm

Neo4j Object Graph Mapper for PHP
MIT License
153 stars 55 forks source link

Unique annotation #119

Open Sraime opened 7 years ago

Sraime commented 7 years ago

Hello,

It is plan to add a Unique annotation like Doctrine ? For example :

/**
 * @Column(type="string",  unique=true)
 */
protected $username;

It could be very useful !

ikwattro commented 7 years ago

Can you explain what usefulness you would expect ?

Sraime commented 7 years ago

In many applications the email must be unique. Two users with the same email is impossible.
So when a new user log on, we have to check if the email is already use by another. Actually when can do this in a Form object (UserType extends AbstractType for exemple) with the SUBMIT event listener.

Here is an example :

<?php
class UserType extends AbstractType
{
    private $user_repo;

    public function __construct(EntityManager $em)
    {
        $this->user_repo = $em->getRepository(User::class);
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $encoder = $this->encoder;
        $builder
            ->add('name')
            ->add('email', EmailType::class)
            ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event){
                $email = $event->getForm()->get('email')->getData();
                $db_user = $this->user_repo->findBy(['email' => $email]);
                if(!empty($db_user))
                    $event->getForm()->get('email')
                        ->addError(new FormError("user.email.unique"));
            })
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User'
        ));
    }
}

That's could be interesting if we can indicate that the property is unique with annotations. And then when the form check if the email is valid an exception occur and the form is not valid.

JoeThielen commented 7 years ago

Is @Sraime talking about unique constraints?

Like this in Cypher:

CREATE CONSTRAINT ON (entity:Entity) ASSERT entity.uuid IS UNIQUE;

I initialize these manually in my project, but yeah, it'd be nice to have them done automatically. However, I'm not entirely sure how the OGM would do this, as I would assume there'd be a performance issue with it having to create these all the time, or re-try. Unless it could do some kind of check beforehand to see if they already exist. I'm not far enough along in Cypher to know if this is possible or not.

ikwattro commented 7 years ago

So excepting for the ogm being able to parse all models and create them, I don't see the point. In fact the unique parameter in the Column annotation of doctrine uses the dbal layer internally, which is just used for creating the database schema.

http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-representation.html

Also, php being what it is, all metadata about the schema knowledge is completely killed after the request, in contrary to java for eg.

On another side, an "index" annotation property could be more useful as it can be used as index hint during generated queries by the ogm.

As of now, this would be post-ga-release, as there is nothing really complicated to create indexes and constraints in cypher and I prefer to prioritize other features. You can also handle this by trying to flush and catching UniqueConstraintViolationExceptions.