コントローラの利用

Webページの具体的な処理は、コントローラを使って行うのが基本。

コントローラは、MVCアーキテクチャの基本となるもの。

 

MVCとコントローラ

ルーティングは、アクセスしたアドレスを元にして、処理を割り振るための機能。

Route::getを使って簡単なWebページを表示したが、ルーティング自体はWebページを作って表示させるためのものではない。

具体的に実行すべき処理は別に用意されていて、それを特定のアドレスに振って呼び出すためのものである。

 

呼び出される「具体的に実行すべき処理」というのは?

それを実装するために用意されているのが「コントローラ」

 

MVCアーキテクチャ

 コントローラを知るには、まず「MVC」と呼ばれるアーキテクチャを理解する必要である。

MVCは、「Model-View-Controller」の略。アプリケーションの処理を、MVCの3つの要素の組み合わせとして構築していく考え方である。

MVCは、以下の役割

モデル(Model) データ処理全般を担当。
具体的にデータベースアクセスに関する処理全般を扱う
ビュー(View) 画面表示を担当。表示に使うテンプレートなど
コントローラ(Controller) 全体の制御を担当。必要に応じてModelを使ってデータを取得したり、Viewを利用して画面表示を作成したりする

モデルやビューは、特定の機能に特化したもの。

コントローラは処理全体を担当である。モデルやビューは、不要であれば用意しないでおくことも可能だが、コントローラがないと処理そのものが実行できない。

Laravelの開発は、まずコントローラを作るところからといってもよい。

 

f:id:mkyosuke:20200107154656p:plain

 

コントローラの作成

 コントローラは、PHPスクリプトファイルとして作成。

ここでは、artidan(アーティザン)コマンドを使用。

 

php artisan make:controller HelloController

これで、「HelloController」という名前のコントローラが作成。

 

artisanのmake:controllerについて

 以下のような形で実行

php artisan コマンド

今回使ったのは、「make:controller」というコマンド。これを以下のように実行

php artisan make:controller コントローラ名

これで指定した名前でコントローラが作成。

コントローラは通常、「〇〇Controller」というように、名前の後に「Controller」を付けたものが使われる。

 

HelloContorller.phpをチェックする

 コントローラは、「app」フォルダの「Http」フォルダ内の「Controller」フォルダの中に作成される。

その中に、「HelloContorller.php」というファイルがある。

これが作成したスクリプトファイル。

f:id:mkyosuke:20200108111529p:plain

このファイルを開く。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    //
}

これ、コントローラの基本ソースコードとなる。

 

Controllers 名前空間

 コントローラは、クラスとして作成。

このクラスは、App/Http/Controllersという名前空間に配置。

名前空間というのは、クラスを階層的に整理するための仕組み。フォルダを使って階層的にファイルを整理するのと同じようなイメージ。

 

ここでは、App/Http/Controllersという名前空間を使っている。コントローラの置かれている場所は、「app」フォルダ内の「Http」フォルダの「Controllers」フォルダの中。

フォルダの構成に従って名前空間が指定されていることがわかる。

namespace App\Http\Controllers;

これが、コントローラクラスを作成する際の基本である。

 

名前空間は、フォルダを階層的に整理した状態に似ている。

f:id:mkyosuke:20200108113936p:plain

 

useによるクラスのインポート

 次に記述されるのがuse文。

use Illuminate\Http\Request;

 ここでは、Illuminate\Httpパッケージ内に用意されている「Request」を使える状態にしている。まだこの段階ではRequestは不要だが、これから多用することになるクラスなので、デフォルトでuse文が追加されている。

 

クラスの定義

 続いてクラスの定義がされている。ここでは、HelloContorllerクラスが以下のように定義されている。

class HelloController extends Controller
{
    //
}

コントローラクラスは、Controllerというクラスを継承して作成される。

名前は「〇〇Controller」というもので継承。これは必須でないが、クラスをわかりやすくする上での必要な命名ルール。

これで、コントローラクラスは用意ができた。あとは、具体的な処理をメソッドとして追加していく。

 

アクションを追加する

 コントローラに用意される処理は、「アクション」と呼ばれる。

これはメソッドの形で用意。

アクションは、コントローラに用意される処理を行うもので複数を用意できる。

 

HelloContorller.phpを以下のように書き換え

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function index(){

        return <<<EOF

<html>
<head>
<title>sample</title>
</head>
<body>
<h1>Sample</h1>
<p>HelloController</p>
</body>
</html>
EOF;

    }
}

ここでは、HelloContorllerクラスの中に「index」というメソッドを追加。

アクションメソッドは、このindexのように引数を持たないメソッドとして用意される(ただし、必要に応じて引数を用意する場合もあり)

アクションメソッドでは、returnでHTMLのソースコードを返している。

returnされた内容が、アクセスしたWebブラウザへ返され、表示される。

 

ルート情報の用意

 コントローラにアクションは用意はできたが、これだけではまだ表示はできない。

アクションを使うようにするためには、アクションにルートを割り当てる設定が必要。

「routes」フォルダのweb.phpを開き、編集。

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

Route::getを使って、ルート情報を設定。

第2引数には関数は使ってなく、'HelloController@index'というテキストが用意される。

 

コントローラを利用する際は、第2引数に「呼び出すコントローラとアクション」を指定。’コントローラ名@アクション名’というように、コントローラとアクションを@でつなげて記述。

 

ルート情報を記述後、Webブラウザで/helloにアクセス

Indexアクションによって作成されたWebページが表示。

f:id:mkyosuke:20200108133613p:plain

 

ルートパラメータの利用

 アクションメソッドを修正して使う。

HelloContorllerクラスを以下に修正

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function index($id='noname', $pass='unknown' ){

        return <<<EOF

<html>
<head>
<title>sample</title>
</head>
<body>
<h1>Sample</h1>
<p>HelloController</p>
<ul>
<li>ID:{$id}</li>
<li>pass:{$pass}</li>
</ul>
</body>
</html>
EOF;

    }
}

続いて、ルート情報の修正。

Web.phpの、HelloContorller@indexへのRoute::get文を以下のように修正。

Route::get('hello/{id?}/{pass?}','HelloController@index');

これで修正完了。

/hello/taro/yamadaというように、/helloの後に2つのパラメータを付けてアクセス。

2つのパラメータの値が画面に表示。

f:id:mkyosuke:20200108135007p:plain

 

ルートパラメータの設定

 Route::getを見てみる。以下のように第1引数が用意されている。

Route::get('hello/{id?}/{pass?}

{id?}と{pass?}の2つのパラメータが用意される。いずれも?をつけて、

任意パラメータとして用意。

 

アクションメソッドの設定

 ここでは、以下のメソッドの定義が変更されている。

public function index($id='noname', $pass='unknown' ){

indexメソッドには、$idと$passの2つの引数を追加。

これが、ルートパラメータに指定された{id}と{pass}の値を受け取るための引数となる。

先にRoute::getの第2引数にクロージャとして処理を用意したが、そのままアクションメソッドに置き換わっていることがわかる。

今回は、任意パラメータで、それぞれの引数にデフォルト値を指定。

 

複数アクションの利用

 コントローラには、複数のアクションを用意ができる。

今回はHelloContorller.phpのHelloContorllerクラスを以下に修正。

クラス以外にグローバル変数も用意。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

global $head$style$body$end;

$head = '<html><head>';
$style = <<<EOF

<style>
body {font-size:20px}
h1 {fontsize:100px}
</style>
EOF;

$body ='</head><body>';
$end ='</body></html>';
function tag($tag, $txt){
    return "<{$tag}>".$txt."</{$tag}>";
}
class HelloController extends Controller
{
    public function index(){
        global $head$style$body$end;

        $html = $head.tag('title','Hello/Index').$style.$body
        .tag('h1','Index').tag('p','this is Index page')
        .'<a href="/hello/other">go to Other page</a>'.$end;
        return $html;
    }

    public function other(){
        global $head$style$body$end;

        $html = $head.tag('title','Hello/other').$style.$body
        .tag('h1','other').tag('p','this is other page')
        .$end;
        return $html;
    }
}

 コントローラの記述後、Web.phpに用意したHelloContorller@indexのルート情報を新たに編集。

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

 修正完了後、Webブラウザで/helloにアクセス。

そして、「go to Otrher page」のリンクをクリック。/hello/otherに移動しページが表示

f:id:mkyosuke:20200108150614p:plain

go to Other page遷移後

 

f:id:mkyosuke:20200108150722p:plain

 

複数のページの対応

 HelloContorllerクラスに「index」「Other」という2つのアクションメソッドを用意。

そして、Web.phpにて、

/helloにindex

/hello/otherにotherをそれぞれ割り当てる。

ページが複数になっても基本的に変わらない。たた割り当てるアドレスには注意。

 

アクションとアドレスの関係

 ここでは、/helloと/hello/otherにアクションを割り当てており、基本的にアドレスとコントローラまたはアクションの関連は、以下のように対応させるのが一般的。

http://アプリケーションのアドレス/コントローラ/アクション

 HelloContorllerのindexアクションならば、/hello/indexとしておくのが一般的であるが、

Webの世界では、indexは省略してアクセスできるようにしておくのが一般的なので

/helloでアクセスできるようにしてある。

 

シングルアクションコントローラ

 複数アクションと反対に、「1つのコントローラに1つのアクションだけしか用意しない」というのもある。

この場合、「シングルアクションコントローラ」としてクラスを用意。

シングルアクションコントローラは、特別なクラスというわけではなく、一般的なアクションメソッドの代わりに、「__invoke」というメソッドを使って処理をする。

■シングルアクションコントローラの基本の形

class コントローラ extends Controller
{
    public function __invoke(){
        ---アクション処理---
    }
}

 これ以外にアクションメソッドは用意しない。メソッドは追加できるが、それらのアクションとして利用はできない。

 

シングルアクションコントローラとして作成されたコントローラは、ルート情報の設定も少し変わってくる。

Route::get('アドレス','コントローラ名');

 このように、コントローラ名だけを指定。アクションの指定はしない。

これにより、指定のアドレスにコントローラが割り当てられる。そのアドレスにアクセスすると、クラスの__invokeが呼び出され処理が実行する。

 

HelloControllerをシングルアクション化

 HelloControllerクラスをシングルアクションコントローラに変更。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HelloController extends Controller
{
    public function __invoke(){
    
    return <<<EOF
    
    <html>
    <head>
    <title>Hello</title>
    <style>
    body{font-size:20px}
    h1{font-size:30px}
    </style>
    </head>
    <body>
      <h1>Sample</h1>
      <p>single action controller</P>
    </body>
    </html>
    EOF;
    
    }
}

 コントローラの修正後、Web.phpを開き、HelloControllerのルート情報を修正。

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

 これで作業完了。Webブラウザから/helloにアクセス。

割り当てるコントローラまたはアクションを示す第2引数には、コントローラ名だけしか記述していない。指定したコントローラの__invokeが呼び出される。

f:id:mkyosuke:20200108162852p:plain

 

リクエストとレスポンス

 ここまで作成したアクションメソッドは、引数も特に用意がなくシンプルな構造。

実際のWebアクセスは、内部で多くの情報をやり取りしている。

PHPでは、アクセスに関する情報を取得する為に$_REQUESTなどのグローバル変数を利用する。

クライアントからサーバーへアクセスしたとき、クライアントから送られてくる情報を「リクエスト」、そしてサーバーからクライアントへの情報は「レスポンス」として扱う。

 このリクエストとレスポンスの情報は、Laravelでも利用することができる。

これはllluminate\Http名前空間に用意されている「Request」「Respose」というクラスとして用意されている。

これらのオブジェクトには、リクエストまたはレスポンスに関する情報を保管するプロパティや、操作するためのメソッドが用意されている。

 

RequestおよびResponse

 実際にRequestおよびResponseオブジェクトを使う。

HelloController.phpを編集

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;

class HelloController extends Controller
{
    public function index(Request $requestResponse $response) {
    
    return <<<EOF
    <html>
    <head>
    <title>Hello/Index</title>
    <style>
    body{font-size:20px}
    h1{font-size:30px}
    </style>
    </head>
    <body>
      <h1>Sample</h1>
      <h3>Request</h3>
      <pre>{$request}</pre>
      <h3>Response</h3>
      <pre>{$response}</pre>
    </body>
    </html>
    EOF;
    
        $response->setConttent($html);
        return $response;
    
    }
}

 続いて、ルート情報の設定

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

 /helloにアクセスしたらHelloControllerのindexアクションが実行。

クライアントからヘッダー情報が、またレスポンスからはキャッシュコントローㇽや日付などの情報が得られる。

 

/helloにアクセスすると、Request/Responseのプロパティが表示。

 

f:id:mkyosuke:20200108171524p:plain

 

 

アクションメソッドの引数定義

RequestとResponseを利用する為、use文に追記

use Illuminate\Http\Request;
use Illuminate\Http\Response;

Requestはデフォルトで用意されていたのでそれに、Responseのuseを追加。

これらの利用は、アクションメソッドで行う。

indexを見ると、以下のような形で定義。

public function index(Request $requestResponse $response) {

引数に、RequestとResponseが用意。このように引数を追加するだけでインスタンスが用意され、使えるようになる。

 

Requestの主なメソッド

 Requestの利用例のメソッド

$request->url();

urlは、アクセスしたURLを返す。ただし、クエリ文字(アドレスの後に付く、?abc=xxxというようなもの)は省力される。

 

$request->fullurl();

fullurlは、アクセスしたアドレスを完全な形で返す(クエリ文字も含む)

 
$request->paeh();
pathは、ドメイン下のパス部分だけを返す。
 
Responseの主なメソッド

 続いてResponse。

$this->status();

 アクセスに関するステータスコードを返す。これは正常にアクセスが終了していたら200となる。

$this->content();
$this->setContent(値);

 コンテンツの取得・設定を行うもの。contentはコンテンツを取得し、setContentは引数の値にコンテンツを変更。