githubの秘密鍵を指定してgit pullする
こんな感じで .ssh/config
に2つ登録したとする
// .ssh/config Host github.com.first HostName github.com IdentityFile ~/.ssh/id_rsa_first User git Host github.com.second HostName github.com IdentityFile ~/.ssh/id_rsa_second User git
秘密鍵を指定して git pull
したいときはこうする
$ git pull github.com.second:組織名/リポジトリ名
公式ドキュメントにも、ここにオプションを指定しなさいと書いてある
git pull [<options>] [<repository> [<refspec>…]]
参考
【Laravel×Postman】画像を取得できない(送信できない)時は
LaravelでREST API作成中にハマった。Postmanで動作確認中。
結論
リクエストヘッダーの Content-Type
のチェックが外れていないか確認!
値は multipart/form-data; boundary=<calculated when request is sent>
となっているはず。
ハマった
こんな感じで、POSTリクエストで、Bodyを form-data
にして、ファイルを設定しているのに、Laravel側で取得できなかった。
<?php dd($request->file('image')); // 結果:null
Laravel Sanctumを使っていたので、Content-Type
を application/json
に指定していた。
色々ググってみて、Content-Type
を multipart/form-data
にしてみても効果なし。
リクエストヘッダーを全部確認してみたら、デフォルトのContent-Type
のチェックが外れていて無効になっていた。
値はmultipart/form-data
ではなく、デフォルトのmultipart/form-data; boundary=<calculated when request is sent>
でないと送信できないよう。
こんな感じだと効果なし。
参考
【Laravel】定数をクラスファイルで管理する
定数をクラスファイルで管理する
app/Consts/CommonConst.php
を作成した。
<?php namespace App\Consts; class CommonConst { const MESSAGE = 'message'; const RESULT = 'success'; }
config/app.php
でエイリアスを追加
<?php return = [ // 省略 'aliases' => [ // 省略 'CommonConst' => \App\Consts\CommonConst::class, ] ]
app/Http/Controllers/Api/UserController.php
で使用する
<?php public function index() { $users = User::where('id', Auth::id())->get(); return response()->json([CommonConst::MESSAGE => CommonConst::RESULT, 'user_info' => $users]); }
参考
【Laravel】419 CSRF token mismachエラーの対処記録
Laravel Sanctumを使ってログイン機能を実装中にエラーに遭遇。 思考の整理と次に時間を溶かさないようにするためのメモ
結論
.env
での SESSION_DOMAIN='localhost'
ここが間違えていた。
.env にてセッションを設定するドメインを設定しているので、ドメインを設定する。
開発環境なので localhost
で良い。
本番環境のドメインを指定してしまっていたので、セッションクッキーがセットされていなかったよう。考えてみれば当たり前。デプロイ時は本番のドメインを指定する。
ちなみに localhost:8000
だとエラーになるのでポート番号はいらない!
環境
Sanctumによるログインの流れ
- Laravel Sanctumをインストール
- 自動で
sanctum/csrf-cookie
というルーティングが追加されるから、ここにGETリクエストすることで、CSRF保護を初期化する。(/login
へPOSTする前に必ず実行する必要あり。これを行わないと、CSRFが照合できずエラーになる ) - レスポンスヘッダーに
XSRF-TOKEN
というクッキーが返ってくる。 - これを
X-XSRF-TOKEN
というキーでリクエストヘッダーにセットして、/login
へリクエストする。 $request->session()->regenerate();
でフロントにセッションクッキーをセット。
流れは間違っていなかったが、ドメインが間違えていたのでセッションクッキーをセットできていなかった。
調べたあれこれ
guard
// config/auth.php 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', // 'driver' => 'session', 'provider' => 'users', 'hash' => false, ], ],
- Laravel Sanctumによる認証は、webのguardを使用する。
- regiter、login、logoutあたりはセッションクッキーを使用するので、sessionドライバーを設定しているweb guardを使用する。
- api guardはデフォルトではtokenドライバーが設定されている。これをsessionに書き換えてもいいようだけど、それだと本来のAPIの仕様が薄れちゃうから微妙という記事もあった。
- 書き換えてみたら CSRF token mismachエラーはでなくなったものの、
Auth::attempt()
が使用できなくなり断念。undefind
エラーが出た。やっぱりセッションクッキーだからapiではなくてwebの方を使えということなのかな?
CSRF
\App\Http\Middleware\VerifyCsrfToken::class
の箇所でtokenの検証をしている。- フロントから送られてくる
X-XSRF-TOKEN
とLaravel側のトークンを比べている。
// app/Http/Kernel.php protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ←ここ \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
VerifyCsrfToken
クラスの詳しい動きは下記の記事が細かく載っていた。
LaravelのCSRF対策の処理を実際のコードから見てみる - Qiita
その他
- config/cors.phpに下記を追記。
// config/cors.php 'paths' => [ 'api/*', 'login', // 追記 'logout', // 追記 'register', // 追記 'sanctum/csrf-cookie' ], 'supports_credentials' => true,
参考
Laravel7 + Sanctum でSPAログイン認証機能を実装 - Qiita
Laravel API SanctumでSPA認証する - Qiita
【attemptメソッドが使えない?】Call to undefined method TokenGuard::attempt() の解決法
Laravelの標準Authentication(Auth)の動きを調べてみる - Qiita
Laravel5.4でAuth::attemptを使わずに認証処理をカスタマイズ
【Laravel】多対多でリレーション先のデータを取得する
多対多のER図
リレーション先を取得する
- モデルで追加したメソッド名を
with('メソッド名')
の引数に追加する- ※リレーション先のテーブル名やクラス名をwith()の引数にするわけではない!
// App/Models/Food.php /** * foodを持っているフードアイコン */ public function foodIcons() { return $this->belongsToMany(FoodIcon::class, 'food_food_icon', 'food_id', 'food_icon_id') ->withTimestamps(); }
// app/Http/Controllers/FoodController.php public function index() { $foods = Food::->with('foodIcons')->get(); return response()->json('foods' => $foods); }
【PHP】多次元配列を並び替えて、指定番目から指定件数のみ切り取った配列を取得
やりたいこと
PHPで、多次元配列があって、指定したキーの値で、昇順・降順の並び替えができるようにしたかった。 並び替えの後、指定した番目から指定した件数分の要素だけを取得したかった。 つまり、ページネーションのイメージ。
SQLでやればこんな感じですぐにできるが、色々あってPHPで処理することとなった。
SELECT * FROM users ORDER BY age ASC LIMIT 2, 2
$array = [ [ 'name'=> 'kenta', 'age' => 20 ], [ 'name'=> 'taro', 'age' => 10 ], [ 'name'=> 'yuki', 'age' => 15 ], [ 'name'=> 'hanako', 'age' => 25 ], [ 'name'=> 'yuji', 'age' => 30 ], ];
結論
こんな感じの関数を作った。
/** * 配列の指定番目から指定数を切り取って返す * * @param int $start * @param int $max * @param array $array * @return array */ function cutStartToMaxArray($start, $max, $array) { $tmp_array = []; for ($i = $start; $i <= count($array) - 1; $i++) { if (count($tmp_array) > $max - 1) { break; } $tmp_array[] = $array[$i]; } return $tmp_array; } /** * キーを指定してその値をもとに、多次元配列をソートして返す * * @param string $target_key * @param string $order SORT_ASC or SORT_DESC * @param string $type SORT_REGULAR or SORT_NUMERIC or SORT_STRING etc... * @param array $array * @return array */ function orderMultiArray($target_key, $order, $type, $array) { foreach ($array as $k => $v) { $order_target_array[] = $v[$target_key]; } array_multisort($order_target_array, $order, $type, $array); return $array; } $start_limit = 2; // 配列の何番目からスタート $max_count = 2; // データ数 $ordered_array = orderMultiArray('age', SORT_DESC, SORT_NUMERIC, $array) $new_array = cutStartToMaxArray($start_limit, $max_count, $ordered_array); var_dump($new_array);
// 結果 // ageで並び替えた2ページ目の2人分($new_array[2]と$new_array[3])のデータを取得 array (size=2) 0 => array (size=2) 'name' => string 'kenta' (length=5) 'age' => int 20 1 => array (size=2) 'name' => string 'hanako' (length=6) 'age' => int 25