1. 返信を追加する
1. ルーティングを追加する
ログインしているユーザーのみが返信できます
ルート/api.php
.
.
.
//删除话题下方增加
$api->delete('topics/{topic}', 'TopicsController@destroy')
->name('api.topics.destroy');
//发布回复
$api->post('topics/{topic}/replies', 'RepliesController@store')
->name('api.topics.replies.store');
.
.
.
返信は特定のトピックに属している必要があるため、 topics/{topic}/replies
特定のトピックに返信を追加するように設計しました。これにより、リソースとリソースの関係がより直感的になります。
2. 増額リクエスト
ReplyRequest を作成します。
$ php artisan make:request Api/ReplyRequest
次のように変更します。
app/Http/Requests/Api/ReplyRequest.php
<?php
namespace App\Http\Requests\Api;
use Dingo\Api\Http\FormRequest;
class ReplyRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'content' => 'required|min:2',
];
}
}
authorize()
誰もが理不尽な場所に気づいているはずです、私たちはこのメソッドを繰り返し 書いています。Laravel の コマンドmake:request
で生成されたすべてのフォーム検証クラスに 1 つあります authorize()
が、DRY 原則 (Don't Reply Yourself、同じことを繰り返さない) に違反しないようにするには、リファクタリングを行う必要があります。
FormRequestを増やす
$ php artisan make:request Api/FormRequest
app/Http/Requests/Api/FormRequest.php
<?php
namespace App\Http\Requests\Api;
use Dingo\Api\Http\FormRequest as BaseFormRequest;
class FormRequest extends BaseFormRequest
{
public function authorize()
{
return true;
}
}
再度変更 ReplyRequest.php
、削除する use Dingo\Api\Http\FormRequest
方法 authorize
。
app/Http/Requests/Api/ReplyRequest.php
<?php
namespace App\Http\Requests\Api;
class ReplyRequest extends FormRequest
{
public function rules()
{
return [
'content' => 'required|min:2',
];
}
}
FormRequest
基本クラスを使用すると 、コードはより簡潔になります。Request
他のファイルは自分で変更できます 。
3. トランスを追加する
$ touch app/Transformers/ReplyTransformer.php
次のように変更します
app/Transformers/ReplyTransformer.php
<?php
namespace App\Transformers;
use App\Models\Reply;
use League\Fractal\TransformerAbstract;
class ReplyTransformer extends TransformerAbstract
{
public function transform(Reply $reply)
{
return [
'id' => $reply->id,
'user_id' => (int) $reply->user_id,
'topic_id' => (int) $reply->topic_id,
'content' => $reply->content,
'created_at' => $reply->created_at->toDateTimeString(),
'updated_at' => $reply->updated_at->toDateTimeString(),
];
}
}
4. コントローラーの追加
$ php artisan make:controller Api/RepliesController
ファイルを変更する
app/Http/Controllers/Api/RepliesController.php
<?php
namespace App\Http\Controllers\Api;
use App\Models\Topic;//注意需要更改使用的命名空间
use App\Models\Reply;
use App\Http\Requests\Api\ReplyRequest;
use App\Transformers\ReplyTransformer;
class RepliesController extends Controller
{
public function store(ReplyRequest $request, Topic $topic, Reply $reply)
{
$reply->content = $request->content;
$reply->topic_id = $topic->id;
$reply->user_id = $this->user()->id;
$reply->save();
return $this->response->item($reply, new ReplyTransformer())
->setStatusCode(201);
}
}
5.PostManのデバッグ
デバッグは成功し、ステータス コードは 201、応答本文は応答データです。インターフェイスを保存し、新しいトピック応答ディレクトリを作成します。
コードのバージョン管理
$ git add -A
$ git commit -m 'replies store'
2. 返信を削除する
この章では、投稿返信の削除機能を開発します。「削除」のような危険な機能を開発するたびに、権限制御に特別な注意を払う必要があります。Larabbs の既存の返信機能によれば、返信を削除する権限を持つ ID は次の 3 つだけです。
- 「返信の作成者」
- 「返信トピックの作成者」
- 「管理者」
次に、この機能の開発を開始し、同時に権限制御を適切に実行します。
1. ルーティングを追加する
ルート/api.php
.
.
.
//发布回复下方添加删除回复
$api->post('topics/{topic}/replies', 'RepliesController@store')
->name('api.topics.replies.store');
//删除回复
$api->delete('topics/{topic}/replies/{reply}', 'RepliesController@destroy')
->name('api.topics.replies.destroy');
.
.
.
2. コントローラーを変更する
app/Http/Controllers/Api/RepliesController.php
.
.
.
public function destroy(Topic $topic, Reply $reply)
{
if ($reply->topic_id != $topic->id) {不是当前用户回复的话题,不允许删除
return $this->response->errorBadRequest();
}
$this->authorize('destroy', $reply);
$reply->delete();
return $this->response->noContent();
}
.
.
.
ここでは destroy
既存の 認可ポリシークラスが使用されていることに注意してください 。
app/Policies/ReplyPolicy.php
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Reply;
class ReplyPolicy extends Policy
{
public function destroy(User $user, Reply $reply)
{
return $user->isAuthorOf($reply) || $user->isAuthorOf($reply->topic);
}
}
トピックの作成者とコメントの作成者のみがコメントを削除できる権限を持つように設定されています。
3.PostManのデバッグ
管理者以外のアカウントを使用し、自分が投稿していないトピックを見つけて、他の人の返信を削除して、エラー 403 権限がありませんを報告してください。
投稿した返信を削除してみます。削除が成功した場合は、204 を返します。
ここでのスクリーンショットの ID は自分の環境の ID と異なる場合があることに注意してください。実際の状況に応じてテストしてください。
コードのバージョン管理
$ git add -A
$ git commit -m 'replies destroy'
3. 返信リスト
トピックへの返信のリスト
1. ルートを追加する
最初のステップはルートを追加することです。このインターフェイスには訪問者がアクセスできることに注意してください。
ルート/api.php
.
.
.
//某个用户发布的话题下方添加 话题回复列表
$api->get('users/{user}/topics', 'TopicsController@userIndex')
->name('api.users.topics.index');
//话题回复列表
$api->get('topics/{topic}/replies', 'RepliesController@index')
->name('api.topics.replies.index');
.
.
.
2. コントローラーを変更する
app/Http/Controllers/Api/RepliesController.php
//查询话题所有评论
public function index(Topic $topic)
{
$replies = $topic->replies()->paginate(20);
return $this->response->paginator($replies, new ReplyTransformer());
}
コードは非常に単純で、ページネーションによってトピックのすべてのコメントをクエリし、 ReplyTransformer
変換されたコメント データを使用してそれを返します。
3.PostManのデバッグ
応答データには、このトピックのコメントデータとページネーションデータが含まれます。
4. Includeパラメータを調整します
必要となるのは返信データだけでなく、回答者の名前やプロフィール写真などのユーザーデータです。
もう一度読んで、 Include メカニズムを思い出してください。リソース データにネストされたリソースを返す必要がある場合 相关的其他资源
、このメカニズムを使用して迅速に実装できます。
設定 Transformer
の availableIncludes
パラメータ
app/Transformers/ReplyTransformer.php
<?php
namespace App\Transformers;
use App\Models\Reply;
use League\Fractal\TransformerAbstract;
class ReplyTransformer extends TransformerAbstract
{
protected $availableIncludes = ['user'];
.
.
.
public function includeUser(Reply $reply)
{
return $this->item($reply->user, new UserTransformer());
}
}
include=user
PostMan を使用したデバッグを再度追加しました
インクルードパラメータが多いため、データ内のユーザーデータも多くなります。
ユーザーの返信のリスト
トピックへの返信に加えて、ユーザーが投稿したすべての返信も表示される場合があります。
1. ルートを追加する
ルート/api.php
.
.
.
//话题回复列表下方添加 每个用户的回复列表
$api->get('topics/{topic}/replies', 'RepliesController@index')
->name('api.topics.replies.index');
//每个用户的回复列表
$api->get('users/{user}/replies', 'RepliesController@userIndex')
->name('api.users.replies.index');
.
.
.
2. コントローラーを変更する
app/Http/Controllers/Api/RepliesController.php
.
.
.
use App\Models\User;
.
.
.
public function userIndex(User $user)
{
$replies = $user->replies()->paginate(20);
return $this->response->paginator($replies, new ReplyTransformer());
}
.
.
.
ユーザーのすべてのコメントをページネーションで照会し、 ReplyTransformer
変換されたコメント データを使用して返します。
3. トランスの変更
返信リストには、返信トピックのタイトルを表示する必要があり、これを 回复资源
関連付ける 必要があることに注意してください话题资源
。
app/Transformers/ReplyTransformer.php
.
.
.
protected $availableIncludes = ['user', 'topic'];
.
.
.
public function includeTopic(Reply $reply)
{
return $this->item($reply->topic, new TopicTransformer());
}
.
.
.
availableIncludes
に追加され topic
、 includeTopic
応答に関連付けられたトピック モデルをクエリし、 TopicTransformer
変換を使用して返すための対応するメソッドが追加されました。
4. PostMan を使用したデバッグ
変数の設定に注意する
返品 回复数据
も可能です 回复的话题数据
。
投稿トピックのユーザーデータ
現在のクライアント インターフェイスが調整されていると仮定すると、ユーザーの返信リスト ページにはトピックのタイトルを表示するだけでなく、ユーザーのアバターと名前、つまり返信に関連付けられたトピック リソースも表示する必要があります 发布话题
。 、トピックに関連付けられたユーザーも必須のリソースです。
データをどのようにネストする必要がありますか。クライアント インターフェイスが変更されました。インターフェイスを調整する必要がありますか?
実際、コードはすでに完成しているので、クライアントはリクエストパラメータを調整するだけで済みます。
渡す include
パラメーターは であることに 注意してください。これは、パラメーターにassociations がtopic.user
含まれており、ユーザー データがトピック データ内にネストされていることを意味します。include パラメータでと の違いを見つけることができるはずです 。话题资源
用户资源
逗号
点
- カンマ - 現在のリソースに関連付けられているリソースです (
include=topic,user
;など)。 - ポイント - 現在のリソースに関連付けられているリソース、およびそれに関連付けられているリソースは、次のレベルのリソースと同等です
include=topic.user
。
返信のトピックは TopicTransformer
次のようにフォーマットされているためです。
public function includeTopic(Reply $reply)
{
return $this->item($reply->topic, new TopicTransformer());
}
したがって、 $availableIncludes
TopicTransformer に含まれるリソースには、 点
継続的なネスト関連付けを使用できます (たとえば、 ) include=topic.user,topic.category
。
例:http://{ {host}}/api/users/:user_id/replies?include=topic.user, topic.category
リソースのデータを処理しています。インターフェースが行う必要があるのは、リソース間の関連付けを使用して、クライアントがさまざまなパラメーターの組み合わせを通じて必要なリソースを取得できるようにすることです。Include メカニズムが非常に柔軟で便利であることがわかります。
N+1 問題はありますか?
ログを確認してください
$ tail -f ./storage/logs/laravel.log
DingoApi がすでに処理しています
コードのバージョン管理
$ git add -A
$ git commit -m 'replies index'
4. メッセージ通知一覧
次に 消息通知
インターフェースを開発し、トピックに対して新しい返信があった場合にトピック作成者に通知するメッセージ通知機能を開発しました。
1. ルーティングを追加する
ログインしたユーザーは自分の通知を表示できます
ルート/api.php
.
.
.
//删除回复下方添加 通知列表
$api->delete('topics/{topic}/replies/{reply}', 'RepliesController@destroy')
->name('api.topics.replies.destroy');
//通知列表
$api->get('user/notifications', 'NotificationsController@index')
->name('api.user.notifications.index');
.
.
.
ここでの 获取登录用户信息
考え方は、user
現在ログインしているユーザー、user/notifications
つまり の考え方と同じです我的通知
。
2. トランスを追加する
$ touch app/Transformers/NotificationTransformer.php
ファイルを変更する
app/Transformers/NotificationTransformer.php
<?php
namespace App\Transformers;
use League\Fractal\TransformerAbstract;
use Illuminate\Notifications\DatabaseNotification;
class NotificationTransformer extends TransformerAbstract
{
public function transform(DatabaseNotification $notification)
{
return [
'id' => $notification->id,
'type' => $notification->type,
'data' => $notification->data,
'read_at' => $notification->read_at ? $notification->read_at->toDateTimeString() : null,
'created_at' => $notification->created_at->toDateTimeString(),
'updated_at' => $notification->updated_at->toDateTimeString(),
];
}
}
ここでフォーマットする必要があるモデルは であることに注意してください Illuminate\Notifications\DatabaseNotification
。
3. コントローラーの追加
初めてエラーを報告し続けたとき: notificationController が存在しません 理由は次のとおりです。
この文を $ php 職人 make:controller Api/NotificationsController.php と書きます。これは間違っています。最後に php を追加することはできません。
$ php artisan make:controller Api/NotificationsController
ファイルを変更する
app/Http/Controllers/Api/NotificationsController.php
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Transformers\NotificationTransformer;
class NotificationsController extends Controller
{
public function index()
{
$notifications = $this->user->notifications()->paginate(20);
return $this->response->paginator($notifications, new NotificationTransformer());
}
}
ユーザーモデルの通知メソッドは、Laravel メッセージング システムによって提供されるメソッドであり、通知作成時間の逆順に並べ替えられます。
4.PostManのデバッグ
消息通知
ディレクトリ保存インターフェイスを追加しました
5. 返却データについて
返されるデータはreply_content
HTML 形式であり、クライアントはシステムの組み込み WebView UI コンポーネントを使用してレンダリングできることに気づきました。iOS には UIWebViewがあり 、Android には WebViewがあります 。
コードのバージョン管理
$ git add -A
$ git commit -m 'notifications index'
5. 未読メッセージの統計
未読メッセージの数
Web ページでは、ユーザーに未読のメッセージがある場合、ヘッダーに赤いプロンプトが表示されます。APP の場合、現在のユーザーをクエリするためのインターフェイスが必要です 未读消息数量
。
1. ルーティングを追加する
ルート/api.php
.
.
.
// 通知列表下方添加 通知统计
$api->get('user/notifications', 'NotificationsController@index')
->name('api.user.notifications.index');
//通知统计
$api->get('user/notifications/stats', 'NotificationsController@stats')
->name('api.user.notifications.stats');
.
.
.
ここでは、stats が統計を意味するstatisticsの略語であるように設計しており user/notifications/stats
、このインターフェイスは直感的に「私の通知データ統計」として表現できます。
2. コントローラーを変更する
app/Http/Controllers/Api/NotificationsController.php
.
.
.
public function stats()
{
return $this->response->array([
'unread_count' => $this->user()->notification_count,
]);
}
.
.
.
新しい通知があると、App\Observers\ReplyObserver.php
統計を作成するのに役立ちます。
// 如果评论的作者不是话题的作者,才需要通知
if ( ! $reply->user->isAuthorOf($topic)) {
$topic->user->notify(new TopicReplied($reply));
}
通知メソッドは notification_count を +1 します。つまり、 $this->user()->notification_count;
ユーザーの未読メッセージの数です。
3.PostManのデバッグ
ログインして最初にユーザーのトピックに返信し larabbs.test
、ユーザーにいくつかの未読通知を追加できます。
新しいディレクトリを追加し 消息通知
、インターフェイスを保存します。
コードのバージョン管理
$ git add -A
$ git commit -m 'notifications stats'
6. 通知を既読としてマークする
通知データをまだ既読としてマークしていません。学生によっては、 消息通知列表
インターフェイスですべての未読メッセージを既読としてマークする場合があります。リスト インターフェイスが呼び出されている限り、メッセージは既読であることを意味します。
そうすることに問題はないようですが、いくつかの原則に違反し、いくつかの問題が発生します。「Github の Restful HTTP API 設計の内訳」セクションで 、GET は安全なリクエストであると述べたことを思い出してください 。
もう 1 つ注意すべき点は、GET リクエストは安全であり、GET リクエストを通じてリソースを変更 (更新または作成) することは許可されていないことです。
消息通知列表
インターフェイスは GET リクエストであり、現時点ではリソース データを変更すべきではありません。クライアントには、ボタンなどの他の方法で既読としてマークを付けることができる場合があります 标记所有通知为已读
。インターフェースを仕様に準拠させ、より一般的なものにする必要があるため、一般にクライアントは積極的にインターフェースを呼び出してメッセージを既読としてマークする必要があります。
1. ルーティングを追加する
ルート/api.php
.
.
.
//通知统计下方添加 标记消息通知为已读
$api->get('user/notifications/stats', 'NotificationsController@stats')
->name('api.user.notifications.stats');
//标记消息通知为已读
$api->patch('user/read/notifications', 'NotificationsController@read')
->name('api.user.notifications.read');
.
.
.
ここでは Github API のStaring の部分を参照し 、PUT /user/starred/:owner/:repo
特定のウェアハウスにスターを付けるために、単一の通知を read として設計することもできます PUT /user/read/notifications/{notification_id}
が、ここでは冪等性の原則を考慮して、すべての未読メッセージをバッチで既読としてマークします。 PATCH を使用するのは詳細です。は適切であり、最終的には になるように設計されています PATCH /user/read/notifications
。
2. コントローラーを変更する
app/Http/Controllers/Api/NotificationsController.php
.
.
.
public function read()
{
$this->user()->markAsRead();
return $this->response->noContent();
}
.
.
.
markAsRead
これは前のチュートリアルですでに処理されているメソッドで、 notification_count
ユーザーを 0 に設定し、すべての未読メッセージを既読に設定します。コードは以下のように表示されます。
app\Models\User.php
public function markAsRead()
{
$this->notification_count = 0;
$this->save();
$this->unreadNotifications->markAsRead();
}
3. PostMan を使用したデバッグ
もう一度訪問してください消息通知统计接口
未読メッセージは消去されました。
コードのバージョン管理
$ git add -A
$ git commit -m 'notifications read'