目次
概要
「Laravel スクレイピング」で検索するとHttpクライアントしてGoutteとかGuzzleなどを使用した例が出てくるが、Laravel7からGuzzleが組み込まれているようなので、Guzzleを使用することにした。
またHttpクライアントが取得したデータの解析はDomCrawlerが良さそうだ。
下準備
guzzleがインストールされているかの確認
make appでコンテナに入ったら下記のコマンドで確認できる。
composer show guzzlehttp/guzzleDomCrawlerがインストールされているかの確認
make appでコンテナに入ったら下記のコマンドで確認できる。たぶん入っていない。エラーが出るはず。
composer show symfony/dom-crawlerDomCrwlerのインストール
composer require symfony/dom-crawler流れ
- 下準備の確認
- Laravel-Permissionのインストールされているか?
- UserモデルにHasRolesトレントが追加されているか?
- テストに使用するユーザーやロール、権限などが作成されているか?
- API認証の実装
- Laravel Sanctum(サンクタム)かPassport(パスポート)か?独自実装か?
API部分
コントローラーの作成
コントローラーファイルの作成
php artisan make:controller MaiPaso/GetCsvController以下のファイルが生成される
- app\Http\Controllers\MaiPaso\GetCsvController.php
コントローラーファイルの編集
<?php
namespace App\Http\Controllers\Gamer;
use App\Models\User;
use App\Models\Score;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ScoreController extends Controller
{
public function getUserName(Request $request) {
if ($request->user()) {
$response = response()->json(
[
'id' => $request->user()->id,
'name' => $request->user()->name,
'guild_name' => $request->user()->guild->name,
],
200,
[], // 追加ヘッダー
JSON_UNESCAPED_UNICODE // デバッグしやすいようにエスケープしない
);
return $response;
}
return response()->json(['error' => 'Not authenticated.'], 401);
}
public function saveScore(Request $request) {
if ($request->user()) {
$score = new Score();
$score->user_id = $request->user()->id;
$score->guild_id = $request->user()->guild_id;
$score->score = $request->input('score');
$score->stage_id = $request->input('stage_id');
$score->save();
return response()->json(['message' => 'Score saved successfully'], 200);
}
return response()->json(['message' => 'ERROR Unknown user'], 401);
}
}apiファイルの編集
apiを呼び出すためのルートを追加。
ここで追加した項目は/api以下に設定される。
- getUserNameであればhttp://localhost/api/getUserName
- saveScoreであればhttp://localhost/api/saveScore
<?php
// ~~~~~中略~~~~~
use App\Http\Controllers\Gamer\ScoreController;
// ~~~~~中略~~~~~
Route::get('getUserName', [ScoreController::class, 'getUserName']);
Route::post('saveScore', [ScoreController::class, 'saveScore']);呼び出し部分(簡易版)
簡易版
Postテスト用のHTML作成
<h1>テスト用フォーム</h1>
<form action="http://localhost/api/saveScore" method="POST">
<input type="text" name="score" placeholder="score">
<input type="text" name="stage_id" placeholder="stage_id">
<input type="submit" value="送信">
</form>Postテスト用のp5.js作成
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
}
function mousePressed() {
saveScore(frameCount);
background(220,0,0);
}
function saveScore(scoreValue) {
let url = 'http://localhost/api/saveScore';
let data = {
score: scoreValue,
stage: 'サンプルステージ',
};
httpPost(url, 'json', data, function(response) {
console.log(response);
});
}呼び出し部分(本命版)
コードをもらってくる
当初作りたかったUnity版。下記のサイトのクラスをそのまま使わせてもらった。
※念のためソースコード
ファイルの配置
UnityのAssets/Scripts/以下に上記のファイルを展開する。
Scripts
│ SceneScript.cs
│
└─Api
├─Base
│ BaseApi.cs
│ CoroutineHandler.cs
│ UrlHelpers.cs
│
└─SampleApi
GetWeatherApi.cs
PostSampleApi.csGETを作る
雛形をコピーして編集する
GetWeatherApi.csをコピーしてGetUserNameApi.csを作り、内容を書き換える。
using System;
namespace Api
{
/// <summary>
/// ユーザー名を取得します
/// </summary>
public class GetUserNameApi : BaseApi
{
/// リクエストパラメータ
[Serializable]
public struct Request
{
//
}
public Request request;
/// レスポンスデータ
[Serializable]
public struct Response
{
// Jsonデータの名前に一致させる
public string name;
public string guild_name;
}
public Response response;
// コンストラクタ
public GetUserNameApi()
{
BaseUrl = "http://localhost/api";
EndPoint = "/getUserName";
}
}
}Scene用のスクリプトを編集する
void Start()
{
Api.GetUserNameApi getApi = new Api.GetUserNameApi();
getApi.Get<Api.GetUserNameApi.Request>(ref getApi.request, result =>
{
if (result.isSuccess)
{
// リクエストに成功した場合
getApi.response = getApi.Response<Api.GetUserNameApi.Response>();
Debug.Log("ユーザー名取得APIのリクエストに成功しました");
Debug.Log(getApi.response.username);
userNameText.GetComponent<Text>().text = getApi.response.username;
}
else
{
// リクエストに失敗した場合
Debug.Log("ユーザー名取得APIのリクエストに失敗しました");
Debug.Log(result.error);
userNameText.GetComponent<Text>().text = "失敗";
}
});
}POSTを作る
PostSampleApi.csをコピーしてPostScoreApi.csを作り、内容を書き換える。
上の方でトラブった話をしたが、個々の部分。もとのPostSampleApi.csではcontent-typeをapplication/jsonとしていたが、これだと500エラーになってしまった。簡易版のFormと送られてきたデータを比較してapplication/x-www-form-urlencodedが正解だということに気づけた。
雛形をコピーして編集する
using System;
namespace Api
{
/// <summary>
///Scoreを保存します
/// </summary>
public class PostScoreApi : BaseApi
{
/// リクエストパラメータ
[Serializable]
public struct Request
{
public string score;
public string stage_id;
}
public Request request;
/// レスポンスデータ
[Serializable]
public struct Response
{
public string message;
}
public Response response;
// コンストラクタ
public PostScoreApi(string score, string stage_id)
{
BaseUrl = "http://localhost/api";
EndPoint = "/saveScore";
Headers.Add("content-type", "application/x-www-form-urlencoded");
request.score = score;
request.stage_id = stage_id;
}
}
}Scene用のスクリプトを編集する
// ~~~~~中略~~~~~
public static int stage_id = 0; // サーバー側に合わせるためのステージ番号
// ~~~~~中略~~~~~
void Update()
{
if (PlayerController.gameState == "gameclear")
{
string score = scoreText.GetComponent<Text>().text;
stage_id += 1;
Api.PostScoreApi postApi = new Api.PostScoreApi(score, stage_id.ToString());
postApi.Post<Api.PostScoreApi.Request>(ref postApi.request, result =>
{
if (result.isSuccess)
{
postApi.response = postApi.Response<Api.PostScoreApi.Response>();
Debug.Log("PostScoreApiのリクエストに成功しました");
}
else
{
Debug.Log("PostScoreApiのリクエストに失敗しました");
Debug.Log(result.error);
Debug.Log(postApi.response.message);
}
});認証部分(guard)よくわからないので保留中
データ更新時のリダイレクト先変更方法
データ更新時のリダイレクト先変更方法
データ更新時のリダイレクト先変更方法
データ更新時のリダイレクト先変更方法
データ更新時のリダイレクト先変更方法