So I'm trying to migrate a small site to Laravel. Trying to come to grips with basic code organization. For starters, I'd like to set up my site with basic controller and model(s) so that this url:
http://example.com/product/123
Will display product information for record with id=123 in my db table named products.
My post is intended to show what I've managed to grok so far. My questions are at the bottom. Any commentary or insights or *****ing and moaning about Laravel are welcome and encouraged.
The docs on controllers have some interesting/maddening instructions on how to create controllers with a command. This is the basic command
php artisan make:controller FooController
It creates a file, app/Http/Controllers/FooController.php, which looks like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FooController extends Controller
{
//
}
This command does not expose one's controller on the website. You still have to define a route for it. You can do that by adding a line like this to routes/web.php:
Route::get('product/{id}', 'FooController@method_name');
It's disappointing a bit that the controller is not automatically exposed when you create it (as with CodeIgniter) and it's also tedious to have to add all kinds of routes manually. It's especially irritating to have to learn yet another weird little syntax and a whole slew of complicated rules about routing, but I guess it's kind of nice that one has a great deal of control over the routes. One can also apparently specify all kinds of namespace and middleware particulars etc. -- which looks to be pretty powerful -- but I haven't yet grasped how to take advantage of these features.
One can also create a 'resource' controller -- this is apparently a controller that handles CRUD for some particular data type. This command constructs a resource controller FooController for a model BarModel:
php artisan make:controller FooController --resource --model=BarModel
If BarModel doesn't exist, it will create a stub file app/BarModel.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BarModel extends Model
{
//
}
This command creates a much more elaborate controller with methods for the various CRUD actions:
<?php
namespace App\Http\Controllers;
use App\BarModel;
use Illuminate\Http\Request;
class FooController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param \App\BarModel $barModel
* @return \Illuminate\Http\Response
*/
public function show(BarModel $barModel)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \App\BarModel $barModel
* @return \Illuminate\Http\Response
*/
public function edit(BarModel $barModel)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\BarModel $barModel
* @return \Illuminate\Http\Response
*/
public function update(Request $request, BarModel $barModel)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \App\BarModel $barModel
* @return \Illuminate\Http\Response
*/
public function destroy(BarModel $barModel)
{
//
}
}
Interestingly, these controllers go right into the app/Https folder -- there's no option to create cli or api controllers. And apparently no default location for them either. Even with auto-generation of model and controller, one must still manually add a route:
Route::resource('photos', 'PhotoController');
I'd like to whinge about the routing of of PUT/PATCH for update operations as indicated in the table in the docs on resource controllers. Since HTML forms don't support PUT or PATCH methods, one must add an extra input in these forms to spoof the PUT input method:
<input type="hidden" name="_method" value="PUT">
What pedantry is this? I'd love to poke the jerk in the eye who decided this was a good idea.
While it's great to have these stub files generated, and I'm aware of Laravel's ability to automatically inject dependencies based on type-hinting, I'm a bit confused about a variety of things.
1) How do I connect this newly generated BarModel class to a database table?
The laravel documentation doesn't have a section on models.
2) How do I best protect some of these methods (insert/update/delete) while allowing all access to others?
The authentication functionality seems like the canonical/orthodox way to go here and I'm hoping to toe that line, but I also recall this warning when reading the docs on controllers:
You may assign middleware to a subset of controller actions; however, it may indicate your controller is growing too large. Instead, consider breaking your controller into multiple, smaller controllers.
3) What's with the code organization?
I see that auto-generated models live in the app directory. Do all of my models go in there? Seems odd not to have a Models directory somewhere. If I do create a Models directory, how would this affect my namespacing commands and autoloading? Also, the app dir has Console and Http but no Api directory despite having a built-in routes/api.php.
Any help/commentary would be much appreciated. So far, this whole framework seems completely ad-hoc.