
Mini API on Lumen

The purpose of this publication is to create a simple Lumen API and consider its differences from the older brother. All code is available here .
I installed it on the homestead box, incl. controlled by one line:
composer create-project laravel/lumen --prefer-dist Lumen
Learn more about homestead.
The project structure is similar to Laravel: The

lack of the / config folder is striking. The fact is that Lumen relies entirely on the contents of the .env file. Content example:
DB_CONNECTION=mysql
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_DATABASE=lumen
All possible settings can be found in vendor / laravel / lumen-framework / config /.
So,
DB structure
Suppose we need a post entity, plus 2 methods - registration and login.
To create migrations, we will use the artisan command utility.
php artisan make:migration create_users_table
php artisan make:migration create_posts_table
Now in the / database folder there are 2 new files. In each of 2 methods, up and down - migration and cancellation of migration.
This is the up method of the users table:
//database/*create_users_table.php
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email')->unique();
$table->string('first_name');
$table->string('last_name');
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
For posts:
//database/*create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('user_id');
$table->string('content');
$table->timestamps();
$table->softDeletes();
});
Migrations are ready, we are trying to apply them:
php artisan migrate
But for some reason, the artisan does not see the variables from the .env file and complains about poor connection parameters. In order to export variables, you need to uncomment the line in /bootstrap/app.php:
Dotenv::load(__DIR__.'/../');
Also turned off by default ORM Eloquent and facades. The pieces are useful, so I included them too.
Now everything should work out:

(art is alias for php artisan)
We also create Eloquent models for these tables. For example, a post model:
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('Written\Models\User');
}
}
Models allow you to give data from methods with less pain, because they take care of table relationships. Of course, the performance of raw database queries is better, but the development speed with this approach will steadily degrade. Such queries are relevant, in my opinion, only for statistical samples.
Controllers
Laravel 5 has a wonderful Trait that allows you to do all the registration with two clicks of your fingers. Unfortunately, this is not the case in Lumen. It’s also customary now not to write all routes to one file, but to use annotations, for example:
/**
* @Middleware("auth.token")
* @Resource('post')
*/
class PostsController extends Controller {
public function index() {}
public function show($id) {}
public function store() {}
public function update() {}
public function destroy() {}
}
This annotation says the controller is RESTful. T.O. having 1 open file before your eyes, you already have an understanding of how to access methods and what filters they have. This is done with the help of laravelcollective / annotations . But it is incompatible with Lumen, so all the routes will have to be shoved into /app/http/routes.php:
$app->get('/', function() use ($app) {
return $app->welcome();
});
$app->post('/register', ['uses' => 'App\Http\Controllers\AuthController@postRegister']);
$app->post('/login', ['uses' => 'App\Http\Controllers\AuthController@postLogin']);
$app->get('/post/{id}', ['uses' => 'App\Http\Controllers\PostsController@show']);
$app->get('/post', ['uses' => 'App\Http\Controllers\PostsController@index']);
$app->group(['middleware' => 'logged.in'], function($app) {
$app->post('/post', ['uses' => 'App\Http\Controllers\PostsController@store']);
/** & another protected routes */
});
In a normal application, this file becomes monstrous quickly.
Lumen, like Laravel, has Middleware that can either filter specific requests or do all sorts of usefulness for each request. All such filters are in / app / Http / Middleware /. In order for Lumen to know about their existence, you need to add the corresponding classes in /bootstrap.app.php.
Middleware example:
//app/Http/Middlewared/LoggedInMiddleware.php
class LoggedInMiddleware {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if(!Auth::check()) {
return new Response('', 401);
}
return $next($request);
}
}
The described filter returns an http code 401 if the request comes from an unauthorized user.
Controller example:
//app/Http/Controller/PostsController.php
/**
* Class PostsController
* @package App\Http\Controllers
*/
class PostsController extends Controller
{
public function index()
{
return $this->respondWithData(Post::with('user')->all()->toArray());
}
public function show($id)
{
return $this->respondWithData(Post::find($id)->with('user')->get()->toArray());
}
public function store()
{
$rules = [
'text' => 'required',
];
$input = $_POST;
$validator = Validator::make($input, $rules);
if ($validator->fails()) {
return $this->respondWithFailedValidation($validator);
}
$post = new Post;
$post->content = $input['content'];
$post->user()->associate(Auth::user());
$post->save();
return $this->show($post->id);
}
// public function delete() {}
}
An example of the profit from using Eloquent can be seen in the show () method. The client is given not only information about the post, but also about the associated user.
respondWith * methods - auxiliary, to give the code some organization. In general, a method can even return a regular string.
Conclusion
No wonder it is stated that Lumen is fully compatible with Laravel, because after all that I have written, I don’t feel like I wrote something about Lumen.
But still, when developing even the above-described functionality, there was a sediment:
- incompatible with libraries written for Laravel. The same annotations are the de facto standard;
- to enter you need to know Laravel, tk. much of what is described in Laravel docks doesn't work, and little is written in Lumen docks. I have to watch the source. For example, facades - not all are available. Missing ones must be registered by hand;
- I could not start the tests, because for some reason $ _POST does not arrive in the method.
I have only