一言まとめ
WordPressのフレームワークはいろいろあるけど、MVCを取り入れたものがほとんどない。あってもフレームワーク自体がしょぼい。
それならフルスタックフレームワークのLaravelをWordPressで使いましょう!
仕事でよく企業様のコーポレートサイト制作にWordPressを利用しています。当然ですが、企業のHPですから、デザインは独自のものになります。なので、スクラッチから作成するのが常です。
スクラッチとは言っても、ゼロからではさすがにナンセンスですので、何かしらのフレームワークは使いたいものです。選択肢は実にたくさんあります。
ページビルダー機能を提供しているフレームワークもありますが、常にごりごりにカスタマイズする必要があるので、まだ仕事で使ったことがありません。個人的には機能がシンプルなものが一番合います。
ただ、最大の問題はそこではなく… ページビルダー機能がいいとか、シンプルがいいとか以前に、WordPressのテーマの作り方自体にあまり好感が持てません。そう、オーソドックスなMVC方式で作りたいのです!
そこで1つアイディアが浮かびました。「Laravel (PHP界隈で最も人気なフルスタックフレームワーク)をWordPressテーマの中でも使えるようにできないのか?」と。
そして作ったのが表題の「Laraish」です。
WordPressテーマの中で動くLaravel
Laravel はPHP用のWebアピリケーションフレームワークです。「美しいコード、洗練された文法、そして表現力の高さ」として知られています。一度使ってみれば確実に恋に落ちるやつですw
Laraish は そんな Laravel を WordPress でも使えるようにするテーマです。目的は、もっと楽に、もっと楽しく WordPress テーマを開発することです。
必要知識
Laravel をベースにしているので、当然 Laravel についての最小限の知識は必要です。初耳の方ならまずは公式サイトを覗いてみて、ちょっと触ってから戻ってきて下さい。
すでに Laravel をご存知である程度知識を持っているのであれば、すごく簡単に始められます。
オリジナルの Laravel とどこが違うの?
ほとんど差はないと言っても過言ではないです。WordPressでも動くよう、軽く調整したところはありますが、違いが気になる方はdiffしてみることをお勧めします。なので、基本的に Laravel でできることはすべてできると思って下さい。
インストール
Composer を使ってインストールします。composer create-project --prefer-dist laraish/laraish テーマ名
注意:実行前に、MySQL と Webサーバーが起動中であることを確認して下さい。なぜなら、composer create-project
コマンドでインストールが終わったあと、artisan コマンドが実行されます。artisan コマンドを実行するためには、実行時にWordPressが使っている MySQL と Webサーバーが動いている必要があります。
また、Mac でMAMPなどを使って環境構築しているのなら、ターミナルで参照しているPHPバイナリーがOSのPHPバイナリーではなく、MAMPなどのアプリが提供しているものにするために、$PATH
環境変数を変えてあげる必要があります。
ルーティング
WordPress用のルートが指定できるように、オリジナルの UriValidator(Illuminate\Routing\Matching\UriValidator)
を独自のものにすり替えています。
以下、使い方の例です
// "about" ページ Route::any('page.about', Controller@method); // "about" ページの子ページ "works" Route::any('page.about.works', Controller@method); // "about" ページの任意な子ページ Route::any('page.about.*', Controller@method); // "about" ページの任意な子孫ページ Route::any('page.about.**', Controller@method); // 共通の`prefix`のルートをまとめて指定 Route::group(['prefix' => 'page'], function () { Route::any('about.contact', function () { return 'Foo'; // <page.about.contact> と等価 }); Route::any('service.*.price', function () { return 'Bar'; // <page.service.*.price> と等価 }); }); // 注意 ! // // 詳細度が高いルートは詳細度が低いルートの上(前)に置かなければならない。 // なぜなら、詳細度が低いルートが前に来ると、後の詳細度が高いルートが無視されるからです。 // // 以下のルートは上のルートより詳細度が低いので、ここに置きましょう。 // すべてのページ Route::any('page', Controller@method); // フロントページ Route::any('front_page', Controller@method); // アーカイブページ Route::any('archive', Controller@method);
以下のことを覚えておきましょう。
- ページとタクソノミーの階層は「ドット記法」で指定できます。
- ウィルドカード(
*
)である 親/祖先 ページの 任意な 子/子孫ページを指定できます。 - ルートが置かれる位置に気をつけて下さい。詳細度が高いルートは低いルートより上に置かなければならないです。
さらに、URIで独自のルートを追加することもできます。
// この場合、Laravel のオリジナルな UriValidator を使用する. Route::get('/my/endpoint', function () { return 'Magic!'; });
モデル
Laraish では、Post
や Term
のような、WordPress用のモデルが使えます。ただ、これは Laravel の Eloquent モデルのような ORM ではなく、あくまでもWordPressのAPIのラッパーで、よくありがちなロジックをカプセル化して、ビジネスロジックを簡略化するために存在しています。
Laraish\WpSupport\Model
にすべてのモデルが入っています。中では一番よく使われるモデルはPost
ですから、Laraish\WpSupport\Model\Post
を継承したクラスをapp/Models/Post.php
に配置してあります。
サンプルを見てみましょう。
以下のルートがあるとします
Route::any('archive', 'Generic\Archive@index');
そして、以下はそのコントローラー app\Http\Controllers\Generic\Archive
です。
<?php namespace App\Http\Controllers\Generic; use App\Http\Controllers\Controller; use App\Models\Post; class Archive extends Controller { public function index() { $data = [ 'posts' => Post::queriedPosts() // 現在ページのすべての投稿を取得する ]; return $this->view('generic.archive', $data); } }
以下はビュー generic.archive
です。
<main class="posts"> @foreach($posts as $post) <section class="post"> <a class="post" href="{{ $post->permalink }}"> <img class="post__thumbnail" src="{{ $post->thumbnail->url }}" alt="{{ $post->title }}"> </a> <time class="post__time" datetime="{{ $post->dateTime }}">{{ $post->date }}</time> <a class="post__category" href="{{ $post->category->url }}">{{ $post->category->name }}</a> <h1 class="post__title">{{ $post->title }}</h1> </section> @endforeach {{ $posts->getPagination() }} </main>
上記サンプルコードにある通り、Post オブジェクトから記事にまつわる一般的なプロパティを取得することができます。
例えば、$post->permalink
や $post->title
。一見して Post オブジェクトのプロパティにアクセスしているように見えますが、実際は「プロパティにアクセス」ではなく、「メソッドを実行する」か「キャッシュから値を返す」の処理になっています。
例えば、初回の $post->permalink
は $post->permalink()
を実行して、結果を保存し、次回からその保存した値(キャッシュ)を使うようにしています。もしキャッシュを使いたくない場合、$post->permalink()
のように、明示的にメソッドをコールして下さい。
このように、初回の(存在しない)プロパティへのアクセスは、実質的には同名のメソッドを呼んで戻り値を返すようになっています。つまり、モデルに public なメソッドを追加することで、新しい「プロパティ」を作ることができます。
どういった「プロパティ」があるのかについては、Laraish\WpSupport\Model を覗いてみて下さい。
@loop
blade ディレクティブ
WordPressの The Loop を簡略するために、@loop
ディレクティブを追加しました。
例:
@loop($posts as $post) {{ get_the_title() }} @endloop
上記は以下にコンパイルされる
wpPost ); ?>
ここでは、$post
は Post
オブジェクトでなければならないです。
通常、@foreach
の代わりに、@loop
を使うべきではありません。なぜなら不必要な処理が走って効率が悪いからです。content
や excerpt
といった「The Loop」の中でしか取得できない値を取得したい時に使って下さい、それ以外の時はなるべく使わないように。
テーマのオプション
カスタム投稿タイプを登録したり、ナビゲーションメニューを設定したり… テーマのビジネスロジックを作り始めるまでの前準備って結構煩雑だったりします。しかもどれもこれも似たようなタスクばかりでつまらないです。Laraishでは、そういった単純作業は app/config/theme.php
で設定することになっています。
基本的なオプションは数多く用意されています。 どんなオプションがあるのかは config/theme.php をご参考下さい。
独自のオプションを追加したい場合、App\Providers\ThemeOptionsProvider
に public メソッドを追加します。追加されたメソッドの名前がそのままオプション名となります。
アクション と フィルター
Laravel の イベントと同じく、アクションとフィルターもApp\Providers\EventServiceProvider
に記述することで登録することができます。
pre_get_posts
アクションを追加する例を以下に示します。アクション発生時に App\Listeners\MainQueryListener
のhandle
メソッドが呼び出されます。
namespace App\Providers; use Laraish\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider { /** * Register the WordPress actions * @var array */ protected $action = [ 'pre_get_posts' => 'App\Listeners\MainQueryListener' ]; /** * Register the WordPress filters * @var array */ protected $filter = []; }
ページネーション
ページネーションを生成する最も簡単な方法は Post
オブジェクトの getPagination
メソッドを使うことです。
use App\Models\Post; $post = Post::queriedPosts();
{{ $posts->getPagination() }}
WordPressもページネーションを生成する関数を提供していますが、マークアップのカスタマイズ性がほぼないのが問題です。
getPagination()
にオプションを渡すことで、viewファイルを指定するなど、幾つかの有用なオプションが用意されています。
例えば出力するページネーションをmenu式(select
要素にする)にしたければ、$posts->getPagination(['type'=>'menu'])
にします。
詳しくは laraish/pagination をご参照下さい。
オプション・ページ
WordPressのテーマを作る際に、最も泥臭い仕事の1つがオプション・ページを作ることでしょう…
WordPressのAPIを使って、実際にオプション・ページを作った人なら分かると思いますが、カオス以外の何物でもないのです…
Laraish はオプション・ページを作るためのクリンかつパワフルな API を提供します。
この機能を使うためには別途パッケージを追加する必要があります。
詳しくは laraish/options をご参照下さい。
View デバッガー
「このページってどのテンプレートファイルを使っているのか…?」と知りたくなる時がありますよね。そういったViewに関する基本的な情報は「View デバッガー」を使えばブラウザのコンソールから取得することができます。
App\Http\Controllers
に ViewDebbuger
trait を追加することで利用できます(デフォルトでは追加されています)。
ブラウザのコンソールを開けば以下のような情報が出力されます。
{ "view_path": "/var/www/example/wp-content/themes/example/resources/views/singular/news.blade.php", "compiled_path": "/var/www/example/wp-content/themes/example/storage/framework/views/befa3e2a2cb93be21c6ebf30a60824a5d2a2ed11.php", "data": { "post": {} }, "controller": "App\\Http\\Controllers\\Singular\\News" }
また、.env
ファイルの中で、APP_ENV=production
が設定されている時、デバッグ情報は出力されないようになっています。
artisan の実行
インストールのほうでもちょっと触れましたが、artisan コマンドを実行するためには以下を注意して下さい。
- MySQL サーバーと web サーバーが動いていること。
- MacでMAMP或いは類似のアプリを使って環境構築をしているのなら、環境変数の
$PATH
を変える必要があるのかもしれません。例えば、php artisan key:generate
を実行するとき、$PATH
を変えなければphp
はOSの内蔵版のPHPになるので、それをMAMP(或いは類似のアプリ)のPHPバイナリーにする必要があります。
まとめ
WordPressのテーマフレームワークっていろいろありますよね。
一般ユーザ向けのものだと、ページビルダー機能を提供しているフレームワークもありますが、「やはりMVCで作りたい」なら、Laraishを使いつつ、Visual Composer やUnysonのようなページビルダープラグインを上手く利用するといいでしょう。
それと、Laravelをベースにしているので、パフォーマンスが心配な方もいるかもしれませんよね。結論から言いますと、環境にもよりますが、デフォルトのテーマより大体100ミリ秒前後の差が出ます。ただし、WordPressですから、結局キャッシュ系のプラグインか、サーバー側でページキャッシュを利用する場合が多いので、そんなに気にしなくても良いと思います!