Is it possible to use a different class for sonata.media.adapter.filesystem.s3 service? Right now I can see it's hardcoded in gaufrette.php:
->set('sonata.media.adapter.filesystem.s3', AwsS3::class)
->args(['', '', ''])
Is it possible to override this behaviour and set any other adapter class, e.g. Gaufrette\Adapter\AsyncAwsS3?
According to Symfonys architecture it should be possible to override pretty much everything: https://symfony.com/doc/current/bundles/override.html#services-configuration
If you want to modify the services created by a bundle, you can use service decoration. If you want to do more advanced manipulations, like removing services created by other bundles, you must work with service definitions inside a compiler pass.
Most probably you solution is the latter. Here is an existing question on how to do that: Symfony: Overriding Symfony service ( compiler pass )
Related
I'm playing with Symfony reusable bundles and I want to make some bundle with default configuration for all my other projects like common entities, controllers etc. But the problem is taht I want to keep some default configuration for 3rd party bundles in that bundle too (easy admin, fos user bundle,...).
I would like to set some default configuration in my bundle and in case of need override it in app/config... Is this possible and if yes, how can I achieve that.
Thanks in advance
You need use prepend extension config for keep other extension configurations.
Follow the documantation
https://symfony.com/doc/current/bundles/prepend_extension.html
You can maybe write a compiler pass that will set parameters in your 3rd party bundle.
Here is an example of compiler pass I did here.
so in your compiler pass you would have something like:
$fosParameters = ['db_driver' => 'orm', 'firewall_name' => 'main'];
$container->setParameter(
'fos_user',
$fosParameters
);
also, do not forget to add your compiler pass to your bundle file like I did here.
I am not 100% sure this will work but I do not see why it would not work.
I'm really new to Symfony 2, coming from CI and trying to get me head around where the correct places for everything should go. I've got a bundle that takes care of the few main page types I have, but here's one page element that I use in multiple pages, that can have different configurations for each page.
The logical way around this (as far as I can see) is to have a single class somewhere that all the pages can use... this isn't to be accessed by users so shouldn't go in the controller I'm guessing but where should I put this class?
Make a 'core' type folder within my bundle. Are there naming best practices for this?
Should it go in the vendor folder or is this just for third party bundles?
Make another bundle to somehow use this code... seems a bit overkill for one or two classes?
other?
I guess what you need is to create a service. You can create your own class that has it's own logic and retrieve it using the service container in the controller. The following example is available at Symfony Service Container Docs
$mailer = $this->get('my_mailer');
$mailer->send('ryan#foobar.net', ...);
To make that class available you have to add it in the service.yml file of your bundle like this:
services:
my_mailer:
class: "%my_mailer.class%"
arguments: ["%my_mailer.transport%"]
You can add any other service or parameter to your class via the arguments
More info here: http://symfony.com/doc/current/book/service_container.html
I have a best practices question relating to building a custom router in Zend 2. I would like to use the service manager to get something in my router which would allow me to connect to an arbitrary data source (without exposing any info to my router) so that I can determine whether or not I can match that route.
For example, I would do something like this in my match() method:
$serviceManager->get('site_manager')->locateByRequest($request);
However, there isn't a clear way to access the service locator in a router. I found this article which essentially creates a custom factory so that you inject the service locator into your router:
http://www.zendexperts.com/2012/12/09/custom-routing-in-zend-framework-2/
Is this the best way to do this? Are there any other ideas or suggestions?
The main thing here is to NOT allow my router to know anything about the implementation of my so-called site_manager which may use a JSON text file, or MongoDB backend, or anything else for that matter. I want no dependencies and I want to expose no more than the method call from my above code example.
Ideas, comments, suggestions?
I think that injecting the whole service manager is just too much. I think it is ok to inject it in contollers, or in other helpers than could need to access many services, but for a helper component with a responsability as defined and as narrow as the router, i would prefer to:
create an interface, that defines what behavior should have the class that the router will work with.
inject just the service that the router needs, that could be any class implementing that interface.
With this, you can change the behavior of how the router resolve routes, changing the service that you are using to do it, but without having to change the routers code to access to something that should not be more than a configuration issue. With this you will get a better decoupling and have a more pure dependency injection.
Take a look at this article about Service Locator, Dependency Injection, and their differences
Also, it can be also interesting to take a look at the Strategy Pattern . This is more or less what im talking about. Instead of giving the router the knowledge and the ability to decide, it is just expecting a dependency to be injected, and inside that dependency is the implementation of some processes that the router needs, but which strategy to achieve the same result could be different, and the router doesn't really care about which one is being used.
I have some fairly complex routing rules, that are only achievable with custom code, and not with the default router.
The router has also to take into account the domain name.
Is it possible (and how) to define my own Router class, that would have a method accepting a Request and returning the bundle/controller name?
To achieve what you're asking, you don't need to completely redefine the router
You can simply write your own class that implements UrlMatcherInterface. If you want to be able to generate URLs that match your scheme as well, you'll have to create another class which overrides UrlGeneratorInterface as well.
In order to take into account the domain name, you'll need to use RequestContext, which is passed to their constructors (it's not well documented, but check Router::get{Matcher,Generator} for the details).
Once your classes are prepared, you can inject them into the router simply by overriding the parameters "router.options.generator_class" and "router.options.matcher_class" in your bundle.
However, it may not be the best approach for what you want - overriding parts of the router like that requires a lot of care to preserve all of the caching.
You might want to consider using Symfony2's normal router, but handing it different route files depending on what the request's domain is. This can be done easily if you configure your web server to set a variable or execute a different front controller depending on the domain name.
Using that information, you can then load a different 'environment' per-request, with the only difference between the different environments being that they use different routing files.
After studying Matthias Noback's tutorial, I have made a slight modification for my CRUD routing builder.
Before and after using CrudLoader can be seen here in routing/crud/acompetencies.yml
It is just a workaround or misuse of resource as you can see in this CrudLoader class.
I don't know if it is right or bad practice. It seems to work well.
refer sonata admin bundle which is having custom routing class classes
symfony 2.5 requires parameter for custom matcher: router.options.matcher_base_class
and class which implements Symfony\Component\Routing\Matcher\RequestMatcherInterface
I'm trying to pass the entity manager to a service but havent find a correct way yet. I want to complete remove the em from the controller so thats why I'm finding another way.
I was thinking of this options:
1. I could save it in the registry and then try to access it from the service object. can I access the registry from there?
2. Inject the em to a static variable of a base class for the services in the bootstrap.
What is the correct way yo do it?
thanks
I think generally the best way to do it is to pass the entitymanager as an argument to the constructor.
This allows you to easily replace the entitymanager for example when doing unit tests, and unlike your approaches of 1 and 2, it does not depend on behavior in a base class or global data (the registry is a lot like a global variable)
What you could do to avoid touching the EM in your controllers is using a dependency injection container, such as the one in Symfony2 or the one in ZF2 (not sure if that component is very stable yet).
Another perhaps slightly simpler approach would be to have a sort of a "service locator" object, which you would use in the controller to get instances of your services. You could initialize the locator in your bootstrap with the services, or perhaps with a factory class which creates them.
In any case you will probably require at least some kind of an intermediate object in the controller. Personally I don't really see an issue with simply using the EM itself, unless you have some other reasons besides just not wanting to.
There's nothing wrong, IMO, with letting your controllers know about the EM. I typically use a Zend_Application_Resource to bootstrap Doctrine. That resource facilitates a bootstrap resource called "doctrine" which has an EM available. The abstract controller implements and em() method, which returns the EM.
When instantiating service classes, the constructor simply injects the EM via a call to $this->em() at constructor time.
This is nice, as many times, simple controller actions don't need any special service class, but can instead get away with doing $entity = $this->em()->getRepository('Some\Entity')->find(1); In those cases, I don't see any reason for additional redirection via a service class.