LoginSignup
2
1

More than 3 years have passed since last update.

Laravelでデータベースを操作する(クエリビルダ編)

Last updated at Posted at 2020-06-13

目次

Laravelの記事一覧は下記
PHPフレームワークLaravelの使い方

Laravelバージョン

動作確認はLaravel Framework 7.19.1で行っています

前提条件

eclipseでLaravel開発環境を構築する。デバッグでブレークポイントをつけて止める。(WindowsもVagrantもdockerも)
本記事は上記が完了している前提で書かれています
プロジェクトの作成もapacheの設定も上記で行っています

Laravelで入力値エラーチェック(validate)を実装する
Laravelでフラッシュデータ(直後のHTTPリクエストの間だけセッションに保存されるデータ)を使う
本記事は上記の内容を理解している前提で書かれています

LaravelでDIを使う
本記事は上記で作成したフォルダとファイルを使用します

Laravelでデータベースを扱う準備をする
Laravelでテーブル作成
Laravelで初期データ投入
本記事は上記ので作成したデータベースとレコードを使用します

サービスクラス作成

(1) /sample/app/Services/InterfacesフォルダにTable2Service.php作成

Table2Service.php
<?php
namespace App\Services\Interfaces;

interface Table2Service
{
    public function __construct();

    public function select($id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
    public function insert($table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
    public function update($id, $table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
    public function delete($id);

}

(2) /sample/app/Services/ImplフォルダにTable2ServiceImpl.php作成

App\Services\Impl\Table2ServiceImpl.php
<?php
namespace App\Services\Impl;

use App\Services\Interfaces\Table2Service;
use Illuminate\Support\Facades\DB;

class Table2ServiceImpl implements Table2Service
{

    public function __construct()
    {

    }

    public function select($id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {

        $db = DB::table('table2')
                    ->leftJoin('table1', 'table2.table1_id', '=', 'table1.id')
                    ->leftJoin('table3', 'table2.id', '=', 'table3.table2_id')
                    ->select([
                        'table1.id            as table1_id',
                        'table1.varchar_col   as table1_varchar_col',
                        'table1.int_col       as table1_int_col',
                        'table1.datetime_col  as table1_datetime_col',
                        'table1.date_col      as table1_date_col',
                        'table1.time_col      as table1_time_col',
                        'table2.id            as table2_id',
                        'table2.varchar_col   as table2_varchar_col',
                        'table2.int_col       as table2_int_col',
                        'table2.datetime_col  as table2_datetime_col',
                        'table2.date_col      as table2_date_col',
                        'table2.time_col      as table2_time_col',
                        'table3.id            as table3_id',
                        'table3.varchar_col   as table3_varchar_col',
                        'table3.int_col       as table3_int_col',
                        'table3.datetime_col  as table3_datetime_col',
                        'table3.date_col      as table3_date_col',
                        'table3.time_col      as table3_time_col',
                    ]);

        if (!is_null($id)) {
            $db->where('table2.id', '=', $id);
        }
        if (!is_null($varchar_col)) {
            $db->where('table2.varchar_col', 'like', '%'. addcslashes($varchar_col, '\\_%') . '%');
        }
        if (!is_null($int_col)) {
            $db->where('table2.int_col', '=', $int_col);
        }
        if (!is_null($datetime_col)) {
            $db->where('table2.datetime_col', '=', $datetime_col);
        }
        if (!is_null($date_col)) {
            $db->where('table2.date_col', '=', $date_col);
        }
        if (!is_null($time_col)) {
            $db->where('table2.time_col', '=', $time_col);
        }

        $recordList = $db->get();

        return $recordList;

    }

    public function insert($table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {
        $id = DB::table('table2')->insertGetId(
            [
                'table1_id' => $table1_id,
                'varchar_col' => $varchar_col,
                'int_col' => $int_col,
                'datetime_col' => $datetime_col,
                'date_col' => $date_col,
                'time_col' => $time_col,
            ]
        );

        return $id;

    }

    public function update($id, $table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {

        $affected = DB::table('table2')
                       ->where('id', '=', $id)
                       ->update([
                           'table1_id' => $table1_id,
                           'varchar_col' => $varchar_col,
                           'int_col' => $int_col,
                           'datetime_col' => $datetime_col,
                           'date_col' => $date_col,
                           'time_col' => $time_col,
                       ]);

        return $affected;

    }

    public function delete($id)
    {
        $affected = DB::table('table2')
                      ->where('id', '=', $id)
                      ->delete();

        return $affected;

    }

}

これがデータベースにselect、insert、update、deleteしている処理になります
コードを見ればどんなSQLが発行されるかわかると思います。説明も不要でしょう
ここで使用していないメソッドは下記で確認できます
Laravel 7.x データベース:クエリビルダ
また、トランザクションを使用したい場合は下記でできます
Laravel 7.x データベース:利用開始 データベーストランザクション

(3) /sample/tests/Services/ImplフォルダにTable2ServiceImpl.php作成

Tests\Services\Impl\Table2ServiceImpl.php
<?php
namespace Tests\Services\Impl;

use App\Services\Interfaces\Table2Service;

class Table2ServiceImpl implements Table2Service
{

    public function __construct()
    {
    }

    public function select($id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {
    }

    public function insert($table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {
    }

    public function update($id, $table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col)
    {
    }

    public function delete($id)
    {
    }

}

DI登録

(1) /sample/app/Providers/DiServiceProvider.phpに下記を追記
use App\Services\Interfaces\Table2Service;

(2) /sample/app/Providers/DiServiceProvider.phpのregisterメソッドに下記を追記
app()->singleton(Table2Service::class, $prefix . 'Table2ServiceImpl');

DiServiceProvider.phpはLaravelでDIを使うで作成したファイルです
LaravelでDIを使うでconfig/app.phpのprovidersに登録してあります

フォームリクエストの作成

/sample/app/Http/Requests/Table2Request.php作成

Table2Request.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class Table2Request extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        $method = $this->getMethod();

        $idRequire = 'nullable';
        $url = $this->url();
        $urlArray = explode("/", $url);
        $urlTail = array_pop($urlArray);
        if ($method === 'POST' && ($urlTail === 'update-query-builder' || $urlTail === 'delete-query-builder')) {
            $idRequire = 'required';
        }

        return [
            'id'               => [$idRequire, 'numeric', 'max:18446744073709551615'],
            'table1_id'        => ['nullable', 'numeric', 'max:18446744073709551615'],
            'varchar_col'      => ['nullable', 'max:255'],
            'int_col'          => ['nullable', 'integer', 'max:2147483647'],
            'datetime_col'     => ['nullable', 'date_format:Y-m-d H:i:s'],
            'date_col'         => ['nullable', 'date_format:Y-m-d'],
            'time_col'         => ['nullable', 'date_format:H:i:s'],
        ];

    }
}

Controllerにメソッド追加

(1) /sample/app/Http/Controllers/SampleController.phpにuse文を追記
use App\Http\Requests\Table2Request;
use App\Services\Interfaces\Table2Service;

(2) /sample/app/Http/Controllers/SampleController.phpにselectQueryBuilderメソッド、insertQueryBuilderメソッド、updateQueryBuilderメソッド、deleteQueryBuilderメソッドを追記

SampleController.php
    public function selectQueryBuilder(Table2Request $request, Table2Service $table2Service)
    {
        if (is_null($request->session()->get('errors'))) {
            $request->flash();
        }

        $id = $request->input('id');
        $varchar_col = $request->input('varchar_col');
        $int_col =  $request->input('int_col');
        $datetime_col =  $request->input('datetime_col');
        $date_col =  $request->input('date_col');
        $time_col =  $request->input('time_col');

        $recordList  = [];
        if ($request->getMethod() === 'POST') {
            $recordList = $table2Service->select($id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
        }

        $data = [
            'recordList' => $recordList
        ];

        return view('sample.select', $data);
    }

    public function insertQueryBuilder(Table2Request $request, Table2Service $table2Service)
    {
        if (is_null($request->session()->get('errors'))) {
            $request->flash();
        }

        $table1_id = $request->input('table1_id');
        $varchar_col = $request->input('varchar_col');
        $int_col =  $request->input('int_col');
        $datetime_col =  $request->input('datetime_col');
        $date_col =  $request->input('date_col');
        $time_col =  $request->input('time_col');

        $id  = null;
        if ($request->getMethod() === 'POST') {
            $id = $table2Service->insert($table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
        }

        $data = [
            'id' => $id
        ];

        return view('sample.insert', $data);
    }

    public function updateQueryBuilder(Table2Request $request, Table2Service $table2Service)
    {
        if (is_null($request->session()->get('errors'))) {
            $request->flash();
        }

        $id = $request->input('id');
        $table1_id = $request->input('table1_id');
        $varchar_col = $request->input('varchar_col');
        $int_col =  $request->input('int_col');
        $datetime_col =  $request->input('datetime_col');
        $date_col =  $request->input('date_col');
        $time_col =  $request->input('time_col');

        $affected  = null;
        if ($request->getMethod() === 'POST') {
            $affected = $table2Service->update($id, $table1_id, $varchar_col, $int_col, $datetime_col, $date_col, $time_col);
        }

        $data = [
            'affected' => $affected
        ];

        return view('sample.update', $data);
    }

    public function deleteQueryBuilder(Table2Request $request, Table2Service $table2Service)
    {
        if (is_null($request->session()->get('errors'))) {
            $request->flash();
        }

        $id = $request->input('id');

        $affected  = null;
        if ($request->getMethod() === 'POST') {
            $affected = $table2Service->delete($id);
        }

        $data = [
            'affected' => $affected
        ];

        return view('sample.delete', $data);
    }

先ほど作成したフォームリクエストを使って入力値を受け取り、先ほど作成したサービスクラスでデータベースアクセス処理を行っています
この記事では入力画面と完了画面を同じメソッドで処理していますが、これはメソッドを分けているとサンプルコードが長くなり、記事が見にくくなるので1つのメソッドで処理しているだけです
実際の開発ではif ($request->getMethod() === 'POST')というif文など使わずにメソッドを分けましょう

(3) /sample/routes/web.phpに下記を追記
Route::match(['get', 'post'],'sample/select-query-builder', 'SampleController@selectQueryBuilder');
Route::match(['get', 'post'],'sample/insert-query-builder', 'SampleController@insertQueryBuilder');
Route::match(['get', 'post'],'sample/update-query-builder', 'SampleController@updateQueryBuilder');
Route::match(['get', 'post'],'sample/delete-query-builder', 'SampleController@deleteQueryBuilder');

viewの作成

(1) /sample/resources/views/sample/select.blade.phpファイル作成

select.blade.php
<html>
    <head>
        <title>sample</title>
        <style>
        .sample-table {
            border-collapse:collapse;
            white-space: nowrap;
            border: 1px solid #000000;
        }
        .sample-table thead {
            background-color: #33CCFF;
            color: #FFFFFF;
            font-weight: bold;
        }
        .sample-table td {
            padding-left:10px;
            padding-right:10px;
            border: 1px solid #000000;
        }
        </style>
    </head>
    <body>

        <form action="{{ url('sample/select-query-builder') }}" method="post">
            @csrf
            @error('id')
                @foreach ($errors->get('id') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>id<input type="text" name="id" value="{{ old('id') }}"></div>
            @error('varchar_col')
                @foreach ($errors->get('varchar_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>varchar_col<input type="text" name="varchar_col" value="{{ old('varchar_col') }}"></div>
            @error('int_col')
                @foreach ($errors->get('int_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>int_col<input type="text" name="int_col" value="{{ old('int_col') }}"></div>
            @error('datetime_col')
                @foreach ($errors->get('datetime_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>datetime_col<input type="text" name="datetime_col" value="{{ old('datetime_col') }}"></div>
            @error('date_col')
                @foreach ($errors->get('date_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>date_col<input type="text" name="date_col" value="{{ old('date_col') }}"></div>
            @error('time_col')
                @foreach ($errors->get('time_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>time_col<input type="text" name="time_col" value="{{ old('time_col') }}"></div>
            <input type="submit" >
        </form>

        <br>

        <table class="sample-table">
            <thead>
                <tr>
                    <td colspan=6>table1</td>
                    <td colspan=6>table2</td>
                    <td colspan=6>table3</td>
                </tr>
                <tr>
                    <td>id</td>
                    <td>varchar_col</td>
                    <td>int_col</td>
                    <td>datetime_col</td>
                    <td>date_col</td>
                    <td>time_col</td>
                    <td>id</td>
                    <td>varchar_col</td>
                    <td>int_col</td>
                    <td>datetime_col</td>
                    <td>date_col</td>
                    <td>time_col</td>
                    <td>id</td>
                    <td>varchar_col</td>
                    <td>int_col</td>
                    <td>datetime_col</td>
                    <td>date_col</td>
                    <td>time_col</td>
                </tr>
            </thead>
            <tbody>
                @foreach ($recordList as $record)
                <tr>
                    <td>{{ $record->table1_id }}</td>
                    <td>{{ $record->table1_varchar_col }}</td>
                    <td>{{ $record->table1_int_col }}</td>
                    <td>{{ $record->table1_datetime_col }}</td>
                    <td>{{ $record->table1_date_col }}</td>
                    <td>{{ $record->table1_time_col }}</td>
                    <td>{{ $record->table2_id }}</td>
                    <td>{{ $record->table2_varchar_col }}</td>
                    <td>{{ $record->table2_int_col }}</td>
                    <td>{{ $record->table2_datetime_col }}</td>
                    <td>{{ $record->table2_date_col }}</td>
                    <td>{{ $record->table2_time_col }}</td>
                    <td>{{ $record->table3_id }}</td>
                    <td>{{ $record->table3_varchar_col }}</td>
                    <td>{{ $record->table3_int_col }}</td>
                    <td>{{ $record->table3_datetime_col }}</td>
                    <td>{{ $record->table3_date_col }}</td>
                    <td>{{ $record->table3_time_col }}</td>
                </tr>
                @endforeach
            </tbody>
        </table>


    </body>
</html>

(2) /sample/resources/views/sample/insert.blade.phpファイル作成

insert.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/insert-query-builder') }}" method="post">
            @csrf
            @error('table1_id')
                @foreach ($errors->get('table1_id') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>table1_id<input type="text" name="table1_id" value="{{ old('table1_id') }}"></div>
            @error('varchar_col')
                @foreach ($errors->get('varchar_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>varchar_col<input type="text" name="varchar_col" value="{{ old('varchar_col') }}"></div>
            @error('int_col')
                @foreach ($errors->get('int_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>int_col<input type="text" name="int_col" value="{{ old('int_col') }}"></div>
            @error('datetime_col')
                @foreach ($errors->get('datetime_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>datetime_col<input type="text" name="datetime_col" value="{{ old('datetime_col') }}"></div>
            @error('date_col')
                @foreach ($errors->get('date_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>date_col<input type="text" name="date_col" value="{{ old('date_col') }}"></div>
            @error('time_col')
                @foreach ($errors->get('time_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>time_col<input type="text" name="time_col" value="{{ old('time_col') }}"></div>
            <input type="submit" >
        </form>

        <br>

        @isset($id)
            <div>新規id:{{$id}}</div>
        @endif

    </body>
</html>

(3) /sample/resources/views/sample/update.blade.phpファイル作成

update.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/update-query-builder') }}" method="post">
            @csrf
            @error('id')
                @foreach ($errors->get('id') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>id<input type="text" name="id" value="{{ old('id') }}"></div>
            @error('table1_id')
                @foreach ($errors->get('table1_id') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>table1_id<input type="text" name="table1_id" value="{{ old('table1_id') }}"></div>
            @error('varchar_col')
                @foreach ($errors->get('varchar_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>varchar_col<input type="text" name="varchar_col" value="{{ old('varchar_col') }}"></div>
            @error('int_col')
                @foreach ($errors->get('int_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>int_col<input type="text" name="int_col" value="{{ old('int_col') }}"></div>
            @error('datetime_col')
                @foreach ($errors->get('datetime_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>datetime_col<input type="text" name="datetime_col" value="{{ old('datetime_col') }}"></div>
            @error('date_col')
                @foreach ($errors->get('date_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>date_col<input type="text" name="date_col" value="{{ old('date_col') }}"></div>
            @error('time_col')
                @foreach ($errors->get('time_col') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>time_col<input type="text" name="time_col" value="{{ old('time_col') }}"></div>
            <input type="submit" >
        </form>

        <br>

        @isset($affected)
            <div>値が変更された行数:{{$affected}}</div>
        @endif

    </body>
</html>

(4) /sample/resources/views/sample/delete.blade.phpファイル作成

delete.blade.php
<html>
    <head>
        <title>sample</title>
    </head>
    <body>

        <form action="{{ url('sample/delete-query-builder') }}" method="post">
            @csrf
            @error('id')
                @foreach ($errors->get('id') as $error)
                    <div style="color:red;">{{ $error }}</div>
                @endforeach
            @enderror
            <div>id<input type="text" name="id" value="{{ old('id') }}"></div>
            <input type="submit" >
        </form>

        <br>

        @isset($affected)
            <div>削除された行数:{{$affected}}</div>
        @endif

    </body>
</html>

動作確認

(1) http://localhost/laravelSample/sample/insert-query-builder

a.png

送信ボタンをクリックするとinsertが実行されます

(2) http://localhost/laravelSample/sample/update-query-builder

b.png

送信ボタンをクリックするとレコードが更新されます

(3) http://localhost/laravelSample/sample/delete-query-builder
c.png

送信ボタンをクリックするとレコードが削除されます

(4) http://localhost/laravelSample/sample/select-query-builder

d.png

送信ボタンをクリックするとレコードがselectされます

2
1
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
2
1