2012-07-21 42 views
11

Ist es möglich, symfony2 app/console Befehle zu überschreiben? Im FOS UserBundle möchte ich zum Beispiel ein paar weitere Felder hinzufügen, die es fragt, wenn es einen Benutzer mit seinem Konsolenbefehl create user erstellt. Ist das möglich, oder muss ich meinen eigenen Konsolenbefehl in meinem eigenen Paket erstellen?Symfony2-Konsolenbefehle außer Kraft setzen?

+0

Hilfreiche Sachen auf diese Frage. Du solltest eine Antwort als richtig markieren;) –

Antwort

5

Sie können die Konsolenbefehle eines Bündels überschreiben, wenn Sie Ihr eigenes Bündel erstellen, das ein Kind dieses Bündels ist (siehe Bundle Inheritance). Wenn Sie dann eine Klasse in Ihr Bundle einfügen, die denselben Ort/denselben Namen wie der ursprüngliche Befehl hat, überschreiben Sie sie effektiv.

Um beispielsweise FOS/UserBundle/Command/CreateUserCommand.php zu überschreiben, erstellen Sie MyCompany/UserBundle/Command/CreateUserCommand, wobei MyCompanyUserBundle FOSUserBundle als übergeordnetes Element hat.

Ihre Befehlsklasse könnte die FOS-Befehlsklasse erweitern, um sie (Bits davon) wiederzuverwenden. Nachdem ich jedoch den FOS CreateUserCommand betrachtet habe, müsste man alle Methoden überschreiben, um weitere Eingabefelder hinzuzufügen, in welchem ​​Fall es keinen Vorteil bringt, dies zu tun. Das bedeutet natürlich auch, dass Sie in jedem Paket Ihren eigenen Befehl erstellen können, aber meiner Meinung nach ist es besser, die Anpassung von FOSUserBundle in einem Unterpaket zu behalten.

14

Der gesamte Prozess für mehrere Felder auf den Befehl Hinzufügen ist:

<?php 

namespace Acme\UserBundle; 

use Symfony\Component\HttpKernel\Bundle\Bundle; 
use Symfony\Component\DependencyInjection\ContainerBuilder; 

class AcmeUserBundle extends Bundle 
{ 
    public function getParent() 
    { 
     return 'FOSUserBundle'; 
    } 
} 

2.Once Sie tun, dass Sie die neu erstellen können:

1.In Ihre AcmeDemoBundle Klasse Sie FOSUser als Eltern setzen müssen CreateUserCommand in Ihrem Paket enthält:

<?php 

namespace Acme\UserBundle\Command; 

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; 
use Symfony\Component\Console\Input\InputArgument; 
use Symfony\Component\Console\Input\InputOption; 
use Symfony\Component\Console\Input\InputInterface; 
use Symfony\Component\Console\Output\OutputInterface; 
use FOS\UserBundle\Model\User; 

/** 
* @author Matthieu Bontemps <[email protected]> 
* @author Thibault Duplessis <[email protected]> 
* @author Luis Cordova <[email protected]> 
*/ 
class CreateUserCommand extends ContainerAwareCommand 
{ 
    /** 
    * @see Command 
    */ 
    protected function configure() 
    { 
     $this 
      ->setName('fos:user:create') 
      ->setDescription('Create a user.') 
      ->setDefinition(array(
       new InputArgument('username', InputArgument::REQUIRED, 'The username'), 
       new InputArgument('email', InputArgument::REQUIRED, 'The email'), 
       new InputArgument('password', InputArgument::REQUIRED, 'The password'), 
       new InputArgument('name', InputArgument::REQUIRED, 'The name'), 
       new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'), 
       new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive'), 
      )) 
      ->setHelp(<<<EOT 
The <info>fos:user:create</info> command creates a user: 

    <info>php app/console fos:user:create matthieu</info> 

This interactive shell will ask you for an email and then a password. 

You can alternatively specify the email and password as the second and third arguments: 

    <info>php app/console fos:user:create matthieu [email protected] mypassword</info> 

You can create a super admin via the super-admin flag: 

    <info>php app/console fos:user:create admin --super-admin</info> 

You can create an inactive user (will not be able to log in): 

    <info>php app/console fos:user:create thibault --inactive</info> 

EOT 
      ); 
    } 

    /** 
    * @see Command 
    */ 
    protected function execute(InputInterface $input, OutputInterface $output) 
    { 
     $username = $input->getArgument('username'); 
     $email  = $input->getArgument('email'); 
     $password = $input->getArgument('password'); 
     $name  = $input->getArgument('name'); 
     $inactive = $input->getOption('inactive'); 
     $superadmin = $input->getOption('super-admin'); 

     $manipulator = $this->getContainer()->get('acme.util.user_manipulator'); 
     $manipulator->create($username, $password, $email, $name, !$inactive, $superadmin); 

     $output->writeln(sprintf('Created user <comment>%s</comment>', $username)); 
    } 

    /** 
    * @see Command 
    */ 
    protected function interact(InputInterface $input, OutputInterface $output) 
    { 
     if (!$input->getArgument('username')) { 
      $username = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a username:', 
       function($username) { 
        if (empty($username)) { 
         throw new \Exception('Username can not be empty'); 
        } 

        return $username; 
       } 
      ); 
      $input->setArgument('username', $username); 
     } 

     if (!$input->getArgument('email')) { 
      $email = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose an email:', 
       function($email) { 
        if (empty($email)) { 
         throw new \Exception('Email can not be empty'); 
        } 

        return $email; 
       } 
      ); 
      $input->setArgument('email', $email); 
     } 

     if (!$input->getArgument('password')) { 
      $password = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a password:', 
       function($password) { 
        if (empty($password)) { 
         throw new \Exception('Password can not be empty'); 
        } 

        return $password; 
       } 
      ); 
      $input->setArgument('password', $password); 
     } 

     if (!$input->getArgument('name')) { 
      $name = $this->getHelper('dialog')->askAndValidate(
       $output, 
       'Please choose a name:', 
       function($name) { 
        if (empty($name)) { 
         throw new \Exception('Name can not be empty'); 
        } 

        return $name; 
       } 
      ); 
      $input->setArgument('name', $name); 
     } 
    } 
} 

Hinweis ich habe ein neues Eingabeargument genannt Namen hinzugefügt und in dem Befehl, den ich bin mit einem acme.util.user_manipulator Service statt Im Original werde ich auch den Benutzernamen bearbeiten.

3.Create Ihre eigene UserManipulator:

<?php 

namespace Acme\UserBundle\Util; 

use FOS\UserBundle\Model\UserManagerInterface; 

/** 
* Executes some manipulations on the users 
* 
* @author Christophe Coevoet <[email protected]> 
* @author Luis Cordova <[email protected]> 
*/ 
class UserManipulator 
{ 
    /** 
    * User manager 
    * 
    * @var UserManagerInterface 
    */ 
    private $userManager; 

    public function __construct(UserManagerInterface $userManager) 
    { 
     $this->userManager = $userManager; 
    } 

    /** 
    * Creates a user and returns it. 
    * 
    * @param string $username 
    * @param string $password 
    * @param string $email 
    * @param string $name 
    * @param Boolean $active 
    * @param Boolean $superadmin 
    * 
    * @return \FOS\UserBundle\Model\UserInterface 
    */ 
    public function create($username, $password, $email, $name, $active, $superadmin) 
    { 
     $user = $this->userManager->createUser(); 
     $user->setUsername($username); 
     $user->setEmail($email); 
     $user->setName($name); 
     $user->setPlainPassword($password); 
     $user->setEnabled((Boolean)$active); 
     $user->setSuperAdmin((Boolean)$superadmin); 
     $this->userManager->updateUser($user); 

     return $user; 
    } 
} 

In dieser Klasse nur muß ich die Funktion erstellen, damit der Rest von Befehlen fördern mag, degradiert .. weiß nicht, über Ihren neuen Eigenschaften des Benutzers, damit ich nicht Sie müssen einen CompilerPass erstellen, um den gesamten Service zu überschreiben.

4.Finally, definieren diesen neuen UserManipulator Dienst in den Ressourcen/config und fügen Sie es die Dependency Injection-Erweiterung:

services: 
    acme.util.user_manipulator: 
     class:  Acme\UserBundle\Util\UserManipulator 
     arguments: [@fos_user.user_manager] 

Fertig !!!

+0

Hi @ nass600! Danke für deine ausführliche Antwort, aber könntest du auch den letzten Teil detailliert beschreiben: "füge es der DependencyInjection-Erweiterung hinzu". Danke vielmals – Reveclair

0

In Symfony (3.3) können Sie Konsolenbefehle überschreiben, indem Sie diesen Links folgen. https://symfony.com/doc/current/console/calling_commands.html und die Optionen auf https://symfony.com/doc/current/console/input.html

-Code von symfony doc:

use Symfony\Component\Console\Input\ArrayInput; 
// ... 

protected function execute(InputInterface $input, OutputInterface $output) 
{ 
    $command = $this->getApplication()->find('demo:greet'); 

    $arguments = array(
     'command' => 'demo:greet', 
     'name' => 'Fabien', 
     '--yell' => true, 
    ); 

    $greetInput = new ArrayInput($arguments); 
    $returnCode = $command->run($greetInput, $output); 

    // ... 
} 
Verwandte Themen