symfony route annotation requirements constraints - symfony

Here is the simple symfony Route:
/**
* #Route("/test/{param}", requirements={"param": "(one|two)"})
*/
But how can I set dynamic requirements from the array or entity feature like:
/**
* #Route("/test/{param}", requirements={"param": "array or entity"})
*/
p.s. the problem appears about the same Routes like /products/{vendors} and /products/{models}. I want to catch valid route by the requirements of the route.
thanks in advance)

You cannot do that with requirements as they are just regular expressions, so they cannot detect things like the type of the parameter. In fact I believe there is no way to achieve what you want to do: how would you "send" an entity or an array in a URL? If you are using parameter converters, then the requirements should refer to the original, not converted, URL

I beleive next annotation will work:
/**
* #Route("/test/{param}", requirements={"param" = "one|two"})
*/

Related

Entity Id validation

I am writing REST API, where resources are entities. There is a problem with Id field, which has NoBlank and NotNull constraints (which are logical) when creating new entity - obviously a new entity has no Id before writing to DB. However validation component of course says the entity is not valid. How to overcome this issue without removing the constraints from the Id field?
In my opinion you shouldn't have a constraint on your id.
Url of create should be [POST]/resource and url of edit should be [PUT]/resource/{id}.
(Or POST/PATCH depending on how strictly you are doing rest HTTP methods)
THis way the id is always mandatory.
If you don't want this routing logic, you can use validation groups
/**
* #Assert\NotNull(groups={"create"})
*/
private $id;
/**
* #Assert\NotNull(groups={"create","edit"})
*/
private $whatever;

Symfony Login form with existing user class

I'm trying to use (and understand) how Security works in Symfony. I've created a login form and it works with hard-coded users.
Now I want to use an existing user table in my database. The table has all the requiered fields but with different column names. The entity also exists, also with different names (for example "customUserId" instead of "id").
Something like (with "MAGIC_MAPPING"):
/**
* #ORM\Table(name="custom_user_table")
* #ORM\Entity
*/
class User implements UserInterface, \Serializable
{
/**
* #ORM\Column(name="customUserId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #MAGIC_MAPPING so it links this to the mandatory "id" field
*/
private $customUserId;
...
}
Is there a way to map my existing fields so Symfony uses them for login purpose? Or at least can I make it work without changing my database structure (only the entity class)?
I've tried seleveral actions, from this forum and from Symfony documentation, but it always ends with ugly error I can't fix.
Any idea or lead? Thanks a lot for your help, I've been struggling on this for several hours now...
You have to change the providers configuration inside the security.yml file
here is an example, i use the email field from my administrator entity, I think you can do the same with your entity
providers:
administrator:
entity: { class: Entity:Administrator, property: email }
Try changing the ORM file of that table.
create an ORM file using Command promt.
then edit the orm file .
<mapped-superclass name="FOS\UserBundle\Entity\User" table="your_table_name">
/.../
</mapped>
Benoît 's answer help me figure it out. I gave too much attention to Symfony documentation's creation process that I forgot the essential: the UserInterface. No need to map anything, just implement this interface and defined methods like:
public function getUsername() {
return $this->customLogin;
}
Then update the provider configuration (thanks Benoit):
providers:
db_sam_provider:
entity:
class: AppBundle:User
property: customLogin
The other parts are conform to Symfony documentation: here and here

Doctrine2: Unable to override generated value strategy?

I have a an entity with an ID as such:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
I'm migrating data into this entity, and want to preserve existing keys. I looked at "Explicitly set Id with Doctrine when using "AUTO" strategy" and found that I should be able to do the following:
$newData = ... // array containing data to bring in
$newEntity = new MyEntity();
$newEntity->setId($newData['id']);
$newEntity->... // set other data fields
$em->persist($newEntity);
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$em->flush();
However, Doctrine is not using the provided ID. It's ignoring it when inserting. I've also tried this approach instead, since some people seemed to have had luck with it (even tried both):
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
But that doesn't change anything. ID's are still inserted automatically by the database. In the query log, I see that Doctrine isn't even attempting to insert the ID.
If I remove #ORM\GeneratedValue(strategy="AUTO") from MyEntity annotations, then the migration will respect the provided ID I give it. But I want to override it just during the migration.
I'm using Doctrine 2.4.2.
For this technique to work, you must use the second of these:
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata = $em->getClassMetadata('CS\AcmeBundle\Entity\MyEntity');
The problem is that Doctrine will return the same class meta data values for both.
They will both correctly identify the class file, read its annotations, etc. Obviously they are equivalent, except that one is an absolute namespace and the other is not.
But these strings will return different instances from getClassMetadata. Changes to one won't reflect in the other. If you want your intended technique to work, you must use the second form, because that is what UnitOfWork uses. It uses this normalization:
// \Doctrine\ORM\UnitOfWork->getCommitOrder()
...
$className = $this->em->getClassMetadata(get_class($entity))->name;
$class = $this->em->getClassMetadata($className);
...
Note that in the linked-to question, the solution uses get_class($entity). That is probably sufficient to get the correct behavior.
Even more detail: after a lot of stepping through code, I noticed that \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory was memoizing both versions of the class name string in its private property $loadedMetadata. The version that was being used to actually flush the entities was the one without the leading slash, and I was editing the one with the leading slash.
Because both strings return the same data, I think this represents a bug in the implementation.
The differences between GeneratedValue strategies
Inside your entity
Replace
#ORM\GeneratedValue(strategy="AUTO")
with
#ORM\GeneratedValue(strategy="NONE")
I am not sure whether you are using annotations or xml, or yml files. So better to change the xml or yml doctrine entity files inside your bundle config as well.

How to auto complete methods from Symfony 2 DI in netbeans

I am starting to develop with symfony 2 and it uses a lot dependency injection. I would like to know if is there any way that makes netbeans detect the type of object based on the string and auto complete with their methods?
For example, $this->container->get('doctrine') returns a Doctrine\Bundle\DoctrineBundle\Registry instance. In the container, the key doctrine corresponds to Doctrine\Bundle\DoctrineBundle\Registry.
Something like it, could be useful for zendframework 2 also.
I don't want to create new methods in the controller and nor use /* #var $var Symfony...*/, I would automatic detection.
As far as I know, there's no way for an IDE to detect the type of the object your container returns. My solution is to wrap those calls to the container into private getter functions. IMHO this improves code readability as well – especially, if you do this call more than once per class.
/**
* #return \Doctrine\Bundle\DoctrineBundle\Registry
*/
private function getDoctrine()
{
return $this->container->get('doctrine');
}
The IDE "PhpStorm" permits to suggest "use" declarations.
And this IDE propose specific features for Symfony2 and Drupal !
edited by JetBrains : http://www.jetbrains.com/phpstorm/
Not free but power full enough to reduce time developpement time (and time is money...)
Enjoy : )
phpStorm:
$foobar= $this->get('foobar'); //returns mixed
/* #var \MyNamespace\FooBar $foobar*/
or
$foobar= $this->get('foobar'); //returns mixed
/* #var FooBar $foobar*/
You can do this with eclipse PDT:
$foobar= $this->get('foobar'); //returns mixed
/* #var $foobar \MyNamespace\FooBar*/
( Walk around ) When comes to Symfony services:
Instead of
$doctrine = $this->container->get('doctrine');
use
$doctrine = $this->getDoctrine();
As you can see, Symfony allows you to access most of it services directly from $this variable. NetBeans will know what auto completion to use.
Lets have a look why this works (inside Controller class)
It is possible because Controller class imports Registry class with USE statement,
use Doctrine\Bundle\DoctrineBundle\Registry;
and then in method comment annotation it declares the returning object type with
/*
* #return Registry
*/
If you call $this->container->get('doctrine'); directly then auto completion will be get omitted and you will have to use whats below.
( Answer ) No magic auto completion works so far. Use Php Storm (it does what you request). For those who pick to stick with NetBeans you need to use manual annotation like in example below:
We can point NetBeans to a class it should be using for auto completion.
1) In terminal from project directory search for service you want to import:
php bin/console debug:container
If you know what you looking for use this instead:
php bin/console d:container | grep doctrine
...
doctrine --------------------------------------------------------
Doctrine\Bundle\DoctrineBundle\Registry
...
2) If this is not a service use get_class() PHP build in function to get class name of the object it particular variable. Or use reflection class. It's up to you.
3) Once you know the class name declare USE statement for better readability
use Doctrine\Bundle\DoctrineBundle\Registry;
4) Now wen we know what is the class name of the object instance in particular variable we are ready to inform NetBeans about what we know by using comment annotations so that it can enable auto completion.
/**
* #var $doctrine Registry
*/
$doctrine = $this->container->get('doctrine');
Now auto completion is enabled. Type
$doctrine->|
then press Ctrl+Space. See the image below:

Extend Symfony2 White October Admin Bundle Form Fields?

This question is quite specific.
I'm using Symfony2 White October Admin Bundle for generating administration for my application.
I wonder if anyone has experience with this bundle and knows how to modify specific fields added to Admin class. The bundle is not documented very well and I'd like to know, if there are methods for doing this, or does the bundle core need to be extended.
For example I've got a Speaker entity with a field storing the path to one's avatar:
/**
* #var string $picturePath
*
* #ORM\Column(name="picture_path", type="string", length=128, nullable=false)
*/
private $picturePath;
Then in the Admin class I'm adding the field:
protected function configure()
{
...
...
->addFields(array(
...
...
'picturePath'=> array("label" => "Avatar"),
));
}
Is there an easy way to tell the bundle that I'd like this field to be an upload field instead of a text field, and define extra methods to call after submitting the form? (e.g. resize the image, store it, and then just store the image path in the DB)
As I haven't found any solution yet, I had to rape my entities to do that. So I modified the basic setter methods to call other methods inside the entity that do the dirty job. This is not a solution, and I'll still be happy if I could find better answers here.

Resources