Is there a way in Symfony 2.3 to use messages loaded from yml file?
Example: CRUD controllers echo a message just for having an entity created or not as Entity created..
Is there a way to define this string in a yml file and use it for every CRUD controller / Twig template and define it once and not to write it for every crud?
Explaining with a better example:
When an entity is created:
$this->get('session')->getFlashBag()->add('success-close', 'Entity created.');
But I just like to use something like this:
$this->get('session')->getFlashBag()->add('success-close', $str_entity_created);
where $str_entity_creted is defined in a hypothetic messages.ymlfile
#MyBundle/Resources/messages.yml
messages:
str_entity_created: "Entity created."
...
....
So, for every CRUD I have to change the string in just one place and it has changed globally in my entire app, instead of changing every string in every CRUD Controller.
Is there a way to accomplish that?
If I have to load a yml resource globally, how much will it degrade memory consumption and performance?
Use translations
$translated = $this->get('translator')->trans('Symfony2 is great');
messages.fr.yml
Symfony2 is great: J'aime Symfony2
Related
Hope you are all fine, I am a beginner trying to learn Symfony 3.0, so I want to generate my controller in a folder called Bundles, but it is not created, here is the command I taped :
php bin/console generate:controller
And this is fine, when I tape the controller name, that was what I wrote :
?[32mController name?[39m: Bundles/FrontBundle
But their answer is :
?[37;41m The controller name must contain a : ("Bundles/FrontBundle"
given, expecting something like AcmeBlogBundle:Post) ?[39;49m
I don't know if I have to do something before this to noy have such error.
Any Help would be much appreciated.
This is because controller name should be a combination of BundleName:ControllerName and you have provided a relative path to your bundle. If that doesn't work make sure you have your autloading properly setup and Symfony knows about your bundle
According to his doc you should use the shortcut notation when you are declaring a controller, entity, etc.
also you need to read the output of the command.
Welcome to the Symfony controller generator
Every page, and even sections of a page, are rendered by a controller.
This command helps you generate them easily.
First, you need to give the controller name you want to generate. You
must use the shortcut notation like AcmeBlogBundle:Post
Controller name: BundleNameEndingBundle:ControllerName
I'm using a standard Symfony 2.8 framework with Doctrine.
My entities' mappings are all annotated, but I would need to map a single entity by using the PHP way (by defining loadMetadata static method) . I know there's a way to override a mapping Bundle configuration like explained here, but what I would like is specifying a single Entity. Is that possible? Thanks
No you can't mix the formats
A bundle can accept only one metadata definition format. For example, it's not possible to mix YAML metadata definitions with annotated PHP entity class definitions.
see doc here:
http://symfony.com/doc/current/doctrine.html
if you really need to change the mapping format then I suggest you create a new bundle for your specific entity. I also had this problem. I wished to have different mapping format (yml and annotation in my case) but I had to create a new bundle.
I have an API, with an API call GET /users which returns me a list of users that all have a avatar_url field
in database this field is just the image name, and in the controller i'm then putting the base URL of my static domain serving images. So that it's only one URL to change in my conf , so the code works in staging/production etc.
but things start to get tricky with GET /comments etc. that all have sub-resource users that needs to have the url, so it means that currently every single point using users needs to have this logic, which is not very DRY
I would like to have something like that
// in my entity
use JMS\Serializer\Annotation as Serializer;
/**
* #Serializer\VirtualProperty
* #Serializer\SerializedName("url")
*/
public function getUrl()
{
return $this->container->getParameter('IMG_URL').$this->imgName;
}
so that regardless on how deeply nested my entity is, I will be able to seralize it with the property.
It seems to me it is possible to achieve something like as there's a bundle
https://github.com/KnpLabs/DoctrineBehaviors
which seems to achieve something similar
Check this out. http://jmsyst.com/libs/serializer/master/handlers
From what I understand you could create your own handler for the url serializer. By having the handler as a service written by you, then you can inject anything you want in it.
More info can be found at Creating a JMS Serializer handler in symfony2
I got a problem to add custom logic to some Symfony classes.
SwitchUserListener
I want to add a check, that a user cannot switch to a another user, which have more rights/roles, than the initial user.
First attempt
Overwrite the parameter in the security_listeners.xml with the key:
security.authentication.switchuser_listener.class But where can I overwrite it?
In the security.yml it didn't work:
security:
...
authentication:
switchuser_listener:
class: Symfony\Component\Security\Http\Firewall\SwitchUserListener
Second attempt
Overwrite the service for the SwitchUserListner service id: security.authentication.switchuser_listener
I create the same service in my service.xml of my bundle, but my class was not used / called.
Another idea was to overwrite only the class, but that only works for bundles, but the SwitchUserListener was not in the SecurityBundle, it was in the symfony component directory and that seemed to me as a really bad idea to overwrite the SecurityBundle
Third attempt
Now I get the solution: First time I didn't realize that the dispatcher call listener for the SWTICH_USER event in the SwitchUserListener:
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
So I need only to create a service with the special tag for this event type:
<tag name="kernel.event_listener" event="security.switch_user" method="onSecuritySwitchUser" />
And do the check in the given method.
This seems to be a better solution thatn the other two. But there is still a problem. In my listener for the SwitchUserEvent I need to ignore my custom check if the user wants to exit the switched user.
So I need to check the requested path: ignore if path containts '?switch_user=_exit'
But the path (URL parameter) can be changed:
# app/config/security.yml
security:
firewalls:
main:
# ...
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
But in my bundle I can't read this parameter, because it will not be passed to the service container. It will be passed to the constructor of the SwitchUserListner class and will be saved there as private attribute, never accessable (without Reflection) from outside. (that happens here: SecurityExtension.php line 591) So what to do? Define the parameter twice go against DRY. Use Reflection?
And the other point is that there aren' every time events that will be fired on which I write a subscriber class. So what would be another / best solution for it?
I ask this question because I will get some similar problem where I want to add or overwrite something of the symfony intern components.
TemplateGuesser
I wanted to modify the TemplateGuesser: For a specific bundle all Templates which has the annotation #Tempalte the tempate file should be located with the controller TestController#showAction at this path:
Resources/views/customDir/Test/show.html.twig
So the guesser should be put and locate everything into a additional folder customDir instead of using only views. When using the render function with a specific template, the guesser should ignore the annotation.
I created my own Guesser and overwrite the service id: sensio_framework_extra.view.guesser and in comparision to the SwitchUserListener this time my class is really called instead of the original guesser. Why it works here but not with the SwitchUserListener?
Is this a good solution at all? I also tried to add a second listener, which calls the TemplateGuesser, its the service sensio_framework_extra.view.listener with the class Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener But that didn't work.
Whenever you need to add custom logic or extend the framework behaviour, you can use and abuse the container configuration. That means you can overwrite pretty much every service Symfony defines by just creating a new class that extends that service – or not, really – and creating the service definition for it with the same key as the original service you wanted to extend or change behaviour.
For instance, Symfony has a base template guesser registered as a service with the sensio_framework_extra.view.guesser id. If you want to extend that or change behaviour, you only need to create your own class and register it with the same id of the original service – remember that the bundles loading order affects the service definitons with the same id, where the last one loaded is the one that will be created.
That should solve both of your problems.
I've started a Symfony2 project from scratch where I then installed FOSUserBundle.
Then, I have written (actually, generated with ORM Designer) some entities that need to have relations between them, and with the User entity.
I have Items belonging to Users, Collections belonging to Users that group Items, and so on.
Since I used FOSUserBundle I only have a basic User class (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md , step 3a) defined using annotations, no config/doctrine folder and no User.yml file in it.
I then created the MyBundle/Resources/config/doctrine folder and added the yml files mentioned above.
When I try to generate the entities with the command-line tool everything works fine: it will create the Entities from my yml files.
However, at this point, trying to load up in browsers the url where the login previously worked (when I only had the FOSUserBundle installed) will throw this error:
MappingException: No mapping file found named
'/var/www/concert/src/X/MyBundle/Resources/config/doctrine/User.orm.yml'
for class 'X\MyBundle\Entity\User'.
Following actions, such as generating the CRUD logic, will not work as long as I have an *.orm.yml file in the config/doctrine folder. If I remove those, CRUD generation will work, but generation of actual mysql tables won't.
Juggling with these gets me to a point where I can also get the tables, but then the actual app doesn't work if I try to use any of the url's where the newly generated CRUD is involved because since the entities are based on yml (which I remove to get things "working") it won't have any mapping knowledge.
Is this inherently wrong? To have yml-based entities in relationship with an User entity based on the FOSUserBundle and still be able to get the nice command-line generation tools?
The problem you describe stems from mixing configuration formats (yaml and I assume annotations). You can easily fix this by ditching the annotations in your models and replacing them with yaml-files like you would do in your own models.
Unfortunately the FOSUserBundle-docs only show you how to use annotations, so here is a quick transformation into yaml format when your X\MyBundle\Entity\User extends FOSUSerBundle's UserEntity:
X\MyBundle\Entity\User:
type: entity
table: fos_user
id:
id:
type: integer
strategy: { generator: "AUTO" }
The remaining stuff is taken care of by FOSUserBundle, as the BaseModel is a mapped-superclass and already describes the stuff in the User.orm.xml, but you could just as well replace the existing values or add additional values just like you would do with your own models.
If you don't use annotations throughout your app, you might also want to disable them in your app/config/config.yml to prevent side effects.