ユーザーがアクセスするURLを理解して、必要な関数にマップするのがroutes.phpの基本的な仕事です。
それらのURLには、以下のようにいろいろな形があります。
http://localhost/admin/login http://localhost/admin/product/156 http://localhost/admin/product/156/edit
さて、上の例の156の数字は、DBテーブルのproduct
の主キーの値なのですが、Laravelはこの値をどのようにコントローラに取り込むのでしょう?
まず、前回のroutes.phpの設定を見てみましょう。
Route::resource('product', 'ProductController');
は、
php artisan route:list
の出力では以下のようなマップになります。
+--------+-----------+------------------------------------+------------------------+-----------------------------------------------------------------------+-----------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+-----------+------------------------------------+------------------------+-----------------------------------------------------------------------+-----------------+ | | POST | admin/product | admin.product.store | App\Http\Controllers\Admin\ProductController@store | web | | | GET|HEAD | admin/product | admin.product.index | App\Http\Controllers\Admin\ProductController@index | web | | | GET|HEAD | admin/product/create | admin.product.create | App\Http\Controllers\Admin\ProductController@create | web | | | GET|HEAD | admin/product/{product} | admin.product.show | App\Http\Controllers\Admin\ProductController@show | web | | | DELETE | admin/product/{product} | admin.product.destroy | App\Http\Controllers\Admin\ProductController@destroy | web | | | PUT|PATCH | admin/product/{product} | admin.product.update | App\Http\Controllers\Admin\ProductController@update | web | | | GET|HEAD | admin/product/{product}/edit | admin.product.edit | App\Http\Controllers\Admin\ProductController@edit | web | +--------+-----------+------------------------------------+------------------------+-----------------------------------------------------------------------+-----------------+
URIの部分を見てください。
例えば、7行目の
admin/product/{product}
は、
ProductController@show
にマップされています。
そして156のIDは、この{product}
の部分に対応します。
admin/product/{product}/edit
も同じことです。
対応するコントローラのメソッドを見ると、
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Models\Product; class ProductController extends Controller { /** * 表示画面 * * @param \App\Models\Product $product * @return \Illuminate\Http\Response */ public function show(Product $product) { return $product->name; //画面に商品名を表示 } ...
show
のパラメータが、数字でなくモデルのProduct
のタイプになっていますね。
これは、Laravelが自動的に、IDの数字をもとに、
$product = Product::find(156);
のようなモデルバインディング(紐づけ)操作を行って、Eloquentのオブジェクトを生成して、メソッドの中で使用できるようにしてくれているのです。便利ですね。
さて、product_id = 156に対応するDBレコードがない場合はどうなるのでしょう?
Sorry, the page you are looking for could not be found. 2/2 NotFoundHttpException in Handler.php line 102: No query results for model [App\Product]. 1/2 ModelNotFoundException in Builder.php line 290: No query results for model [App\Product].
「検索結果が空」の404エラーとなります。
今度は、上のshowの関数のパラメータ名を以下のように変えたとしたら、どうなるのでしょう?
public function show(Product $a_product) { return $a_product_name;//画面は空 }
この場合、$a_project_nameにはDBレコードが入らず、単にProjectの新規オブジェクトとなり、画面には何も表示されません。
つまり、パラメータ名は、{product}とまったく同じ名前である必要があるということです。ミススペルに気をつけましょう。
さて、今度は、product_idではなく、例えば、skuという商品番号の項目の値でレコードを引っ張ってきたいときはどうするのでしょう?
つまり、
http://localhost/admin/product/ABCDE
でアクセスしたい。そこでは、ABCDがskuの値とします。
その場合は、Productのモデルの定義で、
namespace App; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected $table = 'product'; protected $primaryKey = 'product_id'; public function getRouteKeyName() { return 'sku'; } ... }
のように、getRouteKeyName
の関数を作成して、skuをリターンすれば、product_idの代わりに以下のようにオブジェクトを作成してくれます。
$product = Product::where('sku', 'ABCD')->first();
もちろん、skuは、productのDBテーブルで、主キーと同様に1つのレコードを特定するためにユニークなキーを持つ必要あります。
最後に、
http://localhost/admin/product/156?print=Y
の場合、printの値はどう取ってくるのでしょう?
これはshowメソッドを以下のように変更して、
... /** * 表示画面 * * @param \App\Models\Product $product * @param \Illuminate\Http\Request * @return \Illuminate\Http\Response */ public function show(Product $product, Request $request) { $print = $request->input('print'); return $print; } ...
printの値の取得が可能です。ここ、関数のパラメータの順番はURLでの順番とは関係ありません。逆でも同じ結果となります。先に説明したように、{product}の名前と一致する変数名でLaravelは判断するからです。
メルマガ購読の申し込みはこちらから。