クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

Laravelの/publicをルートに変更しHello worldする

前回、MAMP環境でLaravelの白い画面を出しました。今回はLaravelのファイル構成を見ながら、URLパスの変更やHello worldなどを行いました。

【目次】

※参考:Laravel元年!インストールしてMAMP環境で白い画面出す!! - クモのようにコツコツと

やったこと

前回表示した「白い画面」はこちら

f:id:idr_zz:20190502233526j:plain

ここから手を加えていきます。 全体の流れとしてはこんなことを行いました。

  • Laravelのファイル構成確認
  • パスの/publicをなくす
  • 白い画面の場所を突き止める
  • 白い画面にHello world
  • 下層ページを作ってHello wold

それではいきまSHOW!

Laravelのファイル構成確認

第一階層はこちら f:id:idr_zz:20190506183048j:plain

前回インストールした「Funter」というソフトのおかげで隠しファイルも表示されています♪

パスの/publicをなくす

前回表示した白い画面のパスはURLのルート/ではなく/pablicでした。

そしてURLのルート/画面はディレクトリ一覧が表示されてしまいました。 f:id:idr_zz:20190502233513j:plain うーむ…ちょっとよろしくないですねこれは。。

できればルート/自体を「白い画面」にしたいです。調べたところ、いくつかの方法がありました。

  • Webサーバのhttpd.confファイルでURLを変更する
  • /publicの中身をルート直下に移動して、関連するパス設定を修正する
  • /public以外のディレクトリを別のディレクトリに移動し、/publicの中身をルート直下に移動し、関連するパス設定を修正する
  • ルート直下に.htaccessファイルを置く

httpd.confを修正する

一応、この方法はMAMP環境では成功したのですが、Laravelファイルの外側(Webサーバ)での設定のため、今後オンライン上にアップするときなど、環境ごとに都度設定をしなければならない。Laravelの中で設定が完結できた方がといいなーと感じました。

Apache LaravelでHelloWorldを出そうと思ったらつまづいた - ドドスコblog

/publicの中身をルート直下する

こちらは割とシンプルそうな方法ですが、まだ/publicとそれ以外のファイルの位置関係をそこまで理解しきれていないため、少し不安を感じる。

※参考:Laravelのドキュメントルートを変更する - Laravel学習帳

/publicとそれ以外を分離する

こちらはシステムとデザインを分離する方法でシステム的には綺麗になるようです。が、より大掛かりな作業でハードルが高いかも。。

※参考:Laravelで、public(公開)フォルダの位置を変更する際の設定 - Qiita

.htaccessを置く

Laravelのコアなファイル構成の変更はあまりしたくないため、.htaccessをいじる程度の方法はないかなーと調べたところ…なんと、ありました!!

※参考:LaravelのURLからpublicを消す | gfonius.net

リンク先のGISTのコード

※参考:Php laravel 5.5 project .htaccess file · GitHub

IfModuleRewriteCond(条件)、RewriteRule(処理)などはリダイレクト系の記述。13行目に/publicのパスがあります。

※参考:.htaccess の書き方(リダイレクト編) - Qiita

この.htaccessファイルをルートディレクトリ/に置いたところ…

f:id:idr_zz:20190502233526j:plain

やった!!ルート/ページがファイル一覧ではなく「白い画面」になりました!

白い画面にHello world

/publicの中身

さて、/publicディレクトリは無傷のままURLのみを変更できました。次に「白い画面」を修正したい(Hello world的な)。

まずは/publicディレクトリの中身を見てみる。

f:id:idr_zz:20190506192501j:plain

このディレクトリにはCSSやJSなど表示される画面についてのファイルが入っているようです。fabiconもありますね。

index.phpを開く

index.phpを開いてみる(コメントは省略)

<?php
define('LARAVEL_START', microtime(true));

require __DIR__.'/../vendor/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);

ふむふむ……一つだけわかったこと。この中には「白い画面」に表示されている要素は何一つない!…と、いうこと。。

/publicindex.phpがどのような処理を行っているか解説されている記事がありました。

※参考:PHPフレームワーク「Laravel」における処理の流れと、ルーティングを理解しよう (1/3):CodeZine(コードジン)

  1. オートロードファイルの読み込み(vendor/autoload.php
  2. アプリケーションインスタンスの生成(bootstrap/app.php
  3. HTTPカーネルによる処理
  4. リクエストのディスパッチ(移管)

このうちの3番目「HTTPカーネルによる処理」で読み込まれるapp/Providers/RouteServiceProvider.phpというファイルの中に、4番目の「リクエストのディスパッチ(移管)」先であるroutes/web.phpを読み込む処理が書かれていると。ふむ、見てみましょう。

RouteServiceProvider.phpを開く

app/Providers/ディレクトリの中を見てみる。

f:id:idr_zz:20190506200224j:plain

あった!RouteServiceProvider.php。これを開く(コメントは省略)

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
    protected $namespace = 'App\Http\Controllers';
    public function boot()
    {
        parent::boot();
    }

    public function map()
    {
        $this->mapApiRoutes();

        $this->mapWebRoutes();
    }

    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }

    protected function mapApiRoutes()
    {
        Route::prefix('api')
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }
}

みっけた!!確かにあった!mapWebRoutesメソッドのところ。

<?php
//(省略)
    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }
  • protectedはアクセス制御(そのクラスとサブクラスのみアクセスできる)
  • mapWebRoutesメソッドを定義
  • Routeクラスのmiddleware()メソッドの設定(引数はweb
  • namespace()の引数を$this->namespace
  • group()base_path()の引数をroutes/web.php

この最後のところがroutes/web.phpを読み込む設定!

routes/web.phpを開く

routes/ディレクトリの中を見てみる。ファイルが4つある。

f:id:idr_zz:20190506200728j:plain

その中のweb.phpを開いてみる(コメントは省略)。

<?php
Route::get('/', function () {
    return view('welcome');
});
  • Routeクラスのget()メソッドの設定
  • 第一引数:/(ルート)の場合
  • 第二引数:無名関数を実行
    view()メソッドでwelcomeを返す

ルート/にアクセスがあった場合にwelcomeを表示する、という処理が書かれている。

このwelcomeresources/viewsディレクトリの中のwelcome.blade.phpを指しています。

※参考:Laravelルーティングの基本とよく使われるルーティングパターン

/resources/views/welcome.blade.php`を開く

/resources/views/の中身を見てみる

f:id:idr_zz:20190506202107j:plain

あった、welcome.blade.phpだけが入ってます。開いてみる

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Laravel</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
        <!-- Styles -->
        <style>
            /*(省略)*/
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            @if (Route::has('login'))
                <div class="top-right links">
                    @auth
                        <a href="{{ url('/home') }}">Home</a>
                    @else
                        <a href="{{ route('login') }}">Login</a>
                        @if (Route::has('register'))
                            <a href="{{ route('register') }}">Register</a>
                        @endif
                    @endauth
                </div>
            @endif
            <div class="content">
                <div class="title m-b-md">
                    Laravel
                </div>
                <div class="links">
                    <a href="https://laravel.com/docs">Docs</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://blog.laravel.com">Blog</a>
                    <a href="https://nova.laravel.com">Nova</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
</html>

ふい〜。ようやく「白い画面」の中身に相当するファイルにたどり着いた!省略したけどheadタグの中にCSSのスタイルも直で書かれていた。

ファイル名にあるbladeはLaravel専用のテンプレートエンジン。このファイルの中では二重波括弧{{ }}で囲われた部分や、@が頭についたif文などがその書式にあたります。

※参考:Bladeテンプレート 5.5 Laravel

白い画面にHello worldする

さて、果たしてホントにこのファイルが「白い画面」にあたるのか確かめたく、「Hello world」的な修正を加えてみます。

    <body>
        <div class="flex-center position-ref full-height">
            <!--(省略)-->
            <div class="content">
                <div class="title m-b-md">
                    Laravelテストですー
                </div>
                <p>こんにちは、ららべる♪</p>  
                <div class="links">
                    <a href="hoge/subpage">Sub Page</a>
                    <a href="https://laravel.com/docs">Docs</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://blog.laravel.com">Blog</a>
                    <a href="https://nova.laravel.com">Nova</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
  • . title部分のテキストをうち変え(テストですー)を追加
  • その下にpタグ追加(こんにちは、ららべる♪)
  • .linksの中のaタグの頭にSub Pageを追加(hogeはアプリ名)。

さあ、どうだ?

f:id:idr_zz:20190506203909j:plain

きた!変わったー。間違いなくこのファイルが「白い画面」ですな、はい。

下層ページを作ってHello woldする

/subpageを表示(Not found)

さて、.linksの中のメニューは基本的にlaravelオフィシャルの外部ページです。

一つ目に下層ページ/subpageを設定してみました。開いてみると…

f:id:idr_zz:20190506210355j:plain

そんなページはありません(Not found)と…。さてどうするか。

routes/web.phpに下層ページの設定を追記

先ほどのroutes/web.phpを再度開き、/subpageの設定を追記します。

<?php
Route::get('/', function () {
    return view('welcome');
});

//下層ページ設定
Route::get('/subpage', function () {
    return view('subpage');
});

この時点ではまだ404のままです。(画面は少し変わりますが)

f:id:idr_zz:20190506210149j:plain

/resources/views/subpage.blade.php`を作る

/resources/views/の中にsubpage.blade.phpを作成します。(welcome.blade.phpをベースにしている)

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Sub Page | Laravel</title>
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
        <!-- Styles -->
        <style>
          /*(省略)*/
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            <!--(省略)-->
            <div class="content">
                <div class="title m-b-md">
                    Laravelサブページですー
                </div>
                <p>こんにちは、ゲストさん</p>
                <div class="links">
                    <a href="hoge/subpage">Sub Page</a>
                    <a href="https://laravel.com/docs">Docs</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://blog.laravel.com">Blog</a>
                    <a href="https://nova.laravel.com">Nova</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
</html>
  • metaタグのtitleを変更(Sub Page | Laravel)
  • .titleを変更(Laravelサブページですー)
  • pタグを変更(こんにちは、ゲストさん)

さあどうだ…

f:id:idr_zz:20190506211100j:plain

やた!下層ページが表示された! (何度か、変更が反映されないことがありましたが、MAMPのサーバを停止、起動すると最新版になりました)

最後に

まだPHPフレームワークらしいテンプレートやデータベースみたいなコンテンツにはなっていないですが、ひとまずLaravelのファイル一式の中でどこが画面に表示されているファイルになっているかまでは理解できました。

この先に進むにはMVC(モデル・ビュー・コントローラー)アーキテクチャの理解が必要とのことで、次回以降に取り組みたく思います。その先には懸案になっているオンライン上(Heroku)へのアップも控えています。それではまた!