[Laravel8.46.0] LaravelCollectiveのCheckboxでEditの時

{!! Form::checkbox(‘${column}’, null, false !!} だと、初期値はnullですが、editの場合は、{!! Form::checkbox(‘${column}’, null, null !!} にします。

### create
{!! Form::checkbox(‘${column}’, null, false !!}

                    <div class="custom-control custom-checkbox">
                      {!! Form::checkbox('new_release', null, false, ['class'=>'custom-control-input', 'id'=>'custom-check-1']) !!}
                      <label class="custom-control-label" for="custom-check-1">新商品</label>
                    </div>

### Edit
{!! Form::checkbox(‘${column}’, null, null !!}

                    <div class="custom-control custom-checkbox">
                      {!! Form::checkbox('new_release', null, null, ['class'=>'custom-control-input', 'id'=>'custom-check-1']) !!}
                      <label class="custom-control-label" for="custom-check-1">新商品</label>
                    </div>

チェックボックスってあまり使わないので、ドキュメントも少ない印象です。

[Laravel8.46.0] Laravel CollectiveでCountry Listを使いたい時

Select BoxでCountry Listから選択するUIを作る為、Front Endの構築時は以下のmediacollegeのHTMLをはめこんだが、いざLaravel Collectiveで実装する際には、配列で持ってないないといけないので困った。
https://www.mediacollege.com/internet/samples/html/country-list.html

どうやらCountry Listのパッケージがあるみたい。
Github: Monarobase/country-list

### country-listのインストール
$ composer require monarobase/country-list

### configのproviderとaliasesにclass追加。
./config/app.php

'providers' => [
    // ...
    Monarobase\CountryList\CountryListServiceProvider::class,
  ],
 
'aliases' => [
 // ...
 'Countries' => Monarobase\CountryList\CountryListFacade::class,
],

### controller
AdminClientsController.php

use Monarobase\CountryList\CountryListFacade;

    public function create() {

        $countries = CountryListFacade::getList('en');
        // dd($countries);
    	return view('admin.client.input', compact('countries'));
    }

### Resources
input.blade.php

<div class="form-group">
                  {!! Form::label('country', '国・地域') !!}
                  {!! Form::select('country',  $countries, null, ['class' => 'form-control col-md-4', 'placeholder' => 'Select Country...']) !!}
                </div>

上手くできました。
CountryListFacade::getList(‘en’)でcountry listを配列で取得できます。
助かった、危うく無駄な時間を過ごすところだった。。。

[Laravel8.46.0] 8.x系でLaravel Collectiveを使いたい

$ php artisan –version
Laravel Framework 8.46.0

– Laravel Collective公式のドキュメントをざっと見ます。最新バージョンは6.x系のようです。
Laravel Collective

どうもLaravelのバージョンと同じでないと不安になりますが、気にせずインストールしていきます。

$ composer require laravelcollective/html

composer.json

    "require": {
        // 省略
        "laravelcollective/html": "^6.2",
        // 省略
    },

6.2系が入ったようです。実際に使っていきます。

### configのproviderとaliasesにclass追加。
./config/app.php

'providers' => [
    // ...
    Collective\Html\HtmlServiceProvider::class,
    // ...
  ],

'aliases' => [
 // ...
 'Form' => Collective\Html\FormFacade::class,
 'Html' => Collective\Html\HtmlFacade::class,
 // ...
],

### データ挿入
– データは空の状態からコマンドラインでデータを挿入します。migrationは省略。passwordはbycrptの変換サイトで作成します。
INSERT INTO users (name, company, role_id, lang, client_name, password) VALUES (“admin”, “Test Inc.,”, 1, 1, “Taro Yamada”, “$2y$12$4EHyL825F7RvCPRMiAhyEOHjOeP4a9jOqEMxy2LdaU5wBUZXF64U2”);

### Controller
AdminController
– 設計上ではログインユーザのユーザ情報を取得する仕組みですが、テストの為(まだログイン機能を実装していない)、先ほど挿入したデータを引っ張り出します。

use App\Models\User;

public function setting(){
        // $user = Auth::user();
        $user = User::find(1);

    	return view('admin.setting', compact('user'));
    }

### Resource
setting.blade.php

<div class="card-body" width="" height="">
                {!! Form::Model($user, ['method'=>'POST', 'url' => '/admin/setting/confirm']) !!}
                <input type="hidden" name="company" value="{{ $user['company'] }}">
                <input type="hidden" name="name" value="{{ $user['name'] }}">
                <div class="form-group">
                  {!! Form::label('company', '会社名') !!} <span class="badge badge-secondary">必須</span>
                  {!! Form::text('company', null, ['class' => 'form-control col-md-12', 'disabled'=>'disabled']) !!}
                </div>
                <div class="form-group">
                  {!! Form::label('name', 'ユーザID(半角英数字)') !!} <span class="badge badge-secondary">必須</span>
                  {!! Form::text('name', null, ['class' => 'form-control col-md-6', 'disabled'=>'disabled']) !!}
                </div>
                // 省略 
              </div>
              <div class="card-footer ">
                <div class="inner">
                    {!! Form::submit('確認', ['class'=>'btn']) !!}
                </div>
              </div>
              {!! Form::close() !!}
            </div>
          </div>

大丈夫そうです。

[Laravel8.16.0] laravel collective(v6.2.0)を使う

$ composer require laravelcollective/html

laravelは8系なのに、collectiveがv6.2.0って、全然追いついてないけど、使ってみます。
L collectiveはcsrfは自動

config/app.php

'providers' => [
   // 省略
   Collective\Html\HtmlServiceProvider::class,
]

'aliases' => [
  // 省略
  'Form' => Collective\Html\FormFacade::class,
  'Html' => Collective\Html\HtmlFacade::class,
],

まず、普通のhtmlで書きます。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
	<h1>user id:{{ $user-> role_id}}</h1>
	<div class="col-md-8">
	<form method="post" action="/admin/create">
		<div class="form-group">
			<label for="title">Title:</label>
			<input class="form-control" name="title" type="text" id="title">
		</div>

		<div class="form-group">
			<label for="body">Body:</label>
			<textarea class="form-control" name="body" type="text" id="body"></textarea>
		</div>

		<div class="form-group">
			<label for="published_at">Publish On:</label>
			<input class="form-control" name="published_at" type="text" id="published_at">
		</div>
		<div class="form-group">
			<input class="btn btn-primary form-control" type="submit" value="送信">
		</div>
	</form>
	</div>
</body>
</html>

続いて、collectiveを使います。

{!! Form::open(['url' => '/admin/create']) !!}
			<div class="form-group">
				{!! Form::label('title', 'Title:') !!}
				{!! Form::text('title', null, ['class' => 'form-control']) !!}
			</div>
			<div class="form-group">
				{!! Form::label('body', 'Body:') !!}
				{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
			</div>
			<div class="form-group">
				{!! Form::label('published_at', 'Published On:') !!}
				{!! Form::text('published_at', null, ['class' => 'form-control']) !!}
			</div>
			<div class="form-group">
			{!! Form::submit('送信',['class' => 'btn btn-primary form-control']) !!}
			</div>
		{!! Form::close() !!}

ふむ、laravel8系でもcollective v6使えますね。安心した。
これを実装していきます。

extendsの条件分岐

非同期などの機能を実装する際に、同じルーティングで、blade内のインクルードファイルを切り分けたい時
-> if elseだと両方のextendsが読み込まれる為、 三項演算子(?:;)で切り分ける

## 前

@if($id == 1)
	@extends('layouts.hoge')
@else
	@extends('layouts.foo')
@endif

## 後

@extends(($id == 1) ? 'layouts.hoge':'layouts.foo')

ルーティングは要検討か。

Collectiveでのcheckboxの書き方

– view側でnameをブランケットで記述する。
– controllerのwhereInでチェックした値を呼び出せる

### blade

<div class="item">
	{!! Form::checkbox('category[]', 1, 1, ['class'=>'form-check-input']) !!}
	{!! Form::label('category[]', 'シティホテル', ['class'=>'form-check-label']) !!} 
</div>
<div class="item">
	{!! Form::checkbox('category[]', 2, 1, ['class'=>'form-check-input']) !!}
	{!! Form::label('category[]', 'ビジネスホテル', ['class'=>'form-check-label']) !!} 
</div>

### controller

if($request->has('category')){
            $Hotels = Message::where('id', $id)->whereIn('category_id', $request->input('category'))->orderBy('created_at','ASC')->paginate(2)->onEachSide(1);
        } else

input::all()の場合は、配列で渡ってくるので、そのままDBに流し込めば良い。
controller側で配列を作ろうとしたら、checkboxの最後の値しか渡ってこずに失敗しました。

blade内でのswitch文の書き方

idなどの判定で分岐が3つ以上になると、if文が冗長に感じてくるのでswitch文を使用したくなる。

@switch($hoge->id)
	@case(1)
		<li></li>
		@break
	@case(2)
	@case(3)
		<li></li>
		@break
	@default
		<li></li>
@endswitch

@case(1, 2) と書くとエラーになるので注意が必要
一般的にインデントは半角スペース4つだが、テーブル内などで分岐処理を書くと、分岐処理をしているところだけインデントが4つ右にずれるが、これはDOMにした時に揃うように左にずらすべきなのだろうか?
綺麗なコードを書いていると見られたいので、DOMのインデントを揃えたい、という欲求が頭を巡るが、レジストリの処理は殆どの変わらないし、コードの保守性は規約に沿ったほうが高まるように思えるので、いつも葛藤になる。

連想配列のデータをbuttonのonclick=”location.href=””からactionに渡したい時

やりたい事: controllerからbladeに渡ってきた複数の変数を、csv生成の為に、そのままの値で再度controllerの別のメソッドに渡したい

aタグでidをコントローラーに渡したい時は、controllerと引数を渡すだけ。

<a href="{{ action('HogeController@download', $data->id) }}"></a>

上記を踏まえて、buttonのonclickでコントローラーに連想配列のデータを渡したい時

<button type="button" value="送信" class="btn btn-success mx-auto d-block" onclick="location.href='{{ action('HogeController@download'), $data1 }}'">ダウンロード</button>

このように書くと、onclick=”location.href=””の中にシングルクオテーション(”)が入るためエラーになる

バックスラッシュでエスケープしてもダメ。

<button type="button" value="送信" class="btn btn-success mx-auto d-block" onclick="location.href='{{ action(\'HogeController@download\'), $data1 }}'">ダウンロード</button>

フォームで連想配列を渡そうと思ったが上手くいかない。

{!! Form::open(['method'=>'POST', 'action'=>['HogeController@download', $data1] ]) !!}
    {!! Form::submit('ダウンロード',['class'=>'btn btn-success', 'name'=>'download']) !!}
{!! Form::close() !!}

Facade\Ignition\Exceptions\ViewException
syntax error, unexpected

結局hiddenで引数をcontrollerに渡し、controller側で再度データを成形するしかないのか。

LaravelCollectiveのフォームでvue.jsを使って初期値を表示させたい時

laravelCollectiveでvue.jsを使うと、vue.jsが後から呼び出されるので、エラー時や戻る時にinputフォームの値がリセットされてしまう。

<div id="title">
  {!! Form::text('title', null, ['class'=>'form-control', 'placeholder'=>'タイトルを20文字以内で入力してください', 'maxlength'=>'20', 'v-model.trim'=>'message', 'autocomplete'=>'off']) !!} 
 </div>
                        @error('title')
                                <br><span class="error">{{$message}}</span>
                        @enderror

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
            el: "#title",
            data: { message: ""}
        });
</script>

### {{old(‘title’)}}をvue.jsにセット
vue.jsにセットすれば、エラー時や戻る時にinputフォームの値が表示される。

var titleValues = {!! json_encode(old('title', [])) !!};
        new Vue({
            el: "#title",
            data: { message: titleValues}
        });

Vue.jsの仕組みを理解していれば、直ぐにわかる事なのでしょうが、このトラブルシューティングに数時間かかりました。