我曾多次尝试使用symfony 2,但一直都遇到困难。这次我打算坚持下去!
到目前为止,我最大的问题是在没有用户交互的情况下放置将执行任务的对象。
实施例。
我想创建一些php类,它们每天都会处理从几个网站解析一些数据。我希望手动或通过cron作业启动此任务。因此我只需要模型和控制器。 (控制器解析站点并创建模型,模型以存储已解析的数据并持久保存到db)。这是创建一个仅处理这些后台工作的捆绑包的最佳方式。
我正在考虑以下课程:
SiteParser
型号1
模型2
一些负责编排不同网站解析并告知已创建的模型持续存在的类。
这看起来合乎逻辑吗?如果是这样,我将如何将该结构放入symfony?
感谢您提供的任何帮助,如果我不清楚或您有疑问,请询问我是否会提供所需的任何详细信息!
答案 0 :(得分:7)
首先,我建议不要在这里使用Controller。请记住,Controller的目的是在模型和视图之间进行调解。使用自动化流程,您实际上没有视图 - 没有人在查看或读取您的输出(您可能希望实现一些日志记录,但这是另一回事)。
那就是说,我最好的办法是使用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的更多文档)