Symfony 4 Adding/Updating Entities from Command - php

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
}

Related

Doctrine repository hints in PhpStorm

This is a two part question.
First, I can't seem to find out how to make PhpStorm correctly hint Doctrine repositories:
Entity looks like this:
/**
* #ORM\Entity(repositoryClass="UserRepository")
* #Entity #Table(name="users")
*/
class User
{
Repository looks like this:
use Doctrine\ORM\EntityRepository;
class UserRepository extends EntityRepository
{
public function getUser() {}
}
But when access the repository methods like so:
$userRepository = $em->getRepository(User::class);
$user = $userRepository->getU... // getUser() is not suggested
PhpStorm doesn't suggest the getUser() method.
The only workaround I found is:
/** #var UserRepository $userRepository */
$userRepository = $em->getRepository(User::class);
But this seems to be a bit bothersome to do it every time I need some repository.
Also, second part of the question is that I can't use repository as class property:
private EntityManager $em;
private UserRepository $userRepository;
public function __construct(EntityManager $em) {
$this->em = $em;
$this->userRepository = $em->getRepository(User::class);
}
Because it says:
Incompatible types: Expected property of type '\MyProject\UserRepository', '\Doctrine\Persistence\ObjectRepository|\MyProject\User|string' provided
How to set this up correctly for both cases?

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

how can i access to the entity repository from a entity listener in symfony 2.8?

I'm new in Symfony 2.
I have a function called "addNewTarjeta" in a personalized entity respository.
<?php
namespace Elkanogroup\ClientesBundle\Repository;
/**
* ClienteRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class ClienteRepository extends \Doctrine\ORM\EntityRepository {
/**
* Asigna una tarjeta a este cliente.
*/
public function addNewTarjeta(Cliente $cliente) {
$tarjeta = new \Elkanogroup\ClientesBundle\Entity\Tarjeta();
$tarjeta->setNumeroTarjeta('5555 5555 5555 5555');
$tarjeta->setCliente($cliente);
$tarjeta->setFechaExpedicion(new \DateTime());
$em = $this->getDoctrine()->getManager();
$em->persist($tarjeta);
$flush = $em->flush();
if ($flush != null) {
return false;
}
return true;
}
I have a listener waiting for a doctrine event postPersist. I would like to call to "addNewTarjeta" from a postPersist function.
I'm trying to do something like this:
<?php
namespace Elkanogroup\ClientesBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Elkanogroup\ClientesBundle\Entity\Cliente;
use Elkanogroup\ClientesBundle\Repository\ClienteRepository;
class ClienteListener {
public function postPersist(Cliente $cliente, LifecycleEventArgs $args) {
$cliente->addNewTarjeta($cliente);
}
But it doesnt work. Symfony says:
Attempted to call an undefined method named "addNewTarjeta" of class
"Elkanogroup\ClientesBundle\Entity\Cliente".
Can anyone help me ?? Thanks and sorry for my bad english.
Everyone here says that you need to inject the entity manager but to me it's not true: you can retrive it from LifecycleEventArgs without inject anything.
Just do
$args->getObjectManager();
and you're done.
Just a note: usually repos are used to keep custom queries (via DQL or plain SQL or query builder). A logic like this should be fitted inside a service (a manager, helper or whatever).
As #dragoste said, you need to inject the entitymanager service into your listener.
It can be done in services.yml:
name.of.your.listener:
class: AppBundle\Listener\MyListener
arguments: ["#doctrine.orm.entity_manager"]
And then, add a public function __construct(\Doctrine\ORM\EntityManager $entityManager) method in your listener:
<?php
namespace AppBundle\Listener;
class MyListener
{
/**
* #var \Doctrine\ORM\EntityManager
*/
private $entityManager;
public function __construct(\Doctrine\ORM\EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}

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