Laravelのhelloworldを作った話

さて、前回にlaravelのCDを作ったので、今回は超シンプルなlaravelのページを作ってみましょう。

今回作るのは以下の2つ

  • ハローを表示する
  • 言ったこと(引数)を表示する

ま、想像しただけのシンプル系です

第一章 ハローを表示する

/hello へとアクセスするとHelloと文字列を出すだけです。

うん!ただの

echo hello > index.html

です… と、これをlaravel風に書くだけです。超シンプルー

でも、もうちょっとだけ複雑にして、アクセスすると以下の手順かな?

  1. アクセスのパスからルートを決めて
  2. コントローラで処理して
  3. ページを表示する

ま、こんな3ステップですが、laravelの基本です。

  1. routeを決めて
  2. controllerで処理して
  3. bladeページを表示する

こんな3ステップです。

  1. Controllerを決める

ここで、はじめに決めるのはControllerの名前を考えます…
秒で、HelloControllerです!

Controllerというのは前にもありましたが、ページの処理そのものです。
MVCで言うと… C…ですね。laravelでは Mってのもある意味で正しいが…

んで、作成は普通なら、artsanで… って解説が多いですが、私は直書きします
正直プロジェクトで作業していたらコマンド… めんどくさいですw

app/Http/Controllers/ にコントローラを作ります。これ重要!

HelloController.phpです。
同居人のControllerを継承?承継?extendsします…

class HelloController extends Controller{

}

激烈シンプル系ですw

次に考えるのは… メソッド名です。helloって返すだけです。

class HelloController extends Controller
{
    public function hello(){
        $word = 'hello';
    }
}

はい、これではNGですが、今はOKにしましょう!

2.ルートを決める

次に、ルートを決めます。

/hello にアクセスしたら、HelloControllerのhelloに行けば良いわけですね

ルートの処理は routesに記述します。
ファイルで言うとroutes/web.phpです。
web.phpはページ、api.phpはインタフェイスとして私は使い分けています

サンプルとして、サンプルページの処理が書いています

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

各部の解説は…
 Routeですよ!
 getでのリクエスト!
 ’/’に来たのは!…
 処理を無視して、view(‘welcome’)を使いますよ!
 ちょっと先の説明になりますが、welcome.blade.phpを使います!

その程度の理解でOKです。
正直、サンプルでfunctionってのはややこしいですねw

今回は、HelloControllerのhelloに渡すわけです。
記述内容は以下です

Route::get('/hello','HelloController@hello');

はい?激烈シンプル系ですw

/hello → HelloController@hello
これだけのこと…
↓注意 : 8以降はコチラ…

Route::get('hello', [HelloController::class, 'hello']);

仕込みはこれで終わり… アクセスしてもNGなんで…

2.結果ページを作る

今回もbladeで書きます…

viewの名前は、helloにしましょう
helloのviewの場合はhello.balde.phpです。
view入ればresources/views/に入れます

resources/views/hello.blade.php これが、結果ページのファイルだ!

内容は… どうしよう? helloだけを書けばOKだけれども、先のHelloControllerで、helloをword変数に入れていたので、wordの引数を使いましょう。

<html>
    <head>
        <title>sample return hello</title>
    </head>
    <body>
        <h1>sample return {{$word}}</h1>
    </body>
</html>

$wordの文字列を表示します…

うん、それだけです。

これで結果ページは出来ました

3.Controllerから結果ページへと結合する

はい、次にするのは先にページNGと言ったControllerとviewと結合させます

class HelloController extends Controller
{
    public function hello(){
        $word = 'hello';
        $data  = ['word' => $word];
        return view('hello',$data);
    }
}

追加したのはreturnの行

  • viewを返しますhelloって名前のやつ
  • 使う変数はword = $wordって変数

2つめがちょっぴりややこしいですが、blade内で{{ $word }}ってwordの連想配列が使えます。
Classも可能、Classも可能、大切なので2回言います

… ルートをチェックすると…

Illuminate\Contracts\Container\BindingResolutionException
Target class [HelloController] does not exist.

Routeの書き方が8から変わったようです;; ※ 上に注意を追記しました
https://teratail.com/questions/291286

Route::get('hello', [HelloController::class, 'hello']);

artisanを実行すると、ルートは正しいです

$ php artisan route:list
+--------+----------+----------+------+--------------------------------------------+------------+
| Domain | Method   | URI      | Name | Action                                     | Middleware |
+--------+----------+----------+------+--------------------------------------------+------------+
|        | GET|HEAD | /        |      | Closure                                    | web        |
|        | GET|HEAD | api/user |      | Closure                                    | api        |
|        |          |          |      |                                            | auth:api   |
|        | GET|HEAD | hello    |      | App\Http\Controllers\HelloController@hello | web        |
+--------+----------+----------+------+--------------------------------------------+------------+

4.動作検証する

$ curl http://localhost:8080/hello
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>sample return hello</title>
    </head>
    <body>
        <h1>sample return hello</h1>
    </body>
</html>

はいぃ〜〜 h1にhelloが表示されていますねっ!

今回はこんな感じですね。

意外に時間がかかりましたが、laravelの若葉マークはこんな感じです。

*.番外編…

さて、番外編として困ったときのメモを残しておきます

番外編 1. Not foundで困った

/hello にアクセスすると

Not Found
The requested URL was not found on this server.

…ま、あるだろうなと思って、調査…
storage/logs/laravel.logにて、エラーチェック… 何も出ない…


apacheのaccess.logをチェックすると問題なくアクセス…

"GET /hello HTTP/1.1" 404 490 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36"

apacheのerror.log … 何も出ない…

困った系…

色々調べると、apacheのmod_reweiteがないらしい…

早速登録!

a2enmod rewrite
service apache2 restart

アクセスすると問題なくOKになりました!

https://qiita.com/u-akihiro/items/c7a5bb38c34858d00c2a

番外編 2.自動試験を書く系

かなり応用なので番外編としました、PHPUnitの試験を書きます。hello world程度ですが、この辺りからはじめると良いでしょう。

FeatureとUnitがありますが、機能テストと単体テストです…

最初にいつものUnitと思いましたが、私もお勉強と思いFeatureからはじめました。

番外編 2.1.自動試験を書く系 – Feature –

今回の試験は決められた結果を返すだけなので、簡単ですが…
ややこしくなりました。次の番外編へ

FeatureはExampleTest.phpを参考にアクセスすると200 OKが返ればOKってだけですね。

    public function testBasicTest(){
        $response = $this->get('/hello');
        $response->assertStatus(200);
    }

うん、OK …

次に固定のコンテンツが返ればOKなので、コンテンツをチェックしてやればOKです。簡単に書くと…

    public function testData(){
        $response = $this->get('/hello');
        $this->assertEquals(
            "<!DOCTYPE html>
<html lang=\"en\">
    <head>
        <meta charset=\"utf-8\">
        <title>sample return hello</title>
    </head>
    <body>
        <h1>sample return hello</h1>
    </body>
</html>
",$response->getContent());
    }

うむぅ〜OKですw

番外編 2.2.自動試験を書く系 – Unit –

Controllerの試験を書きましょう!
Unitテストなのでメソッドを考えます…

helloメソッドは引数無しで、結果を返しているので試験は単純ですね

… ん? Controllerを作ると…

Illuminate\Contracts\Container\BindingResolutionException : Target [Illuminate\Contracts\View\Factory] is not instantiable.

ぎゃぁ〜〜 作れない orzと言う事でControllerの試験は諦めましょう!

番外編 3.結局 試験結果をファイルに置いておく話

番外編 2.1でやりましたが… 結果を直接書くとちょっぴり変数の頭のシングルクォートがダサい…
ファイルに書き出し… ましょう!

ファイルを保存するときは、storageにしましょう!

storage/tests/Feature/hello/contents.txt

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>sample return hello</title>
    </head>
    <body>
        <h1>sample return hello</h1>
    </body>
</html>

うん、そのままw
テストメソッドはこんな感じに変更

    public function testContents(){
        $response = $this->get('/hello');
        $contents = \File::get(storage_path('tests/Feature/hello/contents.txt'));

        $this->assertEquals($contents,$response->getContent());
    }

ファイルの読み込みはコチラ!

        $contents = \File::get(storage_path('tests/Feature/hello/contents.txt'));