Рекомендуется вызывать отдельную службу из вашего метода handle()
. Таким образом, вы можете использовать эту же службу в контроллере, например.
Техническая версия:
- Вашему приложению дается конкретная вещь, которую нужно сделать (команда, если хотите). Эта команда поступает извне вашего приложения, которое может быть чем угодно, от веб-контроллера до контроллера API или приложения CLI. С точки зрения гексагональной архитектуры это называется port .
- После того, как приложение получит такую команду, его не должно волновать, с какого порта оно пришло. Обрабатывая все подобные команды в одном месте (обработчик команд), он не должен беспокоиться о происхождении команды.
Итак, чтобы дать вам краткий обзор:
[Web request] [CLI command] <-- these are ports
\ /
\ /
\ /
[Command] <--- this is a method call to your service
|
|
|
[Command handler] <--- this is the service doing the actual work
Обновил мой ответ
На основе предоставленного вами кода я реализовал то, что упомянул выше, так:
app / Console / Command / BotScrapeCommand.php
Этокоманда CLI, о которой я упоминал выше. Все, что должен сделать этот класс, это: 1. Собрать входные аргументы;(website_id
) в этом случае 2. Оберните эти аргументы в команду 3. Запустите команду, используя обработчик команды
namespace App\Console\Commands;
use App\Command\ScrapePortalSiteCommand;
use CommandHandler\ScrapePortalSiteCommandHandler;
class BotScrapeCommand extends Command
{
protected $signature = 'bot:scrape {website_id}';
protected $description = 'target a portal site and scrape';
public function handle(ScrapePortalSiteCommandHandler $handler)
{
$portalSiteId = $this->argument("website_id");
$command = new ScrapePortalSiteCommand($portalSiteId);
$handler->handle($command);
}
}
app / Command / ScapePortalSiteCommand.php
ЭтоКоманду я уже упоминал выше. Его работа заключается в переносе всех входных аргументов в классе, который может использоваться обработчиком команд.
namespace App\Command;
class ScrapePortalSiteCommand
{
/**
* @var int
*/
private $portalSiteId;
public function __construct(int $portalSiteId)
{
$this->portalSiteId = $portalSiteId;
}
public function getPortalSiteId(): int
{
return $this->portalSiteId;
}
}
app / CommandHandler / ScrapePortalSiteCommandHandler.php
Обработчик команд должен реализовывать логику на основепо его команде. В этом случае выясняется, какой сканер выбрать, а затем запустите его.
namespace App\CommandHandler;
use App\Command\ScrapePortalSiteCommand;
use App\Crawler\PortalSite1Crawler;
use App\Crawler\PortalSiteCrawlerInterface;
use InvalidArgumentException;
class ScrapePortalSiteCommandHandler
{
public function handle(ScrapePortalSiteCommand $command): void
{
$crawler = $this->getCrawlerForPortalSite($command->getPortalSiteId());
$crawler->crawl();
}
private function getCrawlerForPortalSite(int $portalSiteId): PortalSiteCrawlerInterface {
switch ($portalSiteId) {
case 1:
return new PortalSite1Crawler();
default:
throw new InvalidArgumentException(
sprintf('No crawler configured for portal site with id "%s"', $portalSiteId)
);
}
}
}
app / Crawler / PortalSiteCrawlerInterface.php
Этот интерфейс позволяет убедиться, что все сканеры могут бытьназывается аналогичным образом. Кроме того, это дает хороший тип подсказок.
namespace App\Crawler;
interface PortalSiteCrawlerInterface
{
public function crawl(): void;
}
app / Crawler / PortalSite1Crawler.php
Это то, к чему относится реализация фактического извлечения.
namespace App\Crawler;
class PortalSite1Crawler implements PortalSiteCrawlerInterface
{
public function crawl(): void
{
// Crawl your site here
}
}
Другое обновление
Поскольку у вас было дополнительных вопросов Я обновил свой ответ еще раз.
:void
Использование : void
в объявлении метода означает, что метод не будет ничего возвращать. Точно так же public function getPortalSiteId(): int
означает, что этот метод всегда будет возвращать целое число. Использование возвращаемых шрифтов было добавлено в PHP 7 и не относится к Laravel. Дополнительную информацию о возвращаемых типах можно найти в документации PHP .
Команды и обработчики
Использование команд и обработчиков команд - это лучшая практика, которая является частьюшаблон командного автобуса. Этот шаблон описывает универсальный способ работы с пользовательским вводом (команда). Этот пост предлагает хорошее объяснение команд и обработчиков. Кроме того, в этом блоге более подробно описывается, что такое командная шина, как она используется и каковы ее преимущества. Обратите внимание, что в приведенном мною коде сама реализация шины пропущена. На мой взгляд, вам это не нужно само по себе, но в некоторых случаях оно действительно повышает ценность.