Symfony ContainerAwareCommand not found using Xdebug and PhpStorm - php

I am using PhpStorm with Symfony. What I am trying to do is to debug a Symfony command from inside the IDE by using the debug button (Shift + F9).
I am getting the following error.
PHP Fatal error: Class 'Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand' not found in /home/user/Projects/project1/symfony/src/AppBundle/Command/testScriptCommand.php on line 8
PHP Stack trace:
It's weird as I have followed the Symfony documentation for creating commands and I have included the following classes:
<?php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class testScriptCommand extends ContainerAwareCommand
{
protected function configure(): void
{
$this->setName('app:test-script');
}
protected function execute(InputInterface $input, OutputInterface $output): void
{
echo 1;
}
}
The debugger works inside the IDE until line 8 and once try to continue it fails with the already mentioned fatal error.
It seems to me as line 4 is not actually importing the ContainerAwareCommand that is needed.
Any ideas?

Extend Symfony\Component\Console\Command\Command
Dependency Inject the ContainerInterface with your commands constructor, something like this - in my case using autowired services:
/** #var ContainerInterface $container */
protected $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
Then you should be able to call fe. $this->container->getParameter('project.parameter')

What documentation did you followed?
For creating Commands you need to extend Command, no ContainerAwareCommand
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CreateUserCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:create-user';
protected function configure()
{
// ...
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// ...
}
}
For more information: https://symfony.com/doc/current/console.html
EDIT:
Adding info...
ContainerAwareCommand is for Symfony version <= 2.6 https://symfony.com/doc/2.6/cookbook/console/console_command.html Soooo old

Related

cant fill properties at __construct in laravel test unit

I have created a simple test like this :
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Illuminate\Support\Facades\Config;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class simpleTest extends TestCase
{
public $form_array = ['forms_data'];
/**
* A basic feature test example.
*
* #return void
*/
public function test_example()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
The test above runs without a problem .
I have a public property $form_array which in the example above has a static value, but when I'm trying to fill $form_array with __construct() in test, I get this error :
array_merge(): Argument #1 must be of type array, null given
at vendor/phpunit/phpunit/phpunit:98
94▕ unset($options);
95▕
96▕ require PHPUNIT_COMPOSER_INSTALL;
97▕
➜ 98▕ PHPUnit\TextUI\Command::main();
99▕
code :
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Illuminate\Support\Facades\Config;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class simpleTest extends TestCase
{
public $form_array;
public function __construct(){
$this->form_array = ['forms_data'];
}
/**
* A basic feature test example.
*
* #return void
*/
public function test_example()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
My goal is fill the $form_data with values from config files in laravel which i found this way :
public function __construct(){
parent::setUp();
$this->form_array = Config::get('ravandro.form_array');
}
but even a simple $this->form_data = 'value' doesnt work , and im really confused !
btw , Im using Laravel Octane to serve my application but I dont think it has any effect to tests.
Php version : 8.1
Laravel : 9
php-unit: "phpunit/phpunit": "^9.3.3"
In tests the correct constructor method is called setUp(), which runs before every test on that class.
You can check an example of this on https://phpunit.readthedocs.io/en/9.5/fixtures.html#fixtures

Creating symfony command extending controller

I am writing a symfony console command which will be executable by using "php bin/console app:mycommand" (symfony documentation: https://symfony.com/doc/current/console.html#creating-a-command).
In my MyCommand class I need to use the getDoctrine-function, so I have to extend the controller, but I don't see a way how to do that. Any ideas?
Currently I get following error on CLI: Attempted to call an undefined method named "getDoctrine" of class "App\Command\MyCommand".
<?php
// src/Command/MyCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:mycommand';
protected function configure()
{
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// Not working, producing mentioned error
$em = $this->getDoctrine()->getManager();
}
}
?>
The getDoctrine() method is provided by the ControllerTrait, which in turn depends on the ContainerAwareTrait for the container injection. This however will pull additional services and methods that you won't need in a command so instead of injecting the whole container, the recommended approach is that you inject just the service you need, which in this case is the ObjectManager (ObjectManager is the common interface implemented both by the ORM and the ODM, if you use both or you just care about the ORM, you can use Doctrine\ORM\EntityManagerInterface instead).
<?php
// src/Command/MyCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Persistence\ObjectManager;
class MyCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'app:mycommand';
private $manager;
public function __construct(ObjectManager $manager)
{
$this->manager = $manager;
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// Now you have access to the manager methods in $this->manager
$repository = $this->manager->getRepository(/*...*/);
}
}

How can I send all my Artisan command output to slack? (Using Laravel)

I'm trying to extend my Laravel Artisan commands with a trait. The trait should capture all command line output and send it to Slack.
I've got the 'send messages to slack' part working with this package.
However I'm failing to capture the console output. This is what I've got:
namespace App\Traits;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
trait NotifiesSlack
{
/**
* Execute the console command.
*
* #param \Symfony\Component\Console\Input\InputInterface $input
* #param \Symfony\Component\Console\Output\OutputInterface $output
* #return mixed
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$consoleOutput = new BufferedOutput;
$call = $this->laravel->call([$this, 'handle']);
$this->notifySlack($consoleOutput->fetch());
return $call;
}
public function notifySlack(string $output)
{
\Slack::send($output);
}
}
Am I overriding the right method? Are there other ways to capture the console output from the Command class?
Any help is welcome! Thanks in advance.
You are experiencing usual case of not able to override method via trait. It's obviously because the execute method is already declared in the class itself rendering the trait useless.
A quick and easy way, is to simply create your own abstract command class that extends the Illuminate\Console\Command; and override the execute method to your liking; afterwards use the abstract command class for your slack-reportable commands as base.
abstract class NotifiesSlackCommand extend Illuminate\Console\Command {
protected function execute(InputInterface $input, OutputInterface $output)
{
...
}
}
And real command that needs send to Slack
class ProcessImagesCommand extends NotifiesSlackCommand {
public function handle() {/* do magic */}
}

Doctrine PHP DataFixture : "Compile Error: Cannot redeclare class"

I created a PHP class to generate some fixtures :
namespace DashboardBundle\DataFixtures\ORM;
use DashboardBundle\Entity\Property;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadPropertyData extends AbstractFixture implements FixtureInterface, ContainerAwareInterface, OrderedFixtureInterface
{
/** #var ContainerInterface */
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load(ObjectManager $manager)
{
$properties = $this->container->get('dashboard.properties_generator');
foreach ($properties as $key => $propertyConfig) {
$property = new Property();
$property->setName($key);
$property->setType($propertyConfig);
$this->addReference('property-' . $key, $property);
$manager->persist($property);
}
$manager->flush();
}
public function getOrder()
{
return 1;
}
}
But I get this error :
➜ dashboard git:(guillaume) ✗ bin/console -v fixtures:load
/* ... some stuff ... */
[Symfony\Component\Debug\Exception\FatalErrorException]
Compile Error: Cannot redeclare class DashboardBundle\DataFixtures\ORM\LoadPropertyData
The namespace seems and the class name seems correct. There is no other file in the DashboardBundle\DataFixtures\ORM directory.
I tried to restart the servers (PHP-FPM and Nginx), I tried to clear the Symfony cache, but there is no effect.
In brief, I have no idea why Symfony throws this exception.
Any idea ? Thanks !

how to use properly webSockets in Symfony2

I'm trying to implement websockets in Symfony2,
I found this http://socketo.me/ which seems pretty good.
I try it out of Symfony and it works, this was just a simple call using telnet. But I don't know how to integrate this in Symfony.
I think I have to create a service but I don't know realy which kind of service and how to call it from the client
Thanks for your help.
First you should create a service. If you want to inject your entity manager and other dependencies, do it there.
In src/MyApp/MyBundle/Resources/config/services.yml:
services:
chat:
class: MyApp\MyBundle\Chat
arguments:
- #doctrine.orm.default_entity_manager
And in src/MyApp/MyBundle/Chat.php:
class Chat implements MessageComponentInterface {
/**
* #var \Doctrine\ORM\EntityManager
*/
protected $em;
/**
* Constructor
*
* #param \Doctrine\ORM\EntityManager $em
*/
public function __construct($em)
{
$this->em = $em;
}
// onOpen, onMessage, onClose, onError ...
Next, make a console command to run the server.
In src/MyApp/MyBundle/Command/ServerCommand.php
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Ratchet\Server\IoServer;
class ServerCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('chat:server')
->setDescription('Start the Chat server');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$chat = $this->getContainer()->get('chat');
$server = IoServer::factory($chat, 8080);
$server->run();
}
}
Now you have a Chat class with dependency injections, and you can run the server as a console command. Hope this helps!

Categories