ステップ18:非非にに

5.2版本
维护 没有维护的
5.0

非同にに

フォーム投稿時にスパムの判定をするのには多少問題があります。例えばAkismet APIに遅延の問題があったときに,私たちのWebサイトも遅くなってしまいます。さらに,タイムアウトされてしまったり,Akismet APIに問題があったときには,コメントを失ってしまうかもしれません。

公開することなく投稿されたデータを保存して,レスポンスを早く返すことが理想とするところです。そのためにスパムのチェックとは独立して実行します。

コメントにフラグを付ける

コメントに提交垃圾邮件发表という状态を追加する必要があります。

评论クラスに状态プロパティを追加しましょう:

1
$ 欧宝娱乐app下载地址symfony控制台:实体评论

データベースマイグレーションを追加する:

1
$ 欧宝娱乐app下载地址symfony console make:迁移

既に登録されているコメント全てに,デフォルトの値として发表を指定するようにマイグレーションを正正式しください:

patch_file.
1 2 3 4 5 6 7 8 9 10 11 12 13
——/迁移/ Version00000000000000.php+ + + b /迁移/ Version00000000000000.php@@ -20,7 +20,9 @@最终类Version20200714155905扩展了AbstractMigrationpublic function up(Schema $ Schema): void{//这个up()迁移是自动生成的,请根据需要修改它-  $ this-> addsql('alter表注释添加状态varchar(255)不是null');+ $this->addSql('ALTER TABLE comment ADD state VARCHAR(255)');+ $this->addSql("UPDATE comment SET state='published'");+ $this->addSql('ALTER TABLE comment ALTER COLUMN state SET NOT NULL');} public function down(Schema $ Schema): void

データベースをマイグレートする:

1
sy欧宝娱乐app下载地址mfony控制台原则:迁移:迁移

また,状态のデフォルトの値を提交としてセットされていることを確認してください:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14
——/ src /实体/ Comment.php+ + + b / src /实体/ Comment.php@@ -55,9 + 55,9 @@类评论私人photoFilename美元;/ * *- * @ORM\Column(type="string", length=255)+ * @ORM\Column(type="string", length=255, options={"default": "submitted"})* /美元——私人状态;+私人$ State ='提交';public function __toString(): string {

easyadminの设定ををてコメントの状态(状态)を见ることができるようにしましょううう。

patch_file.
1 2 3 4 5 6 7 8 9 10
--- a / src / controller / admin / commendcrudcontroller.php+ + + b / src /控制器/ Admin / CommentCrudController.php@@ -51,6 +51,7 @@类CommentCrudController扩展了AbstractCrudController- > setLabel(照片)- > onlyOnIndex ();+收益率TextField::新(状态);$createdAt = DateTimeField::new('createdAt')->setFormTypeOptions(['html5' => true,

フィクスチャに状态をセットして,テストコードを修正しましょう:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
——/ src / DataFixtures / AppFixtures.php+++ b / src / datafixtures / appfixtures.php@@ -37,8 +37,16 @@类appfixtures延伸夹具$评论1-> setauthor('fabien');$ compy1-> setemail('[电子邮件受保护]');$评论1-> setext('这是一个很棒的会议。);+ $ comment1 - >设置状态(“发表”);经理- >保存($ comment1);+ $评论2. =新评论();+ $ comment2 - > setConference阿姆斯特丹($);+ $ comment2 - > setAuthor(卢卡斯);+ $ comment2 - > setEmail ('[电子邮件受保护]');+ $comment2->setText('我认为这个将被节制');+ $经理- >保存($ comment2);+$admin = new admin ();管理- > setRoles ([' ROLE_ADMIN ']);管理- > setUsername(管理);

コントローラーのテストでは,バリデーションをシミュレートします:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
--- a / tests / controller / conferenceControllert.php+ + + b /测试/控制器/ ConferenceControllerTest.php@@ 2,6 +2,8 @@名称空间应用\ \测试控制器;+使用App \ Repository \ CommentRepository;+使用Doctrine \ ORM \ EntityManagerInterface;使用Sy欧宝娱乐app下载地址mfony \包\ FrameworkBundle \ \ WebTestCase测试;类ConferenceControllerTest扩展了WebTestCase@@ -22,10 +24,16 @ class conferenceControllert最延伸webtestcase$client->submitForm('Submit', ['comment_form[author]' => 'Fabien', 'comment_form[text]' => '自动功能测试的一些反馈',- 'comment_form[email]' => '[电子邮件受保护]”,+ 'comment_form[email]' => $email = '[电子邮件受保护]”,'comment_form [photo]''''''''=> dirname(__ dir__,2)。'/ public / images / buxtiction.gif',]);$以下 - > assertresponseredirects();++ //模拟注释验证+ $评论= self :: $ container-> get(comment repository :: class) - > findOnebyemail($电子邮件);+ $评论- >设置状态(“发表”);+ self:: $容器- > (EntityManagerInterface::类)——>冲洗();+客户端- > followRedirect ();$this-> assertselectoreexists ('div:contains("有2个注释")');}

PHPUnit)のテストからは自我::$容器- > get ()を使えば,全てのサービス(非公開なサービスも含めて)を取得することができます。

メッセンジャーメッセンジャー理解する

欧宝娱乐app下载地址Symfonyで非同期処理を管理するために,メッセンジャーコンポーネントを使用します:

1
$ 欧宝娱乐app下载地址symfony composer请求信使

非非寿命が必要な际に,メッセージメッセージバスに送ってください。このバスはキューに格納され,処理を止めることなくすぐリターンされます。

コンシューマーは,継続的ににバックで动态ており,キューにある新闻メッセージを,そのメッセージに关键词た実実ししますしはアプリケーションとサーバーサーバーものサーバーサーバーサーバーでものサーバーにてて动手ます。

レスポンスがない以外は,HTTPリクエストを処理するときととても似ています。

メッセージハンドラーをコーディングする

メッセージはデータオブジェクトのクラスで,ロジックを持つべきではありません。シリアライズされ,キューに格納されます。”“シンプルなシリアライズ可能なデータのみを格納しましょう。

CommentMessageクラスを作物成:

src /信息/ CommentMessage.php
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
名称空间App \消息CommentMessage{私人$ id私人美元的上下文公共函数__constructint$ id数组美元的上下文[]){$这一点->id$ id$这一点->上下文美元的上下文公共函数getid.()int{返回$这一点->id公共函数getContext()数组{返回$这一点->上下文

メッセンジャーを使う際には,コントローラーではなくメッセージハンドラーが処理を担います。

应用MessageHandler \ネームスペース以下にCommentMessageメッセージを処理するCommentMessageHandlerクラスを作成してください:

src / MessageHandler / CommentMessageHandler.php
12 34 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
名称空间应用MessageHandler \使用应用\ \ CommentMessage消息使用App \ Repository \ CommentRepository使用App \ SpamChecker使用学说\ ORM \ EntityManagerInterface使用欧宝娱乐app下载地址symfony \ component \ messenger \ handler \ messageHandlerInterfaceCommentMessageHandler实施MessageHandlerInterface{私人spamChecker美元私人$ EntityManager.私人commentRepository美元公共函数__constructEntityManagerInterface.$ EntityManager.SpamCheckerspamChecker美元CommentRepositorycommentRepository美元{$这一点->entityManager$ EntityManager.$这一点->垃圾录spamChecker美元$这一点->CommentRepository.commentRepository美元公共函数__invoke.CommentMessage美元的消息{美元的评论$这一点->CommentRepository.->找到美元的消息->getid.());如果美元的评论{返回如果2= = =$这一点->垃圾录->getSpamScore美元的评论美元的消息->getContext())){美元的评论->setstate.'垃圾邮件');其他的{美元的评论->setstate.“发布”);$这一点->entityManager->fl();

MessageHandlerInterfaceは,マーカーインターフェースです。このインターフェースは,メッセンジャーハンドラのクラスを設定しS欧宝娱乐app下载地址ymfonyの自動登録を行います。規約では,ハンドラーのロジックは,__invoke ()メソッドに書きます。このメソッドの引数のCommentMessage型宣言から,どのクラスを処理するのか知ることができます。

コントローラーを修正します:

patch_file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17日18 19 20 21日22日23日24日25日26日27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
——/ src /控制器/ ConferenceController.php+ + + b / src /控制器/ ConferenceController.php@@ -5,14 +5,15 @@ namespace app \ controller;使用App \实体\评论;使用App \实体\会议;使用App \ \ CommentFormType形式;+使用app \ message \ compounmessage;使用App \ Repository \ CommentRepository;使用App \ Repository \ ConferenceRepository;用程序\ SpamChecker;使用doctrine \ orm \ entityManagerInterface;使用sy欧宝娱乐app下载地址mfony \ bundle \ frameworkbundle \ controller \ AbstractController;使用sy欧宝娱乐app下载地址mfony \ component \ httpfoundation \ file \异常\ fileexception;使用sy欧宝娱乐app下载地址mfony \ component \ httpfoundation \请求;使用sy欧宝娱乐app下载地址mfony \ component \ httpfoundation \响应;+使用Sy欧宝娱乐app下载地址mfony \组件\ \ MessageBusInterface使者;使用Sy欧宝娱乐app下载地址mfony \组件\路由\注释\路线;用树枝\环境;@@ -20,11 +21,13 @@类ConferenceController扩展了抽象的控制器{私人美元树枝;私人entityManager美元;+私人班车;- public function __construct(Environment $twig, EntityManagerInterface $entityManager)+ public function __construct(Environment $twig, EntityManagerInterface $entityManager, MessageBusInterface $bus){$ this-> twig = $ thig;$此 - > entityManager = $ EntityManager;+ $以下 - >总线= $总线;}#[路线('/',名称:'主页')]@@ -36,7 +39,7 @@类ConferenceController扩展了AbstractController} #(路线(“/会议/{蛞蝓}”,名字:“会议”))- public function show(Request $ Request, Conference $ Conference, CommentRepository $ CommentRepository, SpamChecker $ SpamChecker, string $photoDir): Response+ public function show(Request $ Request, Conference $ Conference, CommentRepository $ CommentRepository, string $photoDir): Response{$comment = new comment ();$this->createForm(CommentFormType::class, $comment); / /注释@@ -54,6 +57,7 @@类ConferenceController扩展了AbstractController$以下 - > entityManager->持续存在($评论);+ $ this-> entityManager-> Flush();$context = ['user_ip' => $request->getClientIp(),@@ -61,11 +65,8 @@类ConferenceController扩展了AbstractController“推荐人”= >请求- >标题- >获取美元(“推荐人”)、“永久链接”= >请求- > getUri ()];- if (2 === $spamChecker->getSpamScore($comment, $context)) {-抛出新的\RuntimeException('明面垃圾邮件,走开!');- - - - - -}- $ this - > entityManager - >冲洗();+ $this->bus->dispatch(new CommentMessage($comment->getId(), $context));返回$this->redirectToRoute('会议',['会议' => $会议->getSlug()]);}

スパムスパムバスにディスパッチするようになりましましなりなりましましせせかを决めさせせか决め决めさせせましましささせましをましささするましましましさささましましましましさするするましましましましましましましましましましましする决めましましましましするするましましましましましましましましするましましましましましましましましましましましましましましましなりましましましましましましましなりなりなりなりなりましましなりましチェッカースパムのではなくのではなくスパムスパムチェッカーのではなくスパムスパムスパムチェッカーチェッカーのではなくのではなくのではなくチェッカーチェッカーチェッカーそしてなりましましましましましましましましなりましましましましましましましましまし

コントローラーとスパムチェックを隔離し,ロジックを新しいクラスのハンドラーに移動しました。バスの良いユースケースです。コードをテストして,動作するか確認してください。全て同期的に実行されますが,コードは,“ベター”になっています。

表示されるコメントを制限する

表示ロジックを変更し,公式されていコメントをフロントへ表示表示ないににしう

patch_file.
12 3 4 5 6 7 8 9 10 11 12
——/ src /仓库/ CommentRepository.php+++ b / src /存储库/注释repository.php@@ -27,7 +27,9 @@类CommentRepository扩展了ServiceEntityRepository{$ query = $ this-> createquerybuilder('c') - > andwhere('c.comference =:conference')+  - > andwhere('c.state =:state')- > setParameter(“会议”,会议美元)+ - > setParameter(“国家”、“发表”)- > orderBy (c。create at ', 'DESC') ->setMaxResults(self::PAGINATOR_PER_PAGE) ->setFirstResult($offset)

実際に非同期にする

デフォルトでは,ハンドラハンドラ,同同的にに处し。非非同ににするためため,配置/包/ messenger.yamlの設定ファイルに,ハンドラがどのキューを使用するかを明示的に設定してください:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
--- A / .env+ + + b / .env@@ -29年7 + 29日7 @@ DATABASE_URL = " postgresql: / / 127.0.0.1:5432 / db吗?serverVersion = 13 charset = utf8 "###> 欧宝娱乐app下载地址symfony/messenger ### #选择下面的一个传输- # MESSENGER_TRANSPORT_DSN =学说:/ /违约+ MESSENGER_TRANSPORT_DSN =学说:/ /违约# MESSENGER_TRANSPORT_DSN = amqp: / /客人:[电子邮件受保护]:5672 /%2f / messages#messenger_transport_dsn = redis:// localhost:6379 / messages欧宝娱乐app下载地址 ### ——/ config /包/ messenger.yaml+ + + b / config /包/ messenger.yaml@@ -5、10 +5、15 @@框架:传输:# https://symfony.c欧宝娱乐app下载地址om/doc/current/messenger.html传输配置- # async: '%env(MESSENGER_TRANSPORT_DSN)%'+异步:+ dsn: ' % env (MESSENGER_TRANSPORT_DSN) % '+选项:+ auto_setup:假+ USE_NOTIFY:TRUE+ check_delayed_interval: 60000#失败:“学说:/ /违约?queue_name =失败'# sync: 'sync://'# Route your messages to the transports- # 'App\Message\YourMessage': async+应用程序消息\ \ CommentMessage:异步

この设定では,バスに应用\ \ CommentMessage消息のインスタンスを非同期にキューへ送るようにしています。非同期キューは環境変数MESSENGER_TRANSPORT_DSNによって定義されており,.envで学说をを指すように设定されていいつまり,メッセージメッセージキューて,PostgreSQLを利用しします。

PostgreSQLのテーブルとトリガーを設定します:

1
$ 欧宝娱乐app下载地址symfony console make:迁移

そしてデータベースをマイグレーションします:

1
sy欧宝娱乐app下载地址mfony控制台原则:迁移:迁移

ちなみに

舞台裏では,欧宝娱乐app下载地址SymfonyはPostgreSQLに組み込みの,高速で,スケーラブルで,トランザクションできるpub / subシステム(/通知)を利用しています。メッセージの保存先としてPostgreSQLの代わりにRabbitMQを使いたい場合は、RabbitMQの章を読んでみてください。

メッセージを取得実行する

新しくコメントを投稿しても,スパムチェッカーは呼ばれなくなりました。getSpamScore ()メソッドでerror_log ()関数を追加して確認してみてください。代わりにキューにメッセージが入るようになったので,他のプロセスから取得され実行される準備ができました。

もうお分かりかもしれませんが,欧宝娱乐app下载地址Symfonyは,メッセージを取得し,実行するコマンドがビルトインされていますので,実行してみましょう:

1
$ 欧宝娱乐app下载地址Symfony Console Messenger:消耗Async -vv

コマンドを実行するとすぐに,コメント送信でディスパッチされたメッセージが取得され,実行されるはずです:

1 2 3 4 5 6 7 8 9 10 11
[确定]从传输“异步”的邮件消费消息。//一旦它通过Messenger:stop-workers命令接收了停止信号,工人将自动退出。//使用Control-C退出工人。11:30:20信息[messenger]收到消息app \ message \ comminymessage [“message”=> app \ message \ compounmessage ^ {...},“类”=>“app \ message \ compounmessage”] 11:30:20info [http_client]请求:“post https://80cea32be1f6.rest.akismet.com/1.1/comment-check”11:30:20信息[http_client]响应:“200 https://80cea32be1f6.rest.akismet.com/1.1/comment-check" 11:30:20 INFO [messenger] Message App\Message\CommentMessage handled by App\MessageHandler\CommentMessageHandler::__invoke ["message" => App\Message\CommentMessage^ { …},"class" => "App\Message\CommentMessage","handler" => "App\MessageHandler\CommentMessageHandler::__invoke"] 11:30:20 INFO [messenger] App\Message\CommentMessage was handled successfully (acknowledging to transport). ["message" => App\Message\CommentMessage^ { …},"class" => "App\Message\CommentMessage"]

メッセージメッセージ実行のの定理がログに书架れますが——vvフラグを渡すことでコンソールに即時的なフィードバックを得ることができます。Akismet Akismetさらに,APIの呼び出しを探すこともできます。

メッセージの取得実行は,Ctrl + Cでストップします。

ワーカーワーカーをバックグラウンドグラウンドで実実

コメントを投稿した際に,毎回メッセージ取得の起動と停止を行うのではなく,ターミナルのウィンドウやタブを開くことなく,継続的に実行するようにしましょう。

欧宝娱乐app下载地址Symfony CLIは,跑步コマンドに- dフラグを付けることでデーモンとすることができ,こういったバックグラウンドで実行するコマンドを管理することができます。

メッセージ取得実行をもう一度走らせてください。今度はバックグラウンドで送信しましょう:

1
$ 欧宝娱乐app下载地址symfony run -d——watch配置,src,模板,供应商symfony控制台信使:消费欧宝娱乐app下载地址async

——看オプションを付けることで,配置/SRC /模板/小贩/ディレクトリ内のファイルシステムに変更があった際に,欧宝娱乐app下载地址Symfonyにコマンドをリスタートさせることができます。

注釈

服务器:日志でメッセージを重複させたくない際は,——vvオプションオプション使用しないでください(ログされたメッセージとコンソールのメッセージ)。

メモリ制限やバグなどでメッセージの取得実行が停止した際は,自動的に再起動します。また,メッセージの取得実行の失敗が暴走した際は、 Symfony CLI は処理を停止します。

欧宝娱乐app下载地址服务器:日志コマンドで,PHP Webサやーバー,アプリケーションの全てのログのストリームを見ることができます:

1
sy欧宝娱乐app下载地址mfony美元服务器:日志

服务器:状态コマンドを使えば,現在のプロジェクトで管理されているバックグランドのワーカーの全ての一覧を表示できます:

1 2 3 4
$ 欧宝娱乐app下载地址symfony服务器:状态Web服务器侦听https://127.0.0.1:8000命令symfony控制台Messenger:使用PID运行的Async15774观看配置/,SRC /,模板/

ワーカーを停止するには,Webサーバーを止めるか,服务器:状态コマンドで得られるPIDをキルしてください:

1
15774

メッセージの失败をリトライする

メッセージ取得実行の際に,Akismetが落ちていたらどうしますか吗?コメントの投稿者には何も影響はありませんが,メッセージを失うことになり,スパムはチェックされません。

メッセンジャーには,メッセージのハンドリングで例外になったらリトライする機構があるので,設定してみましょう:

patch_file.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
——/ config /包/ messenger.yaml+ + + b / config /包/ messenger.yaml@@ -1,7 +1,7 @@#取消注释this(和下面失败的传输),将失败的消息发送到这个传输以便稍后处理。—# failure_transport:失败+ failure_transport:失败传输:# https://symfony.c欧宝娱乐app下载地址om/doc/current/messenger.html传输配置@@ -10,7 +10,10 @@框架:选项:USE_NOTIFY:TRUE CHECK_DELAYED_INTERVAL:60000- # failed: 'doctrine://default?queue_name =失败'+ retry_strategy:+ max_retries: 3+乘法器:2+失败:'Doctrine://默认值?queue_name =失败'# sync: 'sync://'

メッセージのハンドリングに問題が起きた際に,メッセージの取得実行は諦めるまでに3回リトライをします。ただし,メッセージを廃棄するのではなく,恒久的に失败的キューに保存します。失败的キューは通常のキューとは別のデータベーステーブルを利用します。

失败したたメッセージを,再実行するには次のコマンド使使使

1 2 3
$ 欧宝娱乐app下载地址symfony console messenger:failed:重试

欧宝娱乐app欧宝体育应用最新版app下载下载地址symfonycloudでワーカーを実行する

PostgreSQLからメッセージ取得実行をするには,Messenger:消费コマンドを継続的に実行する必要があります。これはS欧宝娱乐app欧宝体育应用最新版app下载下载地址ymfonyCloudのワーカーの役割です:

patch_file.
1 2 3 4 5 6 7 8 9 10 11
——/ .sy欧宝娱乐app下欧宝体育应用最新版app下载载地址mfony.cloud.yaml+++ b /欧宝娱乐app下欧宝体育应用最新版app下载载地址 .symfony.cloud.yaml@@ -50,3 +50,8 @@钩子:设置-x -e (>&2 sy欧宝娱乐app下载地址mfony-deploy)++工人:+消息:+命令:+ start: 欧宝娱乐app下载地址symfony console messenger:consume async -vv——time-limit=3600——memory-limit=128M

欧宝娱乐app下载地址Symfony CLIのよ欧宝体育应用最新版app下载うに,SymfonyCloudマネージャーはログをリスタートします。

ワーカーのログを取得するはは,以下のようにしくださいください

1
$ 欧宝娱乐app下载地址symfony logs——worker所有的消息

这项工作,包括代码样本,是在一个Creative Commons BY-NC-SA 4.0许可证。