how to use properly webSockets in Symfony2 - php

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!

Related

Symfony 4 Adding/Updating Entities from Command

I have a command that i run from CLI to import data and create entries.
$doctrine = $this->getContainer()->get('doctrine');
$em = $doctrine->getEntityManager();
/** #var PropertyRepository $propRepo */
$propRepo = $doctrine->getRepository(Property::class);
$propRepo->findOneBy(['id' => $property['PropertyId']])
My Command extends ContentAwareCommand ( even tho it says its deprecated it really dont like it )
SO how can i query my repositories from inside this Command?
Use dependency injection inside your command, you need to pass EntityManagerInterface to your constructor,
class SomeCommand extends ContainerAwareCommand
{
private $em;
function __construct(EntityManagerInterface $em)
{
$this->em = em;
parent::__construct(); // you need to call the parent else command won't show up
}
// after this you are free to use entity manager in your command
}

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(/*...*/);
}
}

Symfony ContainerAwareCommand not found using Xdebug and PhpStorm

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

Injecting Services into a Service

I am trying to inject public services like entityManager in the constructor of a service I created but I keep having this error :
Too few arguments to function App\Services\BillingInterface::__construct(), 0 passed in /var/www/.../src/Controller/TestController.php on line 144 and exactly 1 expected.
In my controllers, services are correctly injected in different methods but in the service I created it's not injected in the constructor.
I didn't change anything in the services.yaml as the documentation says autowire is automatic in Symfony 4.2
PS : I recently updated from Symfony 4.1 to 4.2 and I'm not sure but I think it worked before.
Maybe a library didn't updated correctly but I don't find any errors.
Here are the informations for the service
Service code :
#/src/Services/BillingInterface
namespace App\Services;
use Doctrine\ORM\EntityManagerInterface;
class BillingInterface {
private $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
}
Controller code :
namespace App\Controller;
use App\Services\BillingInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController {
public function teest(EntityManagerInterface $entityManager)
{
$billing = new BillingInterface();
}
}
And If I instantiate BillingInterface with $entityManager parameter of Controller, it works but I would like it injected directly in the BillingInterface class constructor.
And finally, here is what is written in Symfony's documentation :
// src/Service/MessageGenerator.php
// ...
use Psr\Log\LoggerInterface;
class MessageGenerator
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function getHappyMessage()
{
$this->logger->info('About to find a happy message!');
// ...
}
}
Link : https://symfony.com/doc/current/service_container.html
Chapter : Injecting Services/Config into a Service
So, I don't know what's wrong with my Service.
Thank you for your answers.
Since your BillingInterface is a service - you need to use its instance that is provided by Symfony container instead of attempting to instantiate it by yourself. Your controller needs to inject this service in order to be able to use it:
namespace App\Controller;
use App\Services\BillingInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class TestController extends AbstractController
{
/**
* #var BillingInterface
*/
private $billing;
/**
* #param BillingInterface $billing
*/
public function __construct(BillingInterface $billing)
{
$this->billing = $billing;
}
public function teest(EntityManagerInterface $entityManager)
{
// Use $this->billing ...
}
}

Run routing method from console

I want to be able to run a controller's method from URL, and from the console. How can I do that? I mean, having a method in some controller:
/**
* #Route("/fooBar", name="fooBar")
*/
public function actionFooBar() {
$this -> get('file') -> saveSomethingToSomeFile();
return 'a';
}
I want to be able to open it via http://domain.com/fooBar and php app/console fooBar, or something like this.
The console one doesn't work. How can I solve this?
What you want is (I think) technically doable, but not good practice.
You should move the code in your controller method to a service, then you can run that same code from both your command and your controller.
You need to build a Command:
<?php
namespace Application\CommandBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\EntityManager;
/**
* Class testCommand
* #package Application\CommandBundle\Command
*/
class TestCommand extends ContainerAwareCommand
{
/**
* Configuration of the command
*/
protected function configure()
{
$this
->setName('command:do:something')
->setDescription('This command does something');
}
protected function initialize(InputInterface $input, OutputInterface $output)
{
}
/**
* #param InputInterface $input An InputInterface instance
* #param OutputInterface $output An OutputInterface instance
*
* #return null|int null or 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $inputInterface, OutputInterface $outputInterface)
{
$outputInterface->writeln(
'This command does something <info>' . $inputInterface->getOption('env') . '</info> environment'
);
$this->getContainer()->get('application_command.test')->doSomething();
$outputInterface->writeln('Done');
}
}
More info with details: https://extractcode.com

Categories