20200331のlaravelに関する記事は8件です。

Migrate:refreshもだめ、phpMyAdminもだめ。

今日、Laravelのサーバーでgit pullした後に、migrate:refreshをしようとしたらエラーが発生してしまいました。

原因は、migrationの名前を変更したことなのですが、さらに問題が発生しました。

phpMyAdminに入れねぇ。。

phpMyAdminがサーバー側のエラーで入れませんでした。

そこで考えました。

PHPでテーブル消すコード書けば良くね?

ということで、サーバーへのアクセス制限をしたのちに下のコードでテーブルを全て消しました。

<?php
$dbh = new PDO ('mysql:dbname=DB名;host=ホスト名;charset=utf8;','ユーザー名','パスワード');
$stmt = $dbh->query('SHOW TABLES');
while($re = $stmt->fetch(PDO::FETCH_ASSOC)){
  echo $re['Tables_in_DB名'].',';
  $dbh->query('DROP TABLE '.$re['Tables_in_DB名']);
}

こんな感じです。

2~3回実行して何も表示されなくなれば完璧です。

後は、php artisan migrateしましょう。

最後に

いや、これコマンドでのmysqlで済む話だったかも。。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel version5.7以前でマイグレーションエラーが発生した際に行ったこと

laravel 5.7を使用したアプリ開発時に「php artisan migrate」を行ったところ次のようなエラーメッセージが出た。

SQLSTATE[HY000]: General error: 3780 Referencing column 'user_id' and referenced column 'id' in foreign key constraint 'posts_user_id_foreign' are incompatible.

user_idがどうこう言っていたのでmigrationファイルを確認したが異常は見つからず…。

その時の自分が書いたコードが以下の通り

create_users_table.php
public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            省略
        });
    }
create_posts_table.php
public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            中略
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')
                  ->references('id')->on('users')
                  ->onDelete('cascade');
        });
    }

しばらくGoogleで検索しているとこのような下記のような記事が見つかった

Laravel 外部キー制約エラー General error: 3780 Referencing column

記事によるとどうやら外部キー制約によるエラーであることが判明。

記事の通り確認すると問題の箇所は
「create_posts_table」のほうではなく「create_users_table」の方にあった。

$table->bigIncrements('id');

と書かれていたのを

$table->Increments('id');

へと修正し、再度migrateを実行したところうまく行った!解決!!

どうやら自分が参照していたのはlaravel5.8以降のバージョンの記事であったらしくそれより以前のバージョンを使用していたためうまくかなかったらしいとのこと。

laravelにはバージョン別に様々な記事や参考書などがあるが自身が使っているバージョンの把握も大切だと学んだ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel with LAMPスタック on CentOS7 環境構築

パッケージを最新化する

sudo yum update -y

SELinuxを無効化

SELINUXdisabled に変更

sudo vi /etc/selinux/config

変更後、サーバーを再起動する

一般権限ユーザーを作成し、パスワードを設定する

sudo adduser {username}
sudo passwd {username}
sudo usermod -aG wheel {username}

ここで一旦 exit でログアウトし、作成したユーザーでログイン入り直す

rootユーザーで直接SSH接続を許可しない設定に変更する

SSHの設定ファイルの PermitRootLoginno に設定する

sudo vi /etc/ssh/sshd_config
sudo systemctl restart sshd

Apacheをインストールする

sudo yum install -y httpd mod_ssl
sudo systemctl start httpd
sudo systemctl enable httpd

MariaDBをインストールする

sudo vi  /etc/yum.repos.d/MariaDB.repo
sudo yum install -y MariaDB-server MariaDB-client
sudo systemctl start mariadb
sudo systemctl enable mariadb

MariaDB.repoは以下の通り

# MariaDB 10.4 CentOS repository list - created 2020-03-31 02:40 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.4/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

MariaDBを初期化する

sudo mysql_secure_installation

Switch to unix_socket authentication [Y/n]

上記のみ n で、その他はすべて y でOK

PHPをインストールする

sudo yum -y install epel-release
sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
sudo yum install -y --enablerepo=remi,remi-php73 php php-devel php-mbstring php-mysqlnd php-pdo php-gd php-xml php-bcmath php-imagick php-intl php-pecl-zip

post_max_size および upload_max_filesize128M に変更する

sudo vi /etc/php.ini
sudo systemctl restart httpd

Composerをインストール

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer

Node.jsをインストール

curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
sudo yum install -y nodejs

Yarnをインストール

パッケージマネージャーにYarnを使う場合、以下のコマンドでインストールする

curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
sudo yum install -y yarn

Laravelプロジェクトのセットアップ

MariaDBにデータベースを作成しておく。

以下のコマンドでMariaDBにログインし、

mysql -u root -p

データベースを作成する

create database {database} charset utf8mb4;
exit;

Composerに必要なパッケージを追加

sudo yum install -y zip unzip

インストーラーをインストールする

composer global require laravel/installer
echo 'export PATH=$HOME/.config/composer/vendor/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile

/var/www 以下の権限を設定する

sudo usermod -a -G apache {username}
sudo chown -R {username}:apache /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;

プロジェクトを作成

cd /var/www
laravel new {project}
cd {project}
cp .env.example .env
vi .env # 適宜
php artisan key:generate

apacheからファイルを書き込めるように権限を設定する

sudo chown -R apache /var/www
sudo chgrp -R apache /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;

apacheの設定を追加

sudo vi /etc/httpd/conf.d/{project}.conf
sudo systemctl restart httpd

内容は以下を参考に

<VirtualHost *:80>
  ServerName {host}
  DocumentRoot /var/www/{project}/public
  Options Indexes FollowSymLinks

  <Directory "/var/www/{project}/public">
    AllowOverride All
    <IfVersion < 2.4>
      Allow from all
    </IfVersion>
    <IfVersion >= 2.4>
      Require all granted
    </IfVersion>
  </Directory>

</VirtualHost>

ブラウザで {host} に設定したアドレスにアクセスし、Laravelのページが表示されればOK

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Aurora MySQLをLaravelプログラムと連結する方法

AWS上で展開するLaravelプログラムとAurora MySQLの連結方法について明記します。

設定は簡単です。

Laravelの .env ファイルのDB_HOSTをAmazon RDSの画面から作成済みDBのエンドポイント名をコピーして、以下の様に貼り付けるだけです。

DB_HOST=xxxxxx.cluster-yyyyy.ap-northeast-1.rds.amazonaws.com

具体的なAmazon RDS画面での確認場所は画像の通りです。
③のエンドポイント名をコピーしてください。
無題.png

これでLaravelからのAurora MySQLへの指定はできました。

DBのユーザーやパスワード設定は.envと合わせておけばIAMロールの設定はなくても大丈夫そうです。(特に設定した覚えないまま利用してます)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

漏れなく入力チェックするためのLaravelバリデーションの使い方まとめ

Laravelのバリデーション機能は多様なチェック機能がデフォルトで備わっておりとても便利です。
ですが、実際に使用していく中で入力チェックの内容に漏れがあったり抜け穴があったりと気を付けなければならない点がありましたので、バリデーションの使い方とともにまとめました。
今回まとめた内容の動作の確認はLaravel5.8にて行っております。

バリデーション機能の使い方

ここではLaravelバリデーションを使用するうえで作成するファイルや設定する箇所等についてまとめております。

バリデーション言語ファイルの設定

バリデーション言語ファイルはバリデーションエラー時のメッセージを定義するファイルになります。
バリデーションエラーメッセージは後で設定するフォームリクエストバリデーションでも設定が可能ですが、多言語化対応を行うとなった場合に対応しやすいようこのファイルで設定するのがベストです。
このファイルを作成しなくてもバリデーションチェックはできますので、使用しないのであれば読み飛ばしてください。

ファイル作成

resources\lang配下に言語ごとのディレクトリを作成し、その中にvalidation.phpを作成します。
日本語であればresources\lang\ja\validation.phpを作成します。
バリデーション言語ファイルはこちらの日本語翻訳をもとにアプリケーションに合わせて文言を設定するとよいです。
(バージョン6のものですが、5.8のものだとルールが不足しているのでこちらを提示しています)
このファイルを作成した状態でconfig/app.phpのlocaleの設定をjaに設定するとエラー時に表示されるようになります。
また、リクエストに応じて言語設定する場合はApp::setLocaleで設定した言語に応じたメッセージが表示されます。

app.php
'locale' => 'ja', 

バリデーションメッセージ設定

バリデーション言語行の設定では特定のバリデーションルールでエラーになった場合に表示するメッセージを設定します。
以下はdigitsのメッセージ設定の例になります。

validation.php
'digits' => ':attributeは:digits桁で指定してください。', 

上記の「:attribute」には表示する際にチェックする項目の属性名が入ります。
また、「:digits」にはバリデーションチェックの指定時の引数値が入ります。
引数名はバリデーションルールによって異なりますので、resources\lang\en\validation.phpなどを参考に作成します。

形式によって変わるsize系のバリデーションルールは以下のように配列で数値(numeric)、ファイル(file)、文字列(string)、配列(array)の形式ごとにメッセージを指定します。

validation.php
'between' => [
    'numeric' => ':attributeは:min~:maxで指定してください。',
    'file' => ':attributeは:min~:max kBのファイルで指定してください。',
    'string' => ':attributeは:min~:max文字で指定してください。',
    'array' => ':attributeは:min~:max個で指定してください。',
],

カスタムバリデーションメッセージ設定

カスタムバリデーション言語行の設定では特定の属性名の特定のバリデーションルールを使用した際のメッセージを指定します。
例えば、以下のように設定するとupdated_atでexistsのエラーとなった場合に指定したメッセージが表示されるようになります。
バリデーションメッセージ設定と同様に:attributeなどの引数も使用できます。

'custom' => [
    'updated_at' => [
        'exists' => 'データが更新されています。はじめから操作をやり直してください。',
    ],
],

カスタムバリデーション属性名設定

カスタムバリデーション属性名では:attributeに設定される名前を指定することができます。
例えば、以下のように設定すると、設定しない場合メッセージの:attributeにはemailと設定されるところ、メールアドレスと設定されるようになります。

validation.php
'attributes' => [
    'email'=>'メールアドレス',
],

カスタム値設定

バリデーションで指定する引数の値をメッセージに表示する際に別の値に置き換えることができます。
例えば、以下のように設定すると、:valuesに「クレジットカード」が設定されるようになり、card_noの項目が未入力の場合に「お支払いがクレジットカードの場合、カード番号も指定してください。」となります。

validation.php
'required_if' => ':otherが:valueの場合、:attributeも指定してください。',
'attributes' => [
    'card_no'=>'カード番号',
    'payment_type'=>'お支払い',
],
'values' => [
    'payment_type' => [
        '1' => 'クレジットカード' 
    ],
],
フォームリクエストバリデーションファイル
'card_no' => 'nullable|required_if:payment_type,1|numeric|digits_between:14,16',

バリデーションチェックの設定

バリデーションチェックを行う方法としてはRequestオブジェクトのvalidateメソッドを使う方法とフォームリクエストバリデーションを使用する方法があります。
フォームリクエストバリデーションの方が複雑なチェックを行うことができ、ソースコードもきれいにできるので、フォームリクエストバリデーションでチェックを行うことをおススメします。
そのため、Requestオブジェクトのvalidateメソッドを使う方法については割愛しますが、後に紹介するrulesメソッドとルールの設定方法は基本的に同じとなります。

フォームリクエストバリデーション

フォームリクエストバリデーションはFormRequestクラスを継承したクラスにバリデーションチェックルールを定義し、コントローラーのメソッドの引数のクラスに指定して使用します。
コントローラーの処理が呼ばれる前にバリデーションチェックが行われ、エラーがあった場合はメソッドの処理は行われず自動的に前のページヘリダイレクトするようになっています。

FormRequestファイル作成

作成は「php artisan make:request クラス名」のコマンドで作成します。
(この方法で作成しなくても問題はありません)
app/Http/Request配下に作成されますが、ディレクトリ分けを行う場合はディレクトリも指定します
以下のコマンドを実行するとAdminディレクトリ配下にProductRequest.phpを作成します。

php artisan make:request Admin/ProductRequest

authorizeメソッド

このメソッドではboolean型の値を返し、ユーザーがこのリクエストを行える権限を持っているかを判断するメソッドです。
falseが返るとリクエストが403 Forbiddenとなります。
この処理で権限のチェックを行う必要がない場合はtrueを返すかメソッド自体を実装しないようにしてください。

rulesメソッド

このメソッドではルールを指定した連想配列を返します。

基本は以下のようにチェックする項目名に対してルールごとにパイプ分け書き方になるかと思います。

フォームリクエストバリデーションファイル
return [
    'id' => 'nullable|exists:products,id,deleted_at,NULL',
    'tel' => 'required|numeric|digits_between:10,11',
];

regexでパイプを使用する場合やRuleクラスを使用する場合はパイプ分けを行わず、配列で指定します。

フォームリクエストバリデーションファイル
return [
    'id' => [
        'required',
        'integer',
        Rule::exists('t_goods', 'id')->where(function ($query) {
            $query->where('type', $this->type);
            $query->where('deleted_at', NULL);
        })
    ],
    'sort_by' => [
        'required',
        'string',
        'regex:/\A(created_at|amount|price|type)\z/u',
    ],
];

配列の中身に対してバリデーションチェックを行う場合は下記のようにドット記法で対象を指定します。
下記は「images[id]」のように指定されたパラメータをチェックする方法になります。

フォームリクエストバリデーションファイル
return [
    'images'  => 'nullable|array'
    'images.id' => 'required|image',
];

配列の全ての中身に対してバリデーションチェックを行う場合は下記のように「*」を指定します。
下記は「images[]」もしくは「images[0]」のように指定されたパラメータをチェックする方法になります。

フォームリクエストバリデーションファイル
return [
    'images'  => 'nullable|array'
    'images.*' => 'required|image',
];

連想配列の中身に対してバリデーションチェックを行う場合は下記のように「*」の後に属性名を指定します。
下記は「images[][id]」もしくは「images[0][id]」のように指定されたパラメータをチェックする方法になります。

フォームリクエストバリデーションファイル
return [
    'images'      => 'nullable|array'
    'images.*.id' => 'required|distinct|exists:t_images,id,deleted_at,NULL'
];

$this->属性名でリクエストの値を取得できるので、送られてきた値によってチェックする内容を変更することも可能です。
(この方法では配列中の値ごとに配列のチェックを変えるといったことはできません)
詳細は後ほど説明しますが、リクエストの種類が複数あるような場合は以下のように種類ごとにチェックルールの指定を変えることで他の種類で扱うデータをコントローラーで扱わなくて済みます。

フォームリクエストバリデーションファイル
$rules = [
    'payment_type' => 'required|integer|between:1,5',
];
switch ($this->type) {
    case 1:
        $rules += array (
            'card_no' => 'required|numeric|digits_between:14,16',
        );
        break;
    case 2:
        $rules += array (
            'bank_code' => 'required|numeric|digits:4',
        );
        break;
}
return $rules;

messagesメソッド

このメソッドはメッセージのカスタマイズが必要な場合に実装します。
validation.phpファイルに定義されている場合でもこちらで定義したルールが優先で反映されます。
多言語対応などでvalidation.phpファイルでエラーメッセージを一元管理する場合は実装しないようにします。
このメソッドでは特定のエラーの際のメッセージを指定した配列を返します。
配列の添え字に指定した条件に当てはまる場合に値に設定したメッセージが表示されるようになります。
添え字には基本「ruleで指定した属性名.ルール名」になりますが、属性名のみ、ルール名のみも可能です。

フォームリクエストバリデーションファイル
return [
    'digits_between' => ':attributeは数字:max桁以下にしてください。',
    'phone.digits_between' => ':attributeは数字:min桁以上:max桁以下にしてください。',
    'phone' => ':attributeが正しくありません。',
    'images.*.id' => ':attributeが不正です。'
    'images.*.id.required' => ':attributeは必須です。'
];

attributesメソッド

バリデーションメッセージの:attributeに設定される名前を指定することができます。
validation.phpファイルに定義されている場合でもこちらで定義したルールが優先で反映されます。
多言語対応などでvalidation.phpファイルで属性名を一元管理する場合は実装しないようにします。
このメソッドでは属性名に対するカスタム属性名を指定した配列を返します。
添え字の指定の仕方はrulesメソッドと同様です。

フォームリクエストバリデーションファイル
return [
    'goods_cd' => '商品コード',
];

withValidatorメソッド

フォームリクエストでバリデーション実行前のバリデータに対して追加の操作を行う場合に実装します。
特定の入力の際にチェックを追加するsometimesメソッドや、バリデーションルールでできないチェックを行うためのafterフックを追加できます。
ただし、エラーメッセージを直接指定する必要がありますので、多言語化対応が必要な場合はApp::isLocaleの判定で言語ごとにメッセージを定義するか、messages.phpで定義したメッセージを指定することになります。

フォームリクエストバリデーションファイル
public function withValidator($validator) { 
    // from_dateが入力されている場合のみto_dateとの関係をチェック
    $validator->sometimes('to_date', 'after_or_equal:from_date', function () {
        return !empty($this->from_date);
    });
    $validator->after(function ($validator) {
        // fieldにバリデーションエラーがない場合のみチェック
        if (!$validator->errors()->has('field')) {
            if (!isset($this->field)) {
                $validator->errors()->add('field', 'フィールドが不正です。');
                return;
            }
        }
    });
}

failedValidationメソッド

通常のHTTPリクエストの場合はリダイレクトレスポンス(リクエスト時の画面に戻ってエラーメッセージ表示)が生成され、
AJAXリクエスト時はJSONレスポンスが返されますが、それ以外の形式で失敗時のレスポンスを指定したい場合はこのメソッドを実装します。
下記はエラーをJSON形式でレスポンスする例になります。

フォームリクエストバリデーションファイル
protected function failedValidation( Validator $validator ) {
    $response['data']    = [];
    $response['status']  = 'NG';
    $response['summary'] = 'Failed validation.';
    $response['errors']  = $validator->errors()->toArray();

    throw new HttpResponseException(
        response()->json( $response, 422 )
    );
}

validationData(protected)メソッド

バリデーションのチェックを行う前に値に何かしらの処理を行いたい場合に実装します。
例えば、年月日が別々に送られてくる場合にこれらを結合した上で存在する日付かをバリデーションチェックで行いたいといったケースで使えます。
validationDataメソッドはバリデーションする対象となるデータを返すメソッドで、スーパークラスでは\$this->all()をそのまま返しています。
これを継承してリクエストの内容を編集することができます。
このメソッドで編集した内容をコントローラ側で取得するには\$request->validated()で取得します。

フォームリクエストバリデーションファイル
protected function validationData() {
    $data = $this->all();
    if (isset($data['phone'])) {
        $data['phone'] = str_replace("-", "", $data['phone']);
    }
    return $data;
}

FormRequestコントローラ設定

コントローラのリクエストを受け取るメソッドのリクエスト引数のクラスにFormRequestのクラスを指定することでバリデーションが実行されます。
バリデーションに成功した場合のみコントローラのメソッドの処理が呼び出されます。
バリデーションに失敗した場合はリダイレクトレスポンスとなり、AJAXの場合はエラーJSONでエラー内容が返されます。
リクエストの値は\$request->idの形で取得できますが、\$requestには想定していないパラメータも格納されるので注意が必要です。
\$request->validated()でデータを取得することでバリデーションチェックを行った項目のみを取得できるので、不要なデータを扱わずに済みます。
ですので、コントローラでは\$requestから直接データを取得せず\$request->validated()で取得したデータ配列から常に取得することを推奨します。
ただし、配列内の項目についてはチェックしていない項目でも配列の中に入ったままになるので注意が必要です。

コントローラ
public function store(ProductRequest $request) {
    // バリデーション済みデータの取得
    $validated = $request->validated();
    $id = $validated['id'];
}

エラーメッセージ設定

バリデーションチェックでエラーとなった場合にそのメッセージをBladeテンプレートで表示する際の設定になります。
下記のようにanyメソッドでエラーがあるかを判断できます。
全エラーメッセージを一箇所で表示するのであればallメソッドで全エラーメッセージを配列で取得し表示することもできます。

Bladeテンプレート
@if ($errors->any())
    <div class="alert alert-danger">入力内容に不備がありますエラー内容をご確認ください</div>
@endif

下記は指定フィールドにhasメソッドでエラーがあるかを判定し、ある場合にエラーメッセージをfirstメソッドで1件表示する設定になります。
指定フィールドの全エラーメッセージを表示するのであればgetメソッドでエラーメッセージを配列で取得し表示することもできます。
配列形式のフィールドのエラーメッセージはバリデーションの指定時と同じように引数に「*」を使用すれば対象のフィールドのエラーメッセージを取得できます。
配列のエラーメッセージを個別に取得したい場合は「images.0.id」のように指定すれば取得できます。

Bladeテンプレート
@if ($errors->has('id'))
    <small class="form-text text-danger">{{ $errors->first('id') }}</small>
@endif

バリデーション使用する際のノウハウ

ここからはバリデーションチェックの実装を行ってきた中で得たノウハウをまとめております。

バリデーション設定時に考慮すべきこと

Laravelのバリデーションで漏れなく入力チェックを行うために必ずルール設定でやるべきこととして次の3点挙げておきます。

送られてくるパラメータは必ずチェック項目として設定する

FormRequestでバリデーションチェックを行う場合は必ずすべてのリクエスト内容に対してルールを設定します。
前章で記述の通り、ルールを設定しないと\$request->validated()で取得できないからです。
また、ルールを設定していない項目は\$request->validated()で扱われないようにできるので、リクエストの内容をそのままEloquentでデータベースのテーブルを登録・更新するような場合は意図しない項目の変更を防ぐことができます。
(配列項目の場合は想定しない項目もそのまま入ってくるので別途対応が必要です)

必ずrequiredかnullableを最初に指定する

バリデーションチェックを行う項目は必ず以下のいずれかのチェックを最初に入れて下さい。
こちらの記事で確認されているように、チェックルールによっては想定外の動きをする場合があるので、指定を明確にします。

ルール 動作
required データがなければエラー
filled フィールドが存在する場合にデータがなければエラー
present フィールドが存在しなければエラー
nullable nullでもエラーにならない

基本的には必須の場合にrequired、そうでない場合はnullableを指定すれば問題ないです。
required_ifなどの条件必須ルールを使用する場合もnullableを必ず最初に指定してください。

フォームリクエストバリデーションファイル
'card_no' => 'nullable|required_if:payment_type,1|numeric|digits_between:14,16',

必ず型となるルールを指定する

そのリクエストの型を決めるルールを必ず指定してください。
数値であればintegerかnumelic、日付であればdateかdate_format、ファイルであればfileやimage、配列であればarray、それ以外の文字列であればstringを指定します。
フィールドが配列で送られてきた場合にエラーとなるようにするためです。
特に自由な入力を行うような項目の場合、下記のようにstringの設定を入れ忘れがちですが、この設定だとフィールド名がcomment[]と配列でデータが送られてきた場合にエラーとならないので必ず指定しましょう。

NG設定例
'comment' => 'required|max:200',

digitsなどもintegerなどを指定しなくても非数値でエラーとなりますが、配列の指定で送られるとエラーにならないので、numeric等を指定しましょう。
また、size、min、max、between、gt、gte、lt、lteは型によって動作が違うので注意してください。

バリデーションルール例

ここでは入力項目の形式や型に応じたバリデーションルールの設定例を挙げております。

ID系

更新などの際に使用するIDはexistsでテーブルへの存在チェックを行います。
Ruleクラスのexistsメソッドを使えば複雑な存在チェックが可能ですが、existsのルールは以下の形式で指定できるので大半はexistsメソッドを使わないで済む場合がほとんどだと思います。

exists:テーブル名,対象カラム名[,条件カラム,条件値,...]

以下のように基本削除されていないことも確認します。
(削除の場合は削除チェックせずあえてスルーしてもよいかと思います)

フォームリクエストバリデーションファイル
'id' => 'required|exists:t_reports,id,deleted_at,NULL',

区分値

ラジオボタン等の区分値は以下のように想定内の範囲であることを確認します。

フォームリクエストバリデーションファイル
'type' => 'required|integer|between:1,5',

booleanやacceptedは文字列、数値、boolean型と異なる型でチェックを通すので、これらを使う場合は受け入れられる値全てで問題がないことを確認しておく必要があります。

テキスト

基本的なテキスト入力の項目は以下のようになるかと思います。
stringを指定している場合のsize、min、max、betweenの指定は文字数となります。

フォームリクエストバリデーションファイル
'comment' => 'nullable|string|max:200',

alpha、alpha_dash、alpha_numはアルファベット以外の日本語などの文字も対象となる範囲が広いチェックになっているので使用する際は要注意です。
英数字等のチェックする場合は正規表現を使うようにしましょう。

数値入力

数値判定系のものとしては以下のものがあります

ルール 動作
integer 整数(小数点不可、Long値の範囲内)
numeric 数値(is_numeric関数での判定)
digits:桁数 指定した桁数の数値(小数点、マイナス不可)
digits_between:最少桁,最大桁 最少桁~最大桁の範囲の数値(小数点、マイナス不可)

integerやnumericを指定した場合はsize、min、max、betweenが値の範囲指定になります。

人数などの整数値の場合は以下のような指定になるかと思います。
betweenはminとmax、場合によってはdigits_betweenでも問題ないです。

フォームリクエストバリデーションファイル
'customer_num' => 'nullable|integer|between:0,9999',

ハイフンなしの電話番号のような場合はdigits_betweenのチェックを使います。

フォームリクエストバリデーションファイル
'phone' =>'required|numeric|digits_between:10,11',

小数点以下の桁数等を制御する場合は下記のように正規表現での制御で対応します。

フォームリクエストバリデーションファイル
'distance' => 'nullable|numeric|regex:/\A\d{1,4}(\.\d{1,3})?\z/',

数値の大小を比較する場合はgt、gte、lt、lteを使いますが、比較する対象の値が空の場合にExceptionが発生するので項目が必須でない場合はsometimesメソッドでチェックします。

フォームリクエストバリデーションファイル
$validator->sometimes('to_customer_num', 'gte:from_customer_num', function () {
    return !empty($this->from_customer_num);
});

日付

日付のチェックはdateとdate_formatがあるが、どちらかしか使えないので注意してください。
期間指定の場合はbefore、before_or_equal、after、after_or_equalで日付の比較を行うようにしましょう。

フォームリクエストバリデーションファイル
'end_date' => 'nullable|date_format:Y/m/d h:i:s|after:start_date'

ファイル

ファイル形式の場合はfileを指定します。
画像の場合はimageだけを指定すれば問題はないです。
これらを指定した場合はsize、min、max、betweenがファイルサイズ(kb)のチェックになります。
ファイルの形式を指定したい場合はmimetypesかmimesでmimetypeのチェックを行うことができます。
基本どちらかを指定すれば問題ないかと思います。
あとは、無制限に大容量のファイルをアップロードできないよう必ずファイルサイズの最大値を指定しましょう。
(サーバーソフトやPHPのアップロード容量上限にもよりますが)

フォームリクエストバリデーションファイル
'image' => 'nullable|image|mimes:jpeg,bmp,png|max:1024'

配列

リクエストが配列の場合はarrayでチェックします。
arrayを指定した場合はsize、min、max、betweenが配列の数になります。
配列の中身は必要でない場合を除きrequiredを指定し、重複が想定されない値についてはdistinctを指定しましょう。

フォームリクエストバリデーションファイル
'image' => 'nullable|array',
'image.*.id' => 'required|integer|digits_between:1,10|exists:t_images,id',

配列の中のデータの条件に応じてチェックするようなことはできないので、そのようなチェックが必要な場合はafterフックで対応してください。

正規表現

Laravelで用意されているルールでチェックできないような内容は正規表現でのチェックを検討をしましょう。
正規表現でチェックする場合は必ず文字列の開始終端の\A\zで指定します。
日本語等の2バイト文字を使用する場合はパターン修飾子uを指定します。

フォームリクエストバリデーションファイル
'reservation_number' => 'required|string|regex:/\A[a-zA-Z0-9]+\z/|size:8',

ペジネーション

Laravelの標準のペジネーションはオフセット値(表示件数×ページ)がLong最大値を超えるとエラーになるのでそうならないようバリデーションチェックを指定しておくと良いかと思います。
Intの上限値程度を上限で指定しておけば問題はないかと思います。

フォームリクエストバリデーションファイル
'page' => 'nullable|integer|between:1,9999999'

排他制御(楽観ロック)

updated_atで楽観的排他制御を行う方法になります。
ただ、この時点でトランザクションは行われていないので、更新時のトランザクション中に再度チェックを行ったほうが良いかと思います。

フォームリクエストバリデーションファイル
'updated_at' => [
    'required',
    Rule::exists('goods', 'updated_at')->where(function ($query) {
        $query->where('id', $this->report_id);
        $query->where('deleted_at', NULL);
    })],

その他

バリデーションチェックの処理に関連するノウハウになります。

バリデーションエラー時に特定の項目をフラッシュしない

通常バリデーションエラーが発生した場合はリクエストされた内容がフラッシュ(一時保存)され、入力した内容を入れた状態で元の画面に戻れるようになっています。
パスワードのようにバリデーションエラーが発生した際にその入力内容を未入力状態にするには
App\Exceptions\Handlerクラスに$dontFlashが定義されており、この配列に指定されているフィールド名が指定された場合はフラッシュされません。

Handler.php
protected $dontFlash = [
    'password',
    'password_confirmation',
];

リダイレクト先がおかしくなる

バリデーションでエラーになった際、リクエスト時の画面に戻ってエラーメッセージ表示とならない現象が発生することがあります。
過去に遭遇したのは、axiosのGETメソッドでAPIにリクエストを送信した後にフォームリクエストでPOSTメソッドでリクエストした内容がバリデーションエラーとなると、axiosで送った処理にリダイレクトされてしまうというものでした。
原因は、axiosのAPIへのリクエストがLaravelで直前の画面だと判断されてしまっていたことでした。
エラー時のリダイレクト先はIlluminate\Session\Middleware\StartSessionのstoreCurrentUrlの処理で記憶しており、下記の条件文に当てはまる場合に保存されます。

StartSession.php
if ($request->method() === 'GET' &&
    $request->route() &&
    ! $request->ajax() &&
    ! $request->prefetch())

この時はaxiosのAPIへのリクエストをPOSTメソッドでの送信に変更するという方法で対処しました。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mac Laravel 7 Authを用いたユーザ登録 ログイン ログアウトなどの機能を作成する

目的

  • Laravel6以降のバージョンのアプリでAuthを用いたログイン系の機能を付与する方法をまとめる。

ちょっとした知識

  • Authの機能はLaravel6以降だとデフォルトで用意されなくなった。
  • Laravel6以降でAuthの機能を使用したい場合は本作業を実施する必要がある。

実施環境

  • ハードウェア環境(下記の二つの環境で確認)
項目 情報 備考
OS macOS Catalina(10.15.3)
ハードウェア MacBook Air (11-inch ,2012)
プロセッサ 1.7 GHz デュアルコアIntel Core i5
メモリ 8 GB 1600 MHz DDR3
グラフィックス Intel HD Graphics 4000 1536 MB
項目 情報
OS macOS Catalina(10.15.3)
ハードウェア MacBook Pro (16-inch ,2019)
プロセッサ 2.6 GHz 6コアIntel Core i7
メモリ 16 GB 2667 MHz DDR4
グラフィックス AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.3 Homwbrewを用いて導入
Laravel バージョン 7.0.8 commposerを用いて導入
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いて導入

前提条件

  • お使いのMacにNode.jsがインストールされていること。
  • ローカル開発環境でサーバを起動してブラウザから確認できるLaravel6以上のアプリがあること。
  • デフォルトのusersテーブル作成のマイグレーションファイルのマイグレートが完了していること。

実施方法概要

  1. laravel/uiのインストール
  2. Authのファイル取得
  3. フロントエンド側でのモジュール組み込み
  4. 確認

実施方法詳細

  1. laravel/uiのインストール

    1. アプリ名ディレクトリで下記コマンドを実行する。(環境にもよるが若干時間がかかる)

      $ composer require laravel/ui
      
  2. Authのファイル取得

    1. アプリ名ディレクトリで下記コマンドを実行する。

      $ php artisan ui vue --auth
      
  3. フロントエンド側でのモジュール組み込み

    1. アプリ名ディレクトリで下記コマンドを実行する。

      $ npm install && npm run dev
      
  4. 確認

    1. ローカルサーバを起動して下記のリンクにアクセスして下記の様に表示されることを確認する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでjQueryを使ってAjax通信する時のURLの書き方は注意!

こんにちは、Web初心者のはるまきです。Qiita初投稿!

LaravelでJavaScriptを記述する時のパスの書き方には少し注意が必要だなと思ったので、メモしておきます。単純な話ですけど:sunny:

ルーターに合わせてパスを書こう!

初心者あるあるだとは思うんですが、「お手本通りやってもうごかな〜い!」。私の場合はjQueryのAjax通信が、それでした。お手本のコードはこんな感じでした。

hoge.js
$.ajax({
  type: "GET",
  url: "some.php", 他にも[../aaa/bbb/ccc.php]とか
}).done(function( msg ) {
  alert( "データ保存: " + msg );
});

htmlでスタイルシートやjsを読み込む時のパスは、「aaa/bbb/ccc.js」のような書き方ですよね。でもphpファイルを読み込む時(?)はどうやら違うようでした。web.phpファイルにあるルートのまま記述すれば、きちんと動きました。jsファイルとルーター(web.php)。

web.php
Route::get('selectedCategoryHoge', 'hogeController@getHogeAnotherhoge');
hoge.js
$(function(){
    $('#hoge').click(function dojQueryAjax() {
        $.ajax({        
            url:'selectedCategoryHoge',
            type:'GET',
        }).done(function(data){
            //省略
        }).fail(function(data){
            //省略
        });
    });
});

URLはルーターさんに従おう!
以上になります。何かご指摘点があれば是非よろしくお願いします!

今回、生まれて初めて、hogeってヤツを使いました。fuga,piyo,foo,barとかも使ってみたい。。
最後まで読んで頂きありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】リレーションがある場合のファクトリによるテストデータの生成

ファクトリでリレーションがあるモデルのテストデータを生成するパターンをメモしています。
公式リファレンス(データベースのテスト)

親子関係

User(親)->Movie(子)のように、二つのテーブル間の親子関係なら公式リファレンスにある方法で簡単にテストデータを生成できます。each()とモデルのリレーションメソッドを利用します。

factory(App\Models\User::class)
    ->create()
    ->each(function ($user) {
         $user->movies()->save(factory(App\Models\Movie::class)->make());
    });

親子孫関係

User(親)->Movie(子)->Review(孫)のように三つ以上のテーブル間に関係がある場合は上の方法をそのまま使うことはできません。なので外部キーとなる属性をオーバライドしてリレーションを構築します。

factory(App\Models\User::class)->create()->each(function ($user) {
    factory(App\Models\Movie::class)->create(['user_id' => $user->id])->each(function ($movie) {
        factory(App\Models\Review::class)->create(['movie_id' => $movie->id]);
    });
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む