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(),
);
// ...
}
}
Related
I just recently upgraded my project from symfony 4 to 6, without much problems. The current online version is using symfony6 without problem.
I am now trying to clean the code, removing some useless parts and other little modifications, and I just met a strange problem. All my pages are now giving me the error:
You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".
Problem is: the package is present, so the recommended command does nothing.
I tried to check the code triggering the exception:
protected function renderView(string $view, array $parameters = []): string
{
if (!$this->container->has('twig')) {
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
}
...
}
So I checked the twig service with bin/console debug:container twig, which gives me the same output as with the current working version.
There is a note:
"! [NOTE] The "twig" service or alias has been removed or inlined when the container was compiled."
But this note is also present in my production code without problem.
I brought no real modification to the controller files between the two versions, the main difference being files moved and namespaces adapted to this change.
I don't have any ideas other than doing all these changes all over again, but I fear I'll fall on the same result.
Edit:
The problem look larger that I thought, as I get the same problem with the security bundle.
I tried to inject \Twig\Environment in the controller method, and it autowired with no problems.
I tried to update all the recipes with composer recipes, with no interesting result.
I tried to compare it to a newly created Symfony6 controller with twig, but found no significant differences, except the use of php attributes, which I tried to use in my project, with no result either.
Result of bin/console debug:container HomeController:
Option Value
----------------- -------------------------------
Service ID App\Controller\HomeController
Class App\Controller\HomeController
Tags controller.service_arguments
container.service_subscriber
Calls setContainer
Public yes
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired yes
Autoconfigured yes
Usages none
Edit:
To be honest, if twig is now a private service, not accessible through the container, why is the AbstractController still using this line:
if (!$this->container->has('twig')) {
throw new \LogicException('You cannot use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".');
}
Wouldn't that just cause an error for everyone ? Then why not, and only now for me while it doesn't for my current version (my production is operational with the same Symfony 6 packages)
Edit:
By playing in the vendors, I managed to find that in my original code, the ServiceLocator is used in the AbstractController, but in my bugged one, it seems to be a cached Container class that is used (as $this->container).
So the has() method called in not the same...
In Symfony 3.0 (and I'm sure 2.X as well), if I want to make a custom constraint validator with a dependency, I have to register that validator as a service in the dependency injection container (which is described by default in project_directory/app/config/services.yml) using a special tag ( as described here).
This means that the Validator component must know where to look for the service container. This issue also comes up for the ControllerResolver. Since controllers can be registered as services, the ControllerResolver must know where the service container is.
How do the Symfony components know where to look for the service container, and how can I configure this? I ask because I want to build a custom framework using the Symfony components, which means I'll be making my own service container, and I'd like to be able to point the Validator and the ControllerResolver to that service container.
In Symfony Standard Edition, the container is initialised by the Kernel. Have a look at the AppKernel and its parent class.
The kernel loads a configuration file in the registerContainerConfiguration() method:
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
This code will load an environment specific configuration file (config_prod.yml, config_dev.yml etc). In a standard setup that file imports the main config.yml file.
The services.yml file is loaded with an import in config.yml:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
If you're thinking of building your own framework (which is a good learning experience), you'll need to read more code of existing frameworks first. Also, it's worth to read the excellent Create your own PHP framework.
This means that the Validator component must know where to look for the service container
This is scary. I see no connection between validation and the service container. I'd think of a better design.
P.S. Everyone should write their own framework once. The next step should be deleting it.
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.
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.
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.