How can I access Symfony2 services from an external legacy system? - symfony

We are slowly migrating our current system to Symfony2, but the majority of the codebase is still in an inhouse framework. I want to leverage some functionality built in Symfony2 from within classes in the old legacy framework. Is there an easy way to access a Symfony2 service from outside of the Symfony framework?
class MyOldClass extends SomethingOld
{
public function getSomethingViaSymfony()
{
$service = new SomeSymfonyService();
$results = $service->getResults();
}
}
My assumption is that this would be a failure, for the dependencies wouldn't be injected.

you would need to initialize symfony without dispatching any actions. this basicly means taking the code from the symfony front controller file in web/index.php, modifying it a bit and paste it to some initialization file of your legacy app.
// legacy/init.php
require_once 'PATH_TO_SYMFONY/app/bootstrap.php.cache';
require_once 'PATH_TO_SYMFONY/app/AppKernel.php';
$kernel = new AppKernel('dev', true);
$kernel->loadClassCache();
$GLOBALS['service_container'] = $kernel->getContainer();
note that this code is not tested but i'm pretty sure it'll work because symfony is great;)
also you could think about a different strategy in which you embed the legacy action into symfony and not the other way around.
you would have to implement a legacy controller and give it a catch all route at the end of the routing definition. this controller can initialize the legacy application and dispatch actions to it. afterwards you can successively define new routes at the top of the routing file and dispatch them with symfony.
this strategy is imho much better because you can leave the legacy application almost untouched and kill it piece by piece.

Related

Symfony 2 split application to more bundles

I want to split my application to two bundles.
Back-end bundle which will be something like CMS admin(reusable to another projects), and Front-end bundle.
I moved whole backend application including controllers, templates and model to new bundle, but I have a problem with 3rd-party bundles on which my project is dependent.
For example AsseticBundle. When I add assetic configuration to BackendBundle/config.yml i recieve a exception.
There is no extension able to load the configuration for "assetic"
Is there some good tutorial showing how to split application to two cooperating bundles with one config and both dependent to 3rd-party libraries?
Thanks for any advice.
If I understand you correctly, you're trying to add 3rd party bundle configuration to your own bundle config.
This can be achieved only in app/config/config.yml, which is loaded by default by Symfony. It's the only place where Symfony looks.
What you can do, is prepend configuration via own extension. That can be placed in your bundle:
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
class BackendBundleExtension extends Extension implements PrependExtensionInterface
{
public function prepend(ContainerBuilder $container)
{
$container->prependExtensionConfig('assetic', array(
'key' => 'value'
));
}
}
Let me know, if this is sufficient explanation.

How to run Symfony Bundle without setting up Symfony app?

I have created a standalone Symfony bundle now is it possible to run the bundle alone without setting up Symfony?
I have performed unit tests and it is ok now I want to run the controller of the bundle in the browser (is it possible?)
Thanks in advance!
Bundle is Symfony specific and it only makes sense in a Symfony context.
The only context I can think of when it might be useful to call bundle controllers without installing the bundle in a Symfony project is tests. If that's what you're after, it is possible to set up a stripped down Symfony kernel just for tests. See my article on the subject: How to run Behat scenarios and functional tests from a Symfony bundle in isolation of a project
I have also implemented a DemoBundle where you can see it working with both phpunit and Behat tests.
You can take the same approach if you simply need to test your bundle manually in a browser, but you don't really want to install the whole framework.
Bottom line is you need to set up at least a minimal Symfony kernel.
You can't use a bundle inside Symfony context without letting know Symfony that it is "installed". To do so, you have to enable bundle in your AppKernel:
// app/AppKernel.php
// ...
class AppKernel extends Kernel
{
// ...
public function registerBundles()
{
$bundles = array(
// ...,
new FOS\UserBundle\FOSUserBundle(),
);
// ...
}
}

Integrating Sylius packages into Laravel project

I am attempting to use some Sylius packages in a Laravel project I'm building. I have added the packages to my project with composer, and the classes seem to be autoloading fine.
Now I want to do something with it. Let's take a simple example from the Sylius docs:
public function myAction()
{
$repository = $this->container->get('sylius.repository.address');
$manager = $this->container->get('sylius.manager.address'); // Alias to the appropriate doctrine manager service.
$address = $repository->createNew();
$address
->setFirstname('John')
->setLastname('Doe')
;
$manager->persist($address);
$manager->flush(); // Save changes in database.
}
I would like to recreate something like this in Laravel. I've created a simple test route to attempt this, but my problems are:
How do I get a repository?
How do I get a Doctrine manager service?
So I also included the laravel-doctrine package in an attempt to get a manager service, and then I just manually created a Product object, so that now I have:
Route::get('test', function() {
$entityManager = new Doctrine;
$product = new \Sylius\Component\Core\Model\Product;
$product->setName('Bla');
Doctrine::persist($product);
Doctrine::flush();
dd($product);
});
This creates an error: Class "Sylius\Component\Core\Model\Product" sub class of "Sylius\Component\Product\Model\Product" is not a valid entity or mapped super class.
I'm not sure where to go next. My understanding of Doctrine is limited, but my understanding was that the Sylius components are decoupled from Symfony, and that I could just use them. But it seems that the annotations (or xml definitions) don't exist for Doctrine to operate properly.
Any direction would be appreciated!
Laravel and symfony are completely different. You can't use a symfony bundle in a laravel project. If you want to use Sylius, you have to use the Symfony framework. If you want to use laravel, you have to search for another ecommerce platform.

Silex + FOQElasticaBundle

My goal is to link the FOQElasticBundle with my Silex website.
The problem is that the documentationn of FOQElasticBundle states that I only have to put some basic stuff in my config.yml file.
See: https://github.com/Exercise/FOQElasticaBundle#declare-a-client
So far I can't find a config.yml file anywhere and I don't know if I have to create it and if so where to put it.
Did I made the wrong choice making my website with Silex instead of Symfony itself?
Or is it possible to load the FOQElasticBundle?
You cant use Symfony Bundles in Silex directly.
Silex integrates third party libraries via Service Providers, which act like some sort of adapters for third party libs.
If you want the convenience of bundles i suggest you better use Symfony.
Otherwise you could try to write a Service Provider for the Elastica library yourself
or integrate it directly as its done here:
https://github.com/4devs/demo-silex/blob/master/web/index.php
$app['elastica.host'] = "localhost";
$app['elastica.port'] = 9200;
$app['elastica'] = function ($app) {
return new \Elastica\Client(array(
'host' => $app['elastica.host'],
'port' => $app['elastica.port']
));
};
Unfortunatly there is no Elastica Service Provider listed here:
https://github.com/silexphp/Silex/wiki/Third-Party-ServiceProviders

Silex - real DI vs injecting $app which looks like ServiceLocator?

I read the article yesterday: https://igor.io/2012/11/09/scaling-silex.html
And another one http://davedevelopment.co.uk/2012/10/03/Silex-Controllers-As-Services.html
So a conceptual question rised in my head:
Currently I do have a lot of controllers in separate classes. I overwrite controller_resolver to create a controller class instance and inject $app into contoller's constructor.
I define routes like this $app->get('/hello', 'HelloController::indexAction') <- my controller resolver will create new HelloController($app); - so far so good.
But to be honest it became a ServiceLocator pattern, not a DependencyInjection, because I do inject whe whole $app which looks like ServiceLocator usage.
Now I am in doubt: should I leave it as is (because it works well) or try "controllers as services" to inject only those sevices on which my controller really depends on? May be my SeviceLocator approach will hit me some day? (people say that DI is better for tests).
I have also looked into Symfony Framework Bundle: class Controller extends abstract class ContainerAware which also have the whole $container injected! ServiceLocator approach in full stack framework?
Any recomendation? Pros/cons?
The symfony2 full-stack framework
The framework uses the Dependency Injection pattern and not the Service Locator pattern.
All controllers aren't services by default. The ContainerAware class includes methods to get access to the service container, so you can call Services inside the Controller.
If you are going to use a Controller as a Service you need to remove the Controller extend. All dependencies you want to use inside the controller needs to be injected by the Service Container.
Read more about this in a blogpost by richard miller, one of the core contributors of Symfony2.
The Silex micro-framework
The Silex micro-framework provides the bare bones of a framework, it's up to you how the architecture looks and which patterns you use.
The Silex documentation uses Controllers that aren't Services. It injects the complete Service Container inside very Controller:
$app->post('/post/{id}-{slug}', function($id, $slug) use ($app) {
// ...
});
If you want to use controllers as service, you should only inject the services you want to use inside the controller.
EDIT: The Controller::action syntax refers also to a Controller that isn't a Service. The Controller:action notation is used to refer to Controllers as Services.
There's lot's of personal preference involved here. What you've done already is a good (enough) step to organising your code base. Some people like myself take things a step further and move our controllers to the container, rather than injecting it in to some kind of BaseController. This happens in both Silex and the full stack Symfony framework.
My advice would be to leave everything you have as is, then try defining your next controller as a service, by practising BDD.
For example, the behaviour of a UserController view action:
It should retrieve the user from a database
It should render the user with a template
Not once does it mention retrieving the database or the template renderer from a container. I'm comfortable not injecting the container, so I'll only inject what I'm led to believe I need by BDD.

Resources