Laravel で wordpress を読み込む(自前MVC)

ひとまず、Laravel に慣れるために MVC パターンを直接扱ってみる。先に InfyOm を使って自動作成してみたのだが、エラーが頻発してよくわからん。ので、そういうときは手作業でやってみるに限る。

目的としては、

  • wordpress のような既存のデータベースを読み込む
  • マスター管理のような CRUD ベースのページを自動作成する
  • 場合によっては、CRUD な Web API も自動生成する。
  • 場合によっては、クライアントから呼び出すコード(C#, nodejsとか)も生成してしまう。

まずは、xampp で wordpress をインストールして、mysql 部分だけアクセス可能にしておく。

composer でインストール&動作確認

適当なフォルダーを作成して、Laravel をインストール


composer create-project --prefer-dist laravel/laravel blog

データベースの設定

/.env を修正。wordpress のデータベースを読み込ませる。


DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=wordpress DB_USERNAME=wordpress DB_PASSWORD=wordpress

リスト表示を作成

いわゆるトップにアクセスして、一覧を表示させる。http://localhost:8000/WpPost/ にアクセスする。wordpress の記事は wp_posts にあるのだが、これを Model クラスでは WpPost として使う。

Model の作成

Model クラスを作る。対象のテーブル名を記述していないが、この手の MVC パターンの命名規約に

  • テーブル名は複数形、モデルクラスは単数形
  • モデルクラスは、キャメルパターンが多い
  • テーブル名はスネークパターンが多い
  • 「_」が単語の区切りになる。

ということで、自動的に WpPost から wp_posts を推測させている。wordpress の場合プレフィックスは「wp_」とは限らないので、このあたりは明示的にテーブル名を指定したほうがよいかも。


php artisan make:model Models/WpPost

/app/Models/wp_posts.php が生成される


<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class WpPost extends Model { // }

Model クラスの中身が空っぽで不安になるが、これで ORM されている。ただし、条件があって、

  • プライマリーキーは「id」の int 型である。
  • 作成日時に「create_on」を使う。
  • 更新日時に「update_on」を使う。

が必要になる。これを満たすテーブルの場合はそのまま使えるし、新規にテーブルを作るときはこの規約に合わせるほうが便利(テーブルの複数形もあわせて)。

ただ、今回は既存の wordpress のテーブルを使うので、この条件が少し違っている。これは後で修正することになる。

Controller の作成

コントローラーは、モデル名 + 「Controller」となる。


php artisan make:controller WpPostController

/app/Http/Controllers/WpPostController.php が生成される


<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class WpPostController extends Controller { // }

これも中身が空っぽで不安になるのだが、ここは手作業で作ることになる。別途、自動生成することもできるのだけど、今回は手動で作ってみる。

リスト表示する index アクションだけ追加する。


<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\WpPost; class WpPostController extends Controller { public function index() { $items = WpPost::all(); return view('WpPost.index', ['items' => $items]); } }

データベースから全件拾ってくる all() を使うのと、ビューに渡すために items で参照できるようにしておく。

  • ASP.NET の EF のように、ent.WpPost.ToList() な感じで取得
  • ViewBag( “items” ) = items のようなもの

View を作成する

/resources/views/layouts/app.blade.php を作成する。いわゆる
全ページから参照するテンプレートで、@extends(‘layouts.app’) で参照できるようにする。


<!DOCTYPE html> <html> <head> <title> @yield('title') </title> </head> <body> <h1>@yield('title')</h1> <div class="content-wrapper"> @yield('content') </div> </body> </html>

各ページから入れ込む部分は「@yield()」で書いておく。各ページからは「@section()」で参照する。本来は CSS とか JS とかの読み込みが書いてるのだが、今回はシンプルに書いておく。

一覧表を表示するページはこっち。/resources/views/WpPost/index.blade.php を新規作成する。


@extends('layouts.app') @section('title','WpPost.index') @section('content') <table> <thead> <td>ID</td> <td>post_title</td> <td>post_date</td> </thead> <tbody> @foreach( $items as $item ) <tr> <td>{{ $item->ID }}</td> <td>{{ $item->post_title }}</td> <td>{{ $item->post_date }}</td> </tr> @endforeach </tbody> </table> @endsection

レイアウトのファイルを「@extends(‘layouts.app’)」で参照している。あと、コントローラーから渡された、$items を使ってリスト表示する。

ルート情報を追加

/routes/web.php に追加する


Route::get('WpPost', 'WpPostController@index');

ブラウザから呼び出すと、どこが呼び出されるかを記述する。「http://localhost:8000/WpPost」とすると、WpPostController クラスの index メソッドが呼び出される。

ブラウザで表示する.

簡易 HTTP サーバーを動かして、呼び出してみる。


php artisan serve

作成順序

MVC パターンを使うと、書き込むコードや設定があちこち散るのが大変なのだけど、手順を作っておくと便利だったりする。

  1. モデルクラスを作る /app/Models/wp_posts.php
  2. コントローラーを作る /app/Http/Controllers/WpPostController.php
  3. アクションを作る WpPostController::index
  4. ビューを作る /resources/views/WpPost/index.blade.php
  5. ルート情報を作る /routes/web.php

Laravel の場合は、Model -> Controller -> View -> ルート情報(web.php) の順で作っていくとわかりやすい。

詳細表示を作成

id を指定して詳細表示をするページを作る。http://localhost:8000/WpPost/1 のように ID を指定してページを開く。

Controller の作成

/app/Http/Controllers/WpPostController.php を編集


<?php class WpPostController extends Controller { ... public function show($id) { $item = WpPost::find($id); return view('WpPost.show', ['item' => $item]); } }

プライマリ―キーの id での検索は find() を使う。

View を作成する

/resources/views/WpPost/show.blade.php を新規作成する。


@extends('layouts.app') @section('title','WpPost.show') @section('content') <table> <tr> <td>ID</td> <td> {{ $item->ID }}</td> </tr> <tr> <td>post_title</td> <td> {{ $item->post_title }}</td> </tr> <tr> <td>post_date</td> <td> {{ $item->post_date }}</td> </tr> </table> @endsection

ルート情報を追加

/routes/web.php に追加する


Route::get('WpPost/{id}', 'WpPostController@show');

ブラウザで表示する.

http://localhost:8000/WpPost/1

MVC パターンの関係はこうなっている。

Create ページを追加

新規作成のページを作る。

  • 新規入力をする create
  • データを登録する store

に分かれる

Model を修正

/app/Models/wp_posts.php を修正

  • ID が自動インクリメントなので除外する
  • create_at, update_at を除外する
  • デフォルト値を補う

class WpPost extends Model { // IDは自動インクリメント protected $guarded = array('ID'); // 作成日、更新日はなし const CREATED_AT = null; const UPDATED_AT = null; public function __construct() { // insert 時にデフォルト値を補っておく $this->post_excerpt = ''; $this->to_ping = ''; $this->pinged = ''; $this->post_content_filtered = ''; } }

Controller を追加

/app/Http/Controllers/WpPostController.php を編集


class WpPostController extends Controller { ... /// 新規作成(入力) public function create() { $item = new WpPost(); return view('WpPost.create', ['item' => $item]); } /// 新規入力(登録) public function store( Request $request ) { $item = new WpPost(); $form = $request->all(); unset($form['_token']); $item->fill($form); // 現在時刻を入れておく $item->post_date = date('Y-m-d H:i:s'); $item->save(); return redirect('/WpPost'); } }

View を作成する

/resources/views/WpPost/create.blade.php を新規作成する。


@extends('layouts.app') @section('title','WpPost.create') @section('content') <form action="/WpPost/create" method="post" > {{ csrf_field() }} <table> <tr> <td>post_title</td> <td><input type="text" name="post_title" value="{{ $item->post_title }}" /></td> </tr> <tr> <td>post_content</td> <td><input type="text" name="post_content" value="{{ $item->post_content }}" /></td> </tr> </table> <input type="submit" /> </form> @endsection

ルート情報を追加

/routes/web.php に追加する

  • create と store は、show の前に入れる

Route::get('WpPost', 'WpPostController@index'); Route::get('WpPost/create', 'WpPostController@create'); Route::post('WpPost/create', 'WpPostController@store'); Route::get('WpPost/{id}', 'WpPostController@show');

ブラウザで表示する.

http://localhost:8000/WpPost/create

エラーがなければ、一覧へ戻る

編集画面を作る

  • 更新情報を入力する画面
  • 更新処理をする

の2つのアクションの分かれる

Model の修正

/app/Models/wp_posts.php を修正

  • プライマリ―キーが 「id」以外の時は $primaryKey で設定

class WpPost extends Model { // IDは自動インクリメントなので除外 public $incrementing = true ; protected $guarded = array('ID'); // プライマリーキー名を変更 protected $primaryKey = 'ID'; // 作成日、更新日はなし const CREATED_AT = null; const UPDATED_AT = null; public function __construct() { // insert 時にデフォルト値を補っておく $this->post_excerpt = ''; $this->to_ping = ''; $this->pinged = ''; $this->post_content_filtered = ''; } }

Controller を作る

/app/Http/Controllers/WpPostController.php を編集


class WpPostController extends Controller { ... /// 更新(入力) public function edit($id) { $item = WpPost::find($id); return view('WpPost.edit', ['item' => $item]); } /// 更新(コミット) public function update(Request $request) { $item = new WpPost(); $form = $request->all(); $id = $form['ID']; unset($form['_token']); $item = WpPost::find($id); $item->fill($form); // 更新日時を入れておく $item->post_modified = date('Y-m-d H:i:s'); $item->save(); // 一覧へ戻る return redirect('/WpPost'); } }

View を作成する

/resources/views/WpPost/edit.blade.php を新規作成する。


@extends('layouts.app') @section('title','WpPost.edit') @section('content') <form action="/WpPost/edit" method="post" > {{ csrf_field() }} <input type="hidden" name="ID" value="{{ $item->ID }}" /> <table> <tr> <td>post_title</td> <td><input type="text" name="post_title" value="{{ $item->post_title }}" /></td> </tr> <tr> <td>post_content</td> <td><input type="text" name="post_content" value="{{ $item->post_content }}" /></td> </tr> </table> <input type="submit" /> </form> @endsection

ルート情報を追加

/routes/web.php に追加する

  • create と update は、show の前に入れる
  • update のほうに、id が含められないので、form から取得する

Route::get('WpPost/edit/{id}', 'WpPostController@edit'); Route::post('WpPost/edit', 'WpPostController@update'); Route::get('WpPost/{id}', 'WpPostController@show');

ブラウザで表示する.

http://localhost:8000/WpPost/create

エラーがなければ、一覧へ戻る

アイテムを削除する

  • 更新画面に「削除」ボタンを追加する
  • 削除処理をする

の2つのアクションの分かれる

Controller を作る

/app/Http/Controllers/WpPostController.php を編集


class WpPostController extends Controller { ... /// 削除 public function destroy( Request $request ) { $form = $request->all(); $id = $form['ID']; WpPost::find($id)->delete(); // 一覧へ戻る return redirect('/WpPost'); } }

View を編集する

/resources/views/WpPost/edit.blade.php に追記する

下のほうに「削除」ボタンを付ける。


@extends('layouts.app') @section('title','WpPost.edit') @section('content') <form action="/WpPost/edit" method="post" > {{ csrf_field() }} <input type="hidden" name="ID" value="{{ $item->ID }}" /> <table> <tr> <td>post_title</td> <td><input type="text" name="post_title" value="{{ $item->post_title }}" /></td> </tr> <tr> <td>post_content</td> <td><input type="text" name="post_content" value="{{ $item->post_content }}" /></td> </tr> </table> <input type="submit" /> </form> <script> function check(){ return window.confirm('削除してよろしいですか?'); } </script> <form action="/WpPost/delete" method="post" onSubmit="return check()" > {{ csrf_field() }} <input type="hidden" name="ID" value="{{ $item->ID }}" /> <input type="submit" value="削除" /> </form> @endsection

ルート情報を追加

/routes/web.php に追加する

  • destroy は、show の前に入れる
  • destroy に、id が含められないので、form から取得する

Route::post('WpPost/delete', 'WpPostController@destroy'); Route::get('WpPost/{id}', 'WpPostController@show');

ブラウザで表示する.

http://localhost:8000/WpPost/edit/10

「削除」ボタンを押したときに問い合わせのダイアログが出る。

カテゴリー: 開発, PHP パーマリンク