作成日:2021/04/12 更新日:2023/03/06

#6 Laravelの仕組み〜MVCの理解〜

PHPフレームワークの基本的な仕組み〜MVC〜

ここから「名前の登録機能」と動かしたときの「座標を更新する機能」を追加していきますが、 ここで一度Laravelで作るアプリケーションの設計について確認します。
Laravelでのアプリケーション開発においてはMVCモデルという設計でアプリケーションの作成が行われます。 MVCはアプリケーション内の各処理機能の頭文字で
M = 「Model(モデル)」
V = 「View(ビュー)」
C = 「Controller(コントローラ)」
 をそれぞれ意味しています。
Modelモデルは、データの処理
データベースへのアクセス(登録/更新/削除/検索の実行)や、データの加工等々、データにまつわる処理全般を請け負うのがModelです。
Viewビューは、ブラウザに表示される画面を作る
Controllerから取得したデータをテンプレートを使ってブラウザに出力するのもViewの役割です。HTMLやJSがメイン所なので、皆さんにとっては馴染み易いかもしれません。
Controllerコントローラーは、上記の「Model」と「View」の橋渡し
画面からの入力値をModel層の処理機能へデータとして引き渡したり、 データベースから取得したデータを画面へ表示するためにView層へ渡したりと、ViewとModelの間を取り持ちます。

ここから先はデータベースへのデータ登録や検索、更新処理が出てきます。 Laravelでそれらの機能を実装するにはModelモデルControllerコントローラーの理解が必要になっていきます。

#7 Laravelでデータベースのデータを表示する方法

①以前作成したデータベースのデータを移植する

初期表示(ページにアクセスしたときに最初に表示させるページ)機能の実装を行います。
以前作成した「index.php」では下記の部分です。

<div id="drag-area">
<?php
$sql = 'SELECT * FROM sortable';
$stmt = $dbh->query($sql);
foreach ($stmt as $result)){
  echo '  <div class="drag" data-num="'.$result['id'].'" style="left:'.$result['left_x'].'px; top:'.$result['top_y'].'px;">'.PHP_EOL;
  echo '    <p><span class="name">'.$result['id'].' '.$result['name'].'</span></p>'.PHP_EOL;
  echo '  </div>'.PHP_EOL;
}
?>
</div>
まずは、マイグレーションして作成したsortablesテーブルにデータを入れていきましょう。

CSVデータのインポート

応用編1 #9に習って、csvファイルでデータをインポートしてください。

このようになります。

②bladeテンプレートでビューのdrags.blade.phpを作る

#drag-areaに表示させるテンプレート作成

分かりやすいView層から着手しましょう。
View層では、Model層から受け取ったデータを、その数だけ画面に出力する処理を記述します。
「resources」➡「views」配下に、新たに「layouts」フォルダを作成し、更にその配下に「drags.blade.php」を作成します。
drags.blade.phpの内容は以下のとおりです。

@foreach($sortables as $sortable)

<div class="drag" data-num="{{ $sortable->id }}" style="left:{{ $sortable->left_x }}px; top:{{ $sortable->top_y }}px;">
  <p><span class="name">{{ $sortable->id }} {{ $sortable->name }}</span></p>
</div>

@endforeach
スクラッチ(お手製)でphpを作った場合と、テンプレートエンジン「blade」を使う場合との違いは
{{ 変数 }}となっているところです。

▼スクラッチ▼
data-num="'.$result['id'].'"

▼blade▼
data-num="{{ $sortable->id }}"
'. → {{
.' → }}

波括弧×2つに変わっています。foreachも独特な書き方に変わります。
また、インスタンスデータ$sortableからidプロパティを出力します。

「$sortables」変数に、Model層から取得してきたデータが格納される予定です。
「@foreach」で$sortablesに格納されているデータ分だけループ処理を実行する仕組みになっています。

#drag-areaに表示させるテンプレートを読み込む

次は「sortable.blade.php」(トップページ)側で、いま作成した「drags.blade.php」を取り込む記述を追記します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>8001-cri-sortable</title>
  <link href="{{ asset('css/style.css')}}" rel="stylesheet">
</head>
<body>
<div id="wrapper">

<div id="input_form">

</div>

<div id="drag-area">
  @include('layouts.drags')   /* ←drags.blade.phpを読み込みます */
</div>

</div>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
  <script src="{{ asset('js/main.js')}}"></script>
</body>
</html>
#drag-area内に@include('ファイル名')でテンプレートを読み込みます。
「@include()」は外部のPHPファイルを取り込む為に用意されたメソッドです。引数には取り込むPHPファイルを指定します。
includeメソッドは、ファイル名.blade.phpの前の文字を認識しますので、'layouts.drags'で、layoutsフォルダのdrags.blade.php を読み込めます。

③データを取得するモデルSortable.phpを作る

次に、データ処理を担当するモデルの追加をおこないます。 ターミナルから以下のコマンドを実行してモデルファイルを作成します。

$ php artisan make:model Sortable

↓実行後にこのように表示される
Model created successfully.

appフォルダ内にSortable.phpが作られる
Modelのファイル名は必ず最初の一文字は大文字で作るのがルールとなります。
Model層はこれ以上編集する必要はほぼありません。
このファイルに記述されたデフォルトの内容だけで、自動的にデータベースへの接続を行ってくれます。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Sortable extends Model
{
  public $timestamps = false;   /* ←追加*/
}
今回作成するアプリケーションよりも複雑なアプリケーションを開発する場合には、データベースに対する要求を複数記述しますが、 今回はSortable.phpに1行だけ設定を追記しておいてください。
※データベースに、データを更新する日付を記録しておくカラムを用意していない場合は、$timestampsの値をfalseにしておきます。

namespaceやuseについて

namespaceやuseは名前空間と呼ばれています。
namespace
異なるクラスファイルで同名のクラス名を設定している場合に、どこのファイルのクラス名であるかを識別できるように名前をつけてあげます。
上記のSortableというクラスを使いたいときには名前空間がAppにっているのでuse App\Sortable;と書いてSortableクラスをnewします。

use
長いパス名を何回も使用しないで済むように、クラス名のショートカット(エイリアス)を作成します。newしたりextendsするときにスッキリして見やすいです。
例えばSortable.phpにあるuseのパス Illuminate\Database\Eloquent\Model は、/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.phpに書いてある Modelクラスを「Model」という名前で使用しますよ、ということになります。

④コントローラーのSortableController.phpを作る

次はView層とModel層の橋渡し役であるControllerの実装です。
ターミナルから以下のコマンドを実行してください。

$ php artisan make:controller SortableController

↓実行後にこのように表示される
Controller created successfully.

app/Http/Controllers フォルダ内にSortableController.phpが作られる
ファイル名は Model名+Controller となります。Model名は同じく大文字にしておきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Sortable;

class SortableController extends Controller
{
    public function index(){
      $sortable = Sortable::orderBy('id', 'asc')->get();

      return view('sortable', [
        'sortables' => $sortable
      ]);
    }
}
内容の編集を行います。Controllerファイルを開いて、上記の様に追記してください。
「sortable」が複数形になっている箇所があるので注意!
▼解説

use App\Sortable
作成したModelファイル「Sortable.php」に記述したnamespace「App」のSortableクラスをSortableという名前で使う宣言。

$sortable = Sortable::orderBy('id', 'asc')->get();
Sortableクラスを使ってsortablesテーブルに対して全件検索の指示を出しています。
検索結果は「$sortable」変数に多次元配列として格納されます。

return view( 'sortable', ['sortables' => $sortable] );
ここで、前回ルーティングファイルのweb.phpで登場したview()メソッドが出てきますが、今回は少し記述内容が違います。
第一引数の「sortable」はweb.phpで使ったときと同様「sortable.blade.php」を呼び出している事に代わりはありませんが、 今回は第二引数で「'sortables' => $sortable」と指定しています。
これはデータベースから取得したデータを「sortables」という変数に詰め直して渡す」という様に読んでください。

まとめると、この「index()」メソッドでは
①sortablesテーブルから全件検索を実行し、結果を$sortableに格納
②sortable.blade.phpを呼び出す
③sortable.blade.phpに、①の検索結果を渡す

という3つの処理が行われています。

⑤ルーティングのweb.phpを修正する

最後に、web.phpを修正します。

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', 'SortableController@index');
上記の様に修正してください。
以前まではルートURLが呼ばれた際にsortable.blade.phpを呼ぶ様な仕組みになっていましたが、 それを「ルートURLが呼ばれたら、Controllerのindexメソッドの処理を実行する」という仕組みに変更しています。

こうする事によって、先程Controllerに記述したindexメソッドが実行され、データを取得し、sortable.blade.phpでデータが処理され、画面に表示される事になります。 では、ブラウザから画面を表示してみましょう。下図の様になっていれば初期表示処理成功です。

jsを読み込んでいるので要素を動かすことは可能ですが、まだ座標をDBに登録はできません。
初期表示処理の仕組みを、流れに沿ってまとめます。
①ブラウザからURLhttp://localhost:8026が呼び出される。
ルーティングファイルweb.phpがURLを検知し、コントローラーのindex()メソッドを呼び出す。
コントローラーindex()メソッドから、モデルに対しDBデータを取得するよう指示
モデルからデータベースのsortablesテーブルのデータ全件取得を依頼。
データベースから受けたデータをモデルが取得
コントローラーのindex()メソッドよりビューの呼び出し。その際に⑤で取得したデータも一緒に受け渡す。
ビュー内のsortable.blade.phpでincludeしているdrags.blade.phpを取り込む。
drags.blade.php内に記述されているループ処理を実施。受け渡されたsortablesテーブルのデータを全件ループし、HTMLタグを生成する。
⑨実行結果を取り込んだビューファイルsortable.blade.phpがコンパイルされ、ブラウザに表示される。