【问题标题】:Utility Objects Symfony 2实用对象 Symfony 2
【发布时间】:2012-10-01 12:38:48
【问题描述】:

我曾多次尝试开始使用 symfony 2,但一直卡在路上。这次我打算坚持下去!

到目前为止,我最大的问题是在没有用户交互的情况下将执行任务的对象放置在哪里。

例如。

我想创建一些 php 类来处理每天左右解析来自多个网站的一些数据。我希望手动或通过 cron 作业启动此任务。因此,我只需要我猜的模型和控制器。 (控制器解析站点并创建模型,模型存储解析数据并持久化到 db )。这样做是为了创建一个仅处理这些后台作业的捆绑包的最佳方式。

我正在考虑以下课程:

  • 网站解析器

    • Site1Parser 扩展了 SiteParser
    • Site2Parser 扩展了 SiteParser
  • 模型1

  • 模型2

  • 某个类负责协调不同站点的解析并告诉创建的模型保持不变。

这看起来合乎逻辑吗?如果是这样,我将如何将该结构放入 symfony 中?

感谢您的任何帮助,如果我不清楚或您有任何问题,请询问我将提供所需的任何详细信息!

【问题讨论】:

    标签: php symfony cron bundle wamp


    【解决方案1】:

    首先,我建议不要在这里使用控制器。请记住,控制器的目的是在模型和视图之间进行调解。使用自动化流程,您并没有真正的视图——没有人查看或阅读您的输出(您可能想要实现一些日志记录,但这是另一回事)。

    也就是说,我认为最好的办法是使用 Symfony 的内置控制台命令功能创建命令。您可能使用过app/console 命令工具来执行诸如生成包和创建实体映射之类的操作。使用ContainerAwareCommand 类,您实际上可以编写自己的。最好的部分是该命令知道容器...换句话说,您可以使用 get() 方法直接访问 Doctrine、Monolog、Twig 或任何其他服务。

    假设您的应用程序从站点中提取图像,然后将这些图像的 URL 保存到数据库中。为此,您首先需要创建一个服务类(我们将其放在 MyBundle\Service 命名空间下),并为其提供必要的方法:

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

    然后就可以通过app/config/config.yml将其注册为名为“parser”的服务了:

    services:
        parser:
            class: MyBundle\Service\Parser
    

    现在,您可以从容器中调用get("parser")。控制器扩展容器,因此在控制器中您可以说 $this->get("parser"),但在控制台命令中您必须专门获取容器:$this->getContainer()->get("parser")

    那么你可以编写你的 SiteParseCommand 看起来像这样:

    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
        }
    }
    

    现在,您可以从命令行调用:

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

    将它添加到 crontab 中,我认为你很高兴。

    同样,由于没有视图,您将无法轻松判断一切是否正常。所以我会实现某种日志记录,让你知道发生了什么。由于 Monolog 也是一项服务,因此控制台命令也可以通过 $this->getContainer()->get("logger") 访问它。

    希望这会有所帮助!

    (有关 ContainerAwareCommand 类的更多文档here

    【讨论】:

    • 非常感谢!很棒的答案,确实消除了我过去的很多困惑。明天我会更详细地研究你写的所有内容,但我认为你让我走上了正确的道路!
    猜你喜欢
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 2016-07-31
    • 2020-04-04
    • 2012-03-20
    • 1970-01-01
    • 2014-04-09
    相关资源
    最近更新 更多