2012-10-10 1 views
1

J'ai essayé plusieurs fois de démarrer avec symfony 2, mais je me suis toujours retrouvé bloqué en cours de route. Cette fois, je prévois de m'en tenir à ça! Jusqu'à présent, ma plus grande question est de savoir où placer les objets qui vont effectuer des tâches sans l'interaction de l'utilisateur.Objets utilitaires Symfony 2

Ex. Je veux créer quelques classes php qui vont gérer l'analyse de données de plusieurs sites Web tous les jours ou presque. Je veux que cette tâche soit lancée manuellement ou via un travail cron. En tant que tel, je n'ai vraiment besoin que du modèle et du contrôleur. (Contrôleur pour analyser le site et créer un modèle, modèle pour stocker les données analysées et persister à db). Est-ce la meilleure façon de faire cela pour créer un paquet qui traite uniquement de ces emplois de fond.

Je pense aux classes suivantes:

  • SiteParser

    • Site1Parser Prolonge SiteParser
    • Site2Parser Prolonge SiteParser
  • Model1

  • Model2

  • Une classe chargée d'orchestrer l'analyse de différents sites et d'indiquer la persistance des modèles créés.

Cela vous semble-t-il logique? Et si oui, comment pourrais-je mettre cette structure dans symfony?

Merci pour toute l'aide, si je n'ai pas été clair ou si vous avez une question s'il vous plaît demander je fournirai tous les détails nécessaires!

Répondre

7

Tout d'abord, je déconseille d'utiliser un contrôleur ici. Rappelez-vous que le but d'un contrôleur est de servir de médiateur entre le modèle et la vue. Avec les processus automatisés, vous n'avez pas vraiment de vue - personne ne regarde ou ne lit votre sortie (vous voudrez peut-être implémenter une journalisation, mais c'est une autre affaire). Cela dit, je dirais que votre meilleur pari est de créer une commande en utilisant la fonction Console Command de Symfony. Vous avez probablement utilisé l'outil de commande app/console pour générer des ensembles et créer des mappages d'entités. Avec la classe ContainerAwareCommand, vous pouvez écrire les vôtres. Et la meilleure partie est que la commande connaît le conteneur ... en d'autres termes, vous pouvez accéder directement à Doctrine, Monolog, Twig ou à l'un des autres services, en utilisant une méthode get(). Supposons que votre application extrait des images du site, puis enregistre les URL de ces images dans une base de données. Pour ce faire, vous devez d'abord créer une classe de service (nous allons le mettre sous le MyBundle \ espace de noms de service), et lui donner les méthodes nécessaires:

namespace MyBundle\Service; 

class Parser 
{  
    public function extractImageUrls($siteUrl) 
    { 
     // Do whatever here, and return an array of URLs 
    } 
} 

Ensuite, vous pouvez l'enregistrer en tant que service nommé « analyseur » via app/config/config.YML:

services: 
    parser: 
     class: MyBundle\Service\Parser 

Maintenant, vous pouvez appeler get("parser") de votre récipient. Les contrôleurs étendent le conteneur, donc dans un contrôleur vous pouvez dire $this->get("parser"), mais dans votre commande de console vous devez spécifiquement obtenir le conteneur: $this->getContainer()->get("parser").

Alors vous pouvez écrire votre SiteParseCommand pour ressembler à quelque chose comme ceci:

namespace MyBundle\Command; 

class SiteParseCommand extends ContainerAwareCommand { 
    protected function configure() 
    { 
     $this->setName("site:parse"); 
     $this->addArgument("site", InputArgument::REQUIRED); 
    } 

    protected function execute(InputInterface $input, OutputInterface $output) 
    { 
     $parser = $this->getContainer()->get("parser"); 
     $doctrine = $this->getContainer()->get("doctrine"); 
     $em = $doctrine->getEntityManager(); 
     $imageRepository = $em->getRepository("MyBundle:Image"); 

     $site = $input->getArgument("site"); 

     $images = $parser->getImageUrls($site); 

     // Add each image to the database as you normally would, using your entity manager 
    } 
} 

Maintenant, à partir de la ligne de commande, vous pouvez appeler:

app/console site:parse "http://url.com" 

Ajoutez à cela crontab, et je pense tu es bon à faire.

Encore une fois, puisqu'il n'y a pas de vue, vous ne serez pas en mesure de dire facilement si tout fonctionne correctement. Donc, je voudrais mettre en place une sorte de journalisation pour vous faire savoir ce qui se passe. Étant donné que Monolog est également un service, la console de commande y a également accès via $this->getContainer()->get("logger").

Espérons que cela aide!

(Plus de documentation sur la classe ContainerAwareCommand here)

+1

Merci beaucoup! Une réponse géniale qui clarifie vraiment beaucoup de confusion que j'ai eu par le passé. Je regarderai tout ce que vous avez écrit plus en détail demain mais je pense que vous m'avez mis sur la bonne voie! – Nath5