[PHP][Laravel] primaryKeyが複数ある、またはint型でない場合にEloquentモデルでレコードを登録する

バージョン

Laravel 5.8

概要

複合主キーやint型以外の主キーの場合にcreate()でレコード追加しようとしたらエラーが発生する。
そんな時はモデルに以下を追加する。

public $incrementing = false;

詳細は公式を。 Eloquent:利用の開始 5.8 Laravel

主キーがint型でない場合も同様の対応で解決できる。

コード

◾️Model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class HogeTable extends Model
{
    protected $primaryKey = ['key1', 'key2'];

    public $incrementing = false;

    protected $fillable = [
        'key1',
        'key2',
        'name',
        'title',
    ];

}



PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

[PHP][Laravel][vue] vue側に大量のconfig値や定義値を渡したい

バージョン

Laravel 5.8
Vue.js 2.6.10

概要

Laravel側で管理しているconfigフォルダで管理している値や定数などを
Vue側から呼ばれたAPIに渡して判定条件や表示文字列に使用する。

渡したい値が1つや2つであれがblade側で以下のようにして渡せる。

<hoge-component code="{{ $user_code }}"></hoge-component>

しかし、大量に渡したい場合は以下に記載する方法がよい。

方法

APIのレスポンスデータに定義値などをcontroller側でまとめてセットする。
今回は以下の記事で作ったextra項目を使用する。

[PHP][Laravel] APIのResponseデータをカスタムしてシステム内でレスポンス形式をルール化・共通化する - 1分技術ブログ

コード

■controller

    /**
     * ユーザーデータ取得API
     */
    public function showUser()
    {
        $user = Auth::user();
        // ユーザー関連の定義データ取得
        $extra = self::getDefineData();
        return response()->success($user, $extra);
    }

■vue

<template>
  <!-- user_defineに格納されている値を使用できる -->
</template>

<script>
export default {
    data() {
        return {
            user_info: [],
            user_define: []
        }
    },
    mounted() {
        let self = this;
        let url = "/ajax/user/show";
        axios.get(url).then(function(response) {
            self.user_info = response.data.response;
            self.user_define = response.data.extra;
        });
    },
}
</script>

[PHP][Laravel] パスワード変更時の「現在のパスワード」チェックバリデーション

バージョン

Laravel 5.8

概要

パスワード変更機能で現在のパスワードをチェックするバリデーション処理。

コード

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;


    public static function getRules()
    {
        return [
            'password'              => ['required','confirmed','min:8','max:32'],
            'old_password'       => [
                'required', function ($attribute, $value, $fail) {
                    if (!Hash::check($value, Auth::user()->password)) {
                        $fail('現在のパスワードが違います');
                    }
                },
            ],
        ];
    }

現在のパスワード(old_password)をHash::checkでログインユーザのパスワードと比較チェック。



PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

[書籍][Laravel] 「PHPフレームワーク Laravel入門」まずはの一冊

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

結論

  • Laravelは未経験
  • 他の言語、フレームワークの経験有り
  • webアプリケーションの開発経験がある

上記に当てはまる人にとって本書はLaravelの入口として超絶におすすめできます!

理由

最後に目次項目をコピペするが、以下の内容をシンプルにまとめている。

  • ルーティング
  • bladeとcontrollerの関連
  • Request、Response、Validationの最低限の内容
  • ミドルウェア
  • モデル、DB

上記を抑えるだけで最低限の知識が身につき、
最低限の画面を作れるようになればあとは必要に応じてググれば良し。
逆に最低限の知識をネットだけで探そうとすると非常に面倒。

要するに本書は自身で問題解決するスキルを持った技術者が
入口のチュートリアルラクに突破するためのまとめサイトのようなもの。

仮にどんな書籍にしても、Laravelはバージョンを意識しないといけないので
必要に応じて公式ドキュメント( Laravel )のチェックなどは必要。
1冊だけを見るだけで全てをカバーできるようなものは存在しないと考えている。
(私のブログに書いてあるLaravel関連の内容を網羅している書籍なんてないですよね??)



ちなみに流し読み程度でポイントは掴めます。(写経するレベルでもないかな)
総時間は5時間程度。

全くの初心者向きかどうかは、私は初心者ではないのでなんとも言えないところ。

以上

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

目次

PHPフレームワーク Laravel入門 - 秀和システム あなたの学びをサポート! より

Chapter 1 Laravelを準備する
1.1 PHPフレームワークとLaravel
PHP開発の問題点
フレームワークの導入
Laravelの特徴
Laravelのサイト
Composerについて
Laravelをインストールする
1.2 Laravelを使ってみる
Laravel開発の手順
プロジェクトの作成
アプリケーションを実行する
XAMPPにデプロイする
指定のアドレスで公開する

Chapter 2 ルーティングとコントローラ
2.1 ルーティング
アプリケーションの構成
「app」フォルダについて
ルーティングと「routes」フォルダ
ルート情報の記述
トップページのルート情報
ルート情報を追加する
HTMLを出力する
ヒアドキュメントを使う
ルートパラメータの利用
必須パラメータと任意パラメータ
2.2 コントローラの利用
MVCとコントローラ
コントローラの作成
HelloController.phpをチェックする
アクションを追加する
ルートパラメータの利用
複数アクションの利用
シングルアクションコントローラ
リクエストとレスポンス
RequestおよびResponse

Chapter 3 ビューとテンプレート
3.1 PHPテンプレートの利用
ビューについて
PHPテンプレートを作る
ルートの設定でテンプレートを表示する
コントローラでテンプレートを使う
値をテンプレートに渡す
ルートパラメータをテンプレートに渡す
クエリー文字列の利用
3.2 Bladeテンプレートを使う
Bladeを使う
フォームを利用する
CSR対策について
アクションの用意
POSTのルート設定
3.3 Bladeの構文
値の表示
@ifディレクティブ
特殊なディレクティブ
繰り返しのディレクティブ
@break と @continue
$loopによるループ変数
@phpディレクティブについて
3.4 レイアウトの作成
レイアウトの定義と継承
@sectionと@yield
ベース・レイアウトを作成する
継承レイアウトの作成
コンポーネントについて
コンポーネントを作成する
サブビューについて
@eachによるコレクションビュー
3.5 ビューコンポーザ
ビューコンポーザとは?
サービスプロバイダについて
HelloServiceProviderを作成する
クロージャでコンポーザ処理を作る
サービスプロバイダの登録
ビューコンポーザを利用する
ビューコンポーザクラスの作成

Chapter 4 リクエスト・レスポンスを補完する
4.1 ミドルウェアの利用
ミドルウェアとは?
ミドルウェアを作成する
HelloMiddlewareクラス
HelloMiddlewareを修正する
ミドルウェアの実行
ビューとコントローラの修正
リクエストとレスポンスの流れ
レスポンスを操作する
グローバルミドルウェア
ミドルウェアのグループ登録
4.2 バリデーション
ユーザー入力時の問題
バリデーションを利用する
バリデーションの基本処理
エラーメッセージと値の保持
フィールドごとにエラーを表示
バリデーションの検証ルール
4.3 バリデーションをカスタマイズする
フォームリクエストについて
フォームリクエストの作成
HelloRequestクラスの基本コード
メッセージのカスタマイズ
バリデータを作成する
クエリー文字列にバリデータを適用する
エラーメッセージのカスタマイズ
条件に応じてルールを追加する
オリジナル・バリデータの作成
HelloValidatorを作成する
HelloValidatorのルールを使用する
Validator::extendを利用する
4.4 その他のリクエスト・レスポンス処理
CSRF対策とVerifyCsrfToken
クッキーを読み書きする
リダイレクトについて

Chapter 5 データベースの利用
5.1 データベースを準備する
モデルとデータベース
Laravelのアプローチ
SQLiteデータベースを準備する
DB Browser for SQLiteの導入
DB Browserのインストール
DB Browserを起動する
データベースファイルを作る
テーブルを作成する
SQL利用の場合
ダミーのレコードを追加する
DB利用のための手続き
SQLiteの設定
MySQL/PostgreSQLの設定
.envの環境変数について
5.2 DBクラスの利用
DBクラスとは?
パラメータ結合の利用
DB::insertによるレコード作成
DB::updateによる更新
DB::deleteによる削除
SQLクエリがすべて?
5.3 クエリビルダ
クエリビルダとは?
DB::tableとget
指定したIDのレコードを得る
演算記号を指定した検索
whereとorWhere
whereRawによる条件検索
並び順を指定する「orderBy」
offsetとlimit
insertによるレコード追加
updateによるレコード更新
deleteによるレコード削除
5.4 マイグレーションとシーディング
マイグレーションとは?
マイグレーションファイルの生成
マイグレーション処理について
テーブル生成の処理
テーブルの削除処理
マイグレーションを試す
シーディングについて
シーダーファイルの作成
シーディング処理について
シーダーファイルの登録
シーディングを実行する

Chapter 6 Eloquent ORM
6.1 Eloquentの基本
ORMとは?
モデルを作成する
モデルクラスのソースコード
PersonControllerを作成する
index.blade.phpを作成する
Personモデルで全レコードを得る
Personクラスにメソッドを追加する
IDによる検索
6.2 検索とスコープ
whereによる検索
スコープの利用
ローカルスコープについて
nameをスコープにする
スコープを組み合わせる
グローバルスコープについて
グローバルスコープを作成する
Scopeクラスを作成する
ScopePersonクラスを作る
6.3 モデルの保存・更新・削除
モデルの新規保存
モデルを修正する
add.blade.phpを作成する
addおよびcreateアクションを追記する
保存処理の流れ
モデルを更新する
editおよびupdateアクションを追記する
モデルの削除
モデルとDBクラスの共通性
6.4 モデルのリレーション
モデルのリレーションとは?
boardsテーブルを利用する
マイグレーションの作成
モデルの作成
BoardControllerの作成
テンプレートの作成
has Oneについて
has One結合
has Many結合
belongsTo結合
関連レコードの有無
withによるEagerローディング

Chapter 7 RESTfulサービス/セッション/ペジネーション/認証/テスト
7.1 リソースコントローラとRESTful
RESTfulとは?
マイグレーションの作成
モデルの作成
シードの作成
シードの実行
RESTコントローラの作成
リソースコントローラについて
indexおよびshowを作成する
レコードの追加
フォームを/hello/restに埋め込む
RESTfulサービスにするために
7.2 セッション
セッションについて
セッションを利用する
セッション利用アクションを作る
データベースをセッションで使う
セッションの保存先をデータベースに変更する
セッション用マイグレーションの作成
7.3 ペジネーション
ペジネーションとは?
DBクラスとsimplePaginate
ページの表示を作成する
DBクラスとモデル
ソート順を変更する
paginateメソッドの利用
リンクのテンプレートを用意する
app.cssスタイルシートについて
7.4 ユーザー認証
認証機能とAuth
データベースの準備
/helloでログインをチェックする
Authの認証関係ページ
特定ページの保護
ログイン処理の実装
7.5 ユニットテスト
ユニットテストとPHPUnit
テスト用データベースの準備
ダミーレコードの用意
ユニットテストのスクリプト作成
一般的な値のテスト
指定アドレスにアクセスする
データベースをテストする
ユニットテスト以外のテスト

[PHP][Laravel] APIのResponseデータをカスタムしてシステム内でレスポンス形式をルール化・共通化する

バージョン

Laravel 5.8

概要

レスポンスマクロを用いて、APIのレスポンスデータをカスタムして  成功時とエラー時(HTTPステースコードは200を返して、受信側でエラー処理をさせる)のフォーマットを合わせる。

コード

ServiceProviderクラスを追加する。
■app/Providers/ApiResponseServiceProvider.php (新規追加)

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;

class ApiResponseServiceProvider extends ServiceProvider
{
    /**
     * response macro
     *
     * @return void
     */
    public function boot()
    {
        // success
        Response::macro('success', function ($data = [], $extraData = []) {
            return response()->json([
                'success'  => true,
                'response' => $data,
                'extra'    => $extraData
            ]);
        });

        // error(画面側でエラー処理させる)
        Response::macro('error', function ($errMsg = '', array $errors = []) {
            return response()->json([
                'success'  => false,
                'errMsg'   => $errMsg,
                'errors'   => $errors
            ]);
        });

        // error
        Response::macro('fatalError', function ($errMsg, array $errors = [], $status = ResponseStatus::HTTP_INTERNAL_SERVER_ERROR) {
            return response()->json([
                'success'  => false,
                'status'   => $status,
                'errMsg'   => $errMsg,
                'errors'   => $errors
            ], $status);
        });
    }
}

success時にはなんでも使える領域としたextraがあると便利。

■config/app.php

    'providers' => [

        App\Providers\CoreServiceProvider::class,
        // 以下を追加
        App\Providers\ApiResponseServiceProvider::class,


    ],

これで準備は完了。使用例を記載。
■ApiHogeController.php

    public function testApi(Request $request)
    {
        $params = $request->all();

        $validator = Validator::make($params, [
            'remarks' => 'required|max:80',
        ]);
        if ($validator->fails()) {
            return response()->error($validator->errors()->all());
        }

        $fruits = Fruit::getList();
        
        return response()->success($fruits);
    }

hoge.blade.php

<script>

$(function() {

  var remarks = $('#remarks').val();
                                
  $.ajax({
    type:'POST',
    url: "{{ url('/api/hoge') }}",
    data: {remarks:remarks},
    headers: {
      'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
    },
    success:function(data){
      if(data.success){
        var fruits = data.result;
        fruits.forEach(function (ele) {
          var addDiv = '<div>' + ele.name + </div>';
          $(addDiv).appendTo('.addArea');
        });
      }else{
        alert(data.errMsg);
      }
    },
    error: function(XMLHttpRequest,textStatus,errorThrown)
    {
      console.log(textStatus);
    }
  });

});
</script>

もしresponse()->success($fruits)呼び出しでそんなメソッドないぞってエラーが出た場合について。
Laravel自体を再インストールすると解決したとstackoverflowに記載があった。
自分の場合はバージョン5.7でエラー状態になり、たまたま別件で5.8に上げることになったので
再度試したらうまくいった。



PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

[書籍][英語] 「英単語の語源図鑑」をお勧めできない人

TOEICの単語対策として「英単語の語源図鑑」を購入。

英単語の語源図鑑

英単語の語源図鑑

本の内容

ざっくり言うと英単語のパーツ毎に持つ意味を理解することに主題を置いた書籍です。

パーツ 意味
con 共に
ex 外に
dis 離れて

例えば、「exceed」ならば「ex(外に)+ceed(行く)」⇨「外に出る」⇨「超える」と
パーツに分解して単語を理解するといった感じです。

お勧めできない人

私はダメでした。
ある程度の単語力がある人がこの本で学ぼうとすると、すでに覚えいている単語が記憶から消される可能性があります。
私の単語力は金フレを6割以上覚えている程度です。

「英単語の語源図鑑」で紹介されている単語に関してはほぼ意味はわかるレベルですが、
この状態でこの本を読み進めると理解がより深くなるどころか既知の単語が記憶から消される感覚に襲われます。
例えば、compete(競争する)を知っている状態で「com(共に)+pete(求める)」と説明されると
共に求める ⇨ 共存する?? のように間違った意味がinputされていく恐れがあるのです。



この書籍は「これから英語を勉強したい人」には未知の単語の理解力を高めてくれそうですが
ある程度の単語力があれば逆効果になる恐れがあります。

[PHP][Laravel] Handler.phpで特定の例外エラー(Exception)を処理対象外としたい

バージョン

Laravel 5.7

概要

発生した例外エラー(Exception)をHandler.phpのreportメソッドでbugsnagやslackなどに通知する処理があった場合
大量に発生するような例外を処理の対象外とする。
例としてAuthenticationExceptionを除外する。

コード

■App\Exceptions\Handler.php

    // 除外したい例外クラスを追加する
    protected $dontReport = [
        \Illuminate\Auth\AuthenticationException::class,
    ];

    public function report(Exception $exception)
    {
        // shouldReport()はdontReportに含まれていないexceptionであればtrueとなる
        if ($this->shouldReport($exception)) {
            Bugsnag::notifyException($exception);
        }
        
        parent::report($exception);
    }

単純に$dontReportに追加するだけではHandler.phpのreportメソッドでは効果がないので注意。
(parent::reportメソッド側では効果があり、$logger->errorの対象外となる)
ちなみに$dontReportにある例外時は何もさせたくない場合は以下のようにする。

    public function report(Exception $exception)
    {
        if ($this->shouldntReport($e)) {
            return;
        }

        Bugsnag::notifyException($exception);
        
        parent::report($exception);
    }

shoudReportとshouldntReportがあるので都合が良い方を。