Dependency injection in a symfony console command? Not full Symfony application - php

I've seen this How can i inject dependencies to Symfony Console commands? but that answer doesn't really give enough information and is already explained here http://symfony.com/doc/current/cookbook/console/console_command.html
The problem is a containerAwareCommand doesn't work with the setup here http://symfony.com/doc/current/components/console/introduction.html
In order to use containerAwareCommand from what I can tell, I need my application to use
Symfony\Bundle\FrameworkBundle\Console\Application
instead of
Symfony\Component\Console\Application
But using the frameworkBundle Application class requires an instance of KernelInterface and won't allow me to pass in a name and version to my application.
Here is what I have that won't work with containerAwareCommands
#!/usr/bin/env php
<?php
require __DIR__.'/../src/vendor/autoload.php';
$app = new Symfony\Component\Console\Application('spud', '0.0.1');
$app->add(new Isimmons\Spudster\Console\Commands\SayHelloCommand);
$app->run();
The command it's self runs but I get an error when trying to use getContainer
Call to undefined method Symfony\Component\Console\Application::getKernel()
On a related topic which will probably come up next, The documentation for registering a class in the container shows using a app/config/config.php file. But I don't have an app directory since this is not a full symfony application. My base directory in which all of the app except for the file above is located, is src/lib. If I can figure out the first part above, will symfony be able to find the config file at src/lib/config/config.php?

You can use Consolefull application.
Consolefull is a simple library to work with Symfony Console Component and Symfony Dependency Injection Component

Related

How to require and configure a dependency in laravel?

I wish to add chargebee php api to my laravel project
For that I first ran
composer require chargebee/chargebee-php
This added the chargebee API to vendor/chargbee
Next thing I would need to do is to include and configure the api. This can be done by:
require_once base_path('vendor/chargebee/ChargeBee.php');
ChargeBee_Environment::configure("your_site", "{your_site_api_key}");
My question is where should i do this? I would like the including of ChargBee.php and configuring it to be in a generic place so i can later use it in any Controller and it would already be set up. What is the default way to do this in Laravel?
You should set up a new service provider, like described in the official documentation.
Hint 1: Run php artisan make:provider ChargeBeeServiceProvider from command line to generate the new service provider.
Hint 2: take a closer look at the register() method. You should register the ChargeBee "service" there, most probably like a singleton. That's the place, where the API configuration should be put.
Since autoload is being used in the chargebee library (see its composer.json), there is no need for the require_once base_path('vendor/chargebee/ChargeBee.php'); line. Just simply use the classes.

Integration testing in Symfony

I'm writing a reusable bundle and want to carry out an integration testing of this bundle with the hosting app. The problem is that Symfony doesn't call neither the DependencyInjection\Extension::load nor DependencyInjection\Configuration::getConfigTreeBuilder method of my bundle, therefore the bundle's service configuration is not loaded and the services are not constructed properly. How can I get Symfony to load everything in tests, as if it was a real request?
Here is my test:
namespace Tests\AclAgentBundle;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
class IntegrationTest extends KernelTestCase
{
public function testAgentExistence()
{
$container = static::bootKernel()->getContainer();
$service = $container->get('test.Foo\Bar\Baz');
//...assertions...
}
test.Foo\Bar\Baz is an alias of a service, declared in the hosting app's config like
services:
test.Foo\Bar\Baz: '#Foo\Bar\Baz'
used to fetch the service via the container's get method in tests.
I figured out where the problem was. An older cached version of the container was used in the tests, therefore the changes in the configuration of the bundle were not reflected. The command php bin/console cache:clear --env=test helped to rebuild the cache. The methods I mentioned in the original question are not supposed to be called when booting the kernel (at least when the cache already exists).

Symfony console application: dependency injection [duplicate]

This question already has an answer here:
How to use DependencyInjection from symfony in stand alone application with commands?
(1 answer)
Closed last year.
A Symfony novice here. After reading some of the Symfony documentation and some answers here at SO, I am now almost completely confused.
I am trying to use the console application component and create a small db-aware console application.
Many people state that in order to use Symfony's DI features it would be enough to inherit my command class not from Symfony\Component\Console\Command\Command but from ContainerAwareCommand.
However when I try this I get a Method Not Found error on an application::getKernel() call.
I have a feeling that DI features are in fact not available in a console application based on the console component. Is there another kind of Symfony console application, for example, based on the full-blown framework?
I very much like the simple framework provided by the console component Symfony\Component\Console\Application. But the question is then - what to do for dependency injection and DBAL? All examples that I find seem to refer to the full Symfony framework and get me just all the more stuck.
Just a quick update on my progress if anybody stumbles upon the same problems.
I incorporated into my project the PHP-DI dependency injection framework, which seems to be working fairly well with no configuration (so far) - it figures out quite a lot by reflection, actually.
The same way, Doctrine\DBAL is included as a standalone library (I opted against the O/RM part of it, as it is really a tiny project and I'm on a much firmer ground with SQL than anything else) and the connection is simply returned by a connection provider which is injected wherever needed by the DI.
One thing I couldn't figure out is how to have the command classes instantiated by the DI library without my help, so I actually had to inject the container itself into my overridden application class and override the getDefaultCommands() where I then pull the instances out of the container manually. Not ideal but will have to do for now.
If your command extends ContainerAwareCommand
...
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...
class MyCommand extends ContainerAwareCommand
{
The DI container is available with the getContainer() method. (like in a standard controller), ex:
$this->validator = $this->getContainer()->get('validator');
I don't know if your question is still relevant, but I have an answer as I stumbled across the same problem here.
You just have to create the kernel yourself and give it to the \Symfony\Bundle\FrameworkBundle\Console\Application that extends the basic \Symfony\Component\Console\Application.
<?php
// CronRun.php
require __DIR__.'/../../../../vendor/autoload.php';
require_once __DIR__.'/../../../../app/AppKernel.php';
$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
$application->add(new \KingdomHall\TaskBundle\Command\CronCommand());
$input = new \Symfony\Component\Console\Input\StringInput('k:c:r');
$application->run($input);
You could use a solution I just pushed it to packagist.org. Includes full working symfony/dependency-injection. You're welcome to give it a shot. use composer to create your own project composer create-project coral-media/crune project_dir or just clone the repository.
https://packagist.org/packages/coral-media/crune
You only need to install DBAL dependencies (I don't suggest ORM if you don't really need it). Configure connection parameters in .env and just define a service to handle connection. That service can be injected in your Commands using public setMyService($myService) method with #required annotation. Also you could create a Connection class and bind is as parameter in your command constructor.The crune boilerplate also supports autowire and autoconfiguring features.

Can we use Symfony\Bundle\FrameworkBundle\Test\WebTestCase for symfony 2 console commands testing?

Using Symfony\Bundle\FrameworkBundle\Test\WebTestCase, we get easy access to container, entity manager etc. We can use it for functional testing by automatic manual HTTP requests.
Can we use it to test Symfony2 console commands as well so that we can have easy access to container and all services?
I want to test my costum Symfony2 console commands which uses many services which in turn uses doctrine entity manager to access data.
PHPunit documentation suggest to extend the test class with PHPUnit_Extensions_Database_TestCase,
Can we extend WebTestCase instead of test instead to test console commands ?
I have already refereed
How to test Doctrine Repositories Cookbook
How to test code that interacts with the Database Cookbook
The Console Component Docs
WebTestCase is meant for functional testing your web applications. Nothing will stop you from using it to test commands, but it doesn't feel right (hence your question).
Testing commands
Remember, that command tests (as well as controller tests) shouldn't be complex, just like the code you're putting in there shouldn't be complex either.
Treat your commands as controllers, make them slim and put your business logic where it belongs - to the model.
Accessing the container
Having said that, you can implement your own KernelAwareTestCase (or ContainerAwareTestCase) yourself. Here's a base class I'm using occasionally: jakzal / KernelAwareTest.php Gist
Also, note that next to Symfony\Component\Console\Application there's a Symfony\Bundle\FrameworkBundle\Console\Application which can actually work with the Symfony kernel.
Final note
Remember, that the most extensive testing should be done on a unit level.

Where should I add my internal classes file in symfony2?

I'm porting an old project to symfony2 in order to start learning the framework and I cannot realize how to properly add some helper functions I have in a PHP file.
Services. Wrap those function in a class (like Helper), define the class as a service and then inject it where needed (controller or another service, or even into a cli command).
The namespace (thus the path, as you tagged the question with psr-0) is up to you.

Categories