3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LaravelのerrorsやoldをJavaScriptで扱いたい

Last updated at Posted at 2019-04-23

Laravelのエラーメッセージやold値をJavaScriptやそのフレームワークなどで扱うのに何かいい方法ないかなと色々試行錯誤した結果辿り着いた一つの答え
これがアンチパターンなのかどうなのかは感知しません

はじめの試行

<script>
var laravelErrors=@php print(htmlspecialchars_decode($errors))@endphp;
</script>
<script src="{{ asset('js/app.js') }}" defer></script>

最初はこれでいいかな…なんて思ってたのだけれど
TypeScriptを使った場合にどうしてもGlobal変数名の未定義警告TS2304がどうしても消せない状況になったので抜本的変更をしようと思い立った

方針とか問題点とか
・グローバル変数渡しは辞める
・まずbladeで@phpを使うのも辞めたい
・bladeで使ってる$errorsやold()がそもそもどういう仕組みなのかも調べ直す
・bladeの{{}}を使うとダブルクォーテーションとかがHTMLエンティティ化してしまうのでなんか面倒
・SCRFトークンみたいにmetaタグにぶち込もう
・タグの値にJSONの文字列入れるのなんか嫌だなぁ…

ってことでとりあえず$errorsやold()はどこからとってきてるのか調べてみた
→どうやらsessionから取ってきてるみたいなのでコントローラーで

view('hoge',['sessions'=>json_encode($request->session()->all())])

とかで無理やり取ってきて表示してみたら確かにどっちも入ってた

どうやら

$request->session()->get('_old_input');
$request->session()->get('errors');

で取れる模様_old_inputにはpasswordなどの値は返ってこないようなので全取得しても特に問題はなさそう

ってことで↓こんな感じでbase64に加工してbladeに渡してみる事にした
CSRFトークンは送っても無駄っぽいので予め除外
ちなみに'e30='は{}でパースしたら空のオブジェクトになるbase64文字列

public function index(Request $request)
{
	$empty_object='{}';
	$b64_empty=base64_encode($empty_object);//'e30='
	$meta_olds=$request->session()->get('_old_input');
	if($meta_olds!==null) unset($meta_olds['_token']);
	$meta_olds=($meta_olds===null)?$b64_empty:base64_encode(json_encode($meta_olds));
	$meta_errors=$request->session()->get('errors');
	$meta_errors=($meta_errors===null)?$b64_empty:base64_encode($meta_errors);
	return view('hoge',[
		'meta_olds'=>$meta_olds,
		'meta_errors'=>$meta_errors,
	]);
}

これを受けてbladeではこんな感じにmetaに刺す

<meta name="laravel-olds" content="{{$meta_olds}}">
<meta name="laravel-errors" content="{{$meta_errors}}">

あとは
受け側のJavaScriptで以下のように取り出せばよさそう
※metaタグに最低限'e30='が入ってればatobでもJSON.parseでもエラーにはならない

var errors = JSON.parse(atob(document.head.querySelector('meta[name="laravel-errors"]').content))

TypeScriptの場合.contentがないみたいなエラーが出るのでHTMLMetaElementにキャストすればOK

var errors: object = JSON.parse(atob((<HTMLMetaElement>document.head.querySelector('meta[name="laravel-errors"]')).content))
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?