How to integrate Swagger in Lumen/Laravel for REST API? - laravel-5.4

I have built some REST API in Lumen micro framework and it's working fine. Now I want to integrate Swagger into it so the API will be well documented on future use. Has anyone done this?

Steps to follow for Laravel Lumen 5.7 with swagger using OpenApi 3.0 specs (this governs the way you write annotations so that swagger documentation is generated)
The steps were written a while ago but they still work with Laravel Lumen 6.X, 7.X and 8.X
I reached this adjusting on #black-mamba answer in order to make it work.
1. Install swagger-lume dependency (which also installs swagger)
composer require "darkaonline/swagger-lume:5.6.*"
2. Edit bootstrap/app.php file
make sure $app->withFacades(); is NOT commented (around line 26)
in Create The Application section add the following before Register Container Bindings section
$app->configure('swagger-lume');
in Register Service Providers section add
$app->register(\SwaggerLume\ServiceProvider::class);
3. Publish configuration file for swagger-lume
php artisan swagger-lume:publish
4. Add annotations to your code
For example in your app/Http/Controllers/Controller.php you could have the general part of the documentation
<?php
namespace App\Http\Controllers;
use Laravel\Lumen\Routing\Controller as BaseController;
class Controller extends BaseController
{
/**
* #OA\Info(
* title="Example API",
* version="1.0",
* #OA\Contact(
* email="support#example.com",
* name="Support Team"
* )
* )
*/
}
And inside each of your controllers you should have the appropriate annotations above each public method
<?php
namespace App\Http\Controllers;
class ExampleController extends Controller
{
/**
* #OA\Get(
* path="/sample/{category}/things",
* operationId="/sample/category/things",
* tags={"yourtag"},
* #OA\Parameter(
* name="category",
* in="path",
* description="The category parameter in path",
* required=true,
* #OA\Schema(type="string")
* ),
* #OA\Parameter(
* name="criteria",
* in="query",
* description="Some optional other parameter",
* required=false,
* #OA\Schema(type="string")
* ),
* #OA\Response(
* response="200",
* description="Returns some sample category things",
* #OA\JsonContent()
* ),
* #OA\Response(
* response="400",
* description="Error: Bad request. When required parameters were not supplied.",
* ),
* )
*/
public function getThings(Request $request, $category)
{
$criteria= $request->input("criteria");
if (! isset($category)) {
return response()->json(null, Response::HTTP_BAD_REQUEST);
}
// ...
return response()->json(["thing1", "thing2"], Response::HTTP_OK);
}
}
5. Generate swagger documentation
php artisan swagger-lume:generate
Run this each time you update the documentation
see:
https://zircote.github.io/swagger-php/
https://github.com/DarkaOnLine/SwaggerLume
https://swagger.io/specification/

I had really hard time in learning how to use it. Here I'm going to share some of the things I did to get it working
Use this wrapper
Run this command in your terminal:
composer require "darkaonline/swagger-lume:5.5.*"
Or older version from the repo linked if this doesn't work for you
Then from the repo follow these steps:
Open your bootstrap/app.php file and:
uncomment this line (around line 26) in Create The Application
section:
$app->withFacades(); add this line before Register Container Bindings section:
$app->configure('swagger-lume'); add this line in Register Service Providers section:
$app->register(\SwaggerLume\ServiceProvider::class);
Then you'll need to use annotations for your project instead of YAML or JSON
For more
Create a Annotation.php file in your app folder add the following a sample
/**
* #SWG\Swagger(
* basePath="/",
* schemes={"http"},
* #SWG\Info(
* version="1.0.0",
* title="HAVE MY BOOKS",
* #SWG\Contact(
* email="example#test.com"
* ),
* )
* )
*/
/**
* #SWG\Get(
* path="/",
* summary="Version",
* #SWG\Response(
* response=200,
* description="Working"
* ),
* #SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
Then run
php artisan swagger-lume:publish
Then run
php artisan swagger-lume:generate
This generates JSON which can be accessed from your localhost:8000 or whichever port you are serving your LUMEN service
Note: after creating an issue in the repo I found that to access you'll need to serve or run using
php -S localhost:8000 public/index.php
Because of some PHP routing issue with php -S localhost:8000 public

Related

Symfony Doctrine runs same queries

since the last update of my server which happened last month, I face an unusual problem with Doctrine.
When I run doctrine:schema:update --force, I the result "54 queries executed". The same result happens even if I don't change my entities.
When I run doctrine:schema:update --dump-sql to see the queries, I can see that same queries are run. Ex :
ALTER TABLE artisan CHANGE creator_id creator_id INT DEFAULT NULL;
ALTER TABLE user_connection CHANGE date date DATETIME DEFAULT NULL;
ALTER TABLE device CHANGE device_type device_type VARCHAR(500) DEFAULT 'ios' NOT NULL;
The problem is that columns are from the same type that the one changed by the query. I don't know why Doctrine want to change the type.
MariaDB version is 10.4.13 - Doctrine version is 2.5.14 - Symfony version is 2.8.42
Entity examples :
Device : device_type
/**
* #var string
*
* #ORM\Column(name="device_type", type="string", length=500, options={ "default":"ios" })
*/
private $device_type = "ios";
UserConnection : date
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetime", nullable=true)
*/
private $date;
Artisan : Creator
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="MiddlewareBundle\Entity\User")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="creator_id", referencedColumnName="id", nullable=true)
* })
*/
private $creator;
There has been a pull request some years ago, have a look at https://github.com/doctrine/dbal/pull/2825 - it clearly states your problem:
Doctrine currently does not support MariaDB 10.2.7+. Schema creation/update is triggering infinite schema diffs
The code from this pull request has been included since doctrine/dbal:2.7.0, so you should consider updating at least that single package

Laravel daily cron job automatically?

How I can create automatically record daily with laravel task scheduling without running artisan command. In my case I just want when the date is 28-02-2020 create record in db, when date is 29-02-2020 create another record and etc...
Just check Laravel docs on Task Scheduling. First add this cron entry:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Then, You may define all of your scheduled tasks in the schedule method of the App\Console\Kernel class:
/**
* Define the application's command schedule.
*
* #param \Illuminate\Console\Scheduling\Schedule $schedule
* #return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('your_table')->insert([
'first_column' => 'first_value',
// List other columns
]);
})->daily();
}

create rule class in dektrium module rbac in basic project yii2

I installed dektrium\user and dektrium\rbac\ modules for manage user and access control.Related tables and files installed completely and i can see several tabs in /user/admin path ( Users, Roles, Permissions, Rules, Create ) for work with modules.I can manage users perfectly(create user, reset password, edit,..). buy I can not create a rule.
I created a class in app\rbac\rules folder named AuthorRule :
<?php
namespace app\rbac\rules;
use yii\rbac\Rule;
use app\models\News;
/**
* Checks if authorID matches user passed via params
*/
class AuthorRule extends Rule
{
public $name = 'isAuthor';
/**
* #param string|int $user the user ID.
* #param Item $item the role or permission that this rule is associated with
* #param array $params parameters passed to ManagerInterface::checkAccess().
* #return bool a value indicating whether the rule permits the role or permission it is associated with.
*/
public function execute($user, $item, $params)
{
return isset($params['news']) ? $params['news']->createdBy == $user : false;
}
}
(I created news class with model,controler,views)
but when I entered name and class rule in my modules. Neither the data is logged nor the error message. I can't add the rest of the sections until I get into the rule.
I certainly hope the OP has solved their problem by now, but other people might encounter it.
First a remark: as described, the Save fails silently. This is because the form is submitted with Ajax (XHR). The error can be seen in the browser console.
This is the relevant part of the error message:
preg_match(): Compilation failed: invalid range in character class at offset 8
Due to the architecture of Yii 2, the actual regexp is a little tricky to find. It is in the model for Rules in yii2-rbac vendor/dektrium/yii2-rbac/models/Rule.php, line 86.
The original regexp is /^[\w][\w-.:]+[\w]$/
PHP 7.3 uses the PCRE2 library instead of the original PCRE, and the pattern above is wrong. The dash (-) needs to be escaped.
The full line should now be:
['name', 'match', 'pattern' => '/^[\w][\w\-.:]+[\w]$/'],
As the yii2-rbac package is abandoned, you can just modify the file. A more robust solution would be to override the Class.

Laravel Migration | Drop/create tables in raw SQL NO error, NO effect

For a new Laravel project, I need to use an existing MySQL database (176 tables). I don't want to create a Laravel migration for each existing table, so I've made an export of the database structure to a sql file.
In a migration I want to execute the SQL file, like so:
public function up()
{
DB::unprepared(file_get_contents('/path/to/file.sql'));
}
unprepared returns true but it seems the import will not be (fully) executed. No error, no effect (sometimes, there are 1 or 2 tables created, for example after dropping and recreating the database before executing the sql file).
When I execute this file with mysql source /path/to/file.sql, the import works fine (some errors by version difference will be reported, but the execution continues).
My question: for testing purposes, I want to creating the 176 old/existing tables from an SQL file during the migration process. I need to alter some tables during the migration process.
I don't want to create a migration for each table.
You can do reverse migration for all your tables by following these steps:-
1)composer require --dev "xethron/migrations-generator"
2)in bootstrap/app -$app->register(\Way\Generators\GeneratorsServiceProvider::class);
$app->register(\Xethron\MigrationsGenerator\MigrationsGeneratorServiceProvider::class);
3)In bootstrap/app.php add
class Application extends Laravel\Lumen\Application
{
/**
* Get the path to the application configuration files.
*
* #param string $path Optionally, a path to append to the config path
* #return string
*/
public function configPath($path = '')
{
return $this->basePath.DIRECTORY_SEPARATOR.'config'.($path ? DIRECTORY_SEPARATOR.$path : $path);
}
}
if (!function_exists('config_path')) {
/**
* Get the configuration path.
*
* #param string $path
* #return string
*/
function config_path($path = '')
{
return app()->basePath() . '/config' . ($path ? '/' . $path : $path);
}
}
if (!function_exists('app_path')) {
/**
* Get the path to the application folder.
*
* #param string $path
* #return string
*/
function app_path($path = '')
{
return app('path') . ($path ? DIRECTORY_SEPARATOR . $path : $path);
}
}
class_alias('Illuminate\Support\Facades\Config', 'Config');
$app = new Application(
realpath(__DIR__.'/../')
);
4) write php artisan migrate:generate in terminal
5) change
$app = new Application(
realpath(__DIR__.'/../')
);
to
$app = new Laravel\Lumen\Application(
realpath(__DIR__.'/../')
);
in bootstrap/app.php

symfony 2 many to many relation crud

I've created a many to many relation and generated crud via command line. I have Users and Groups.
USER
/**
* #ORM\ManyToMany(targetEntity="Grup", mappedBy="users")
* #ORM\JoinTable(name="user_has_grup",
* joinColumns={#ORM\JoinColumn(name="grup_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
protected $grups;
Grup
/**
* #ORM\ManyToMany(targetEntity="User", inversedBy="grups")
* #ORM\JoinTable(name="user_has_grup",
* joinColumns={#ORM\JoinColumn(name="grup_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
protected $users;
When i create user group show up but i can't assign user to group. Still when i go to edit Group i can assign User to it and its works well.
What do I need to change, if i want to be able do it in both directions? Is there any Doctrine Entity change or in controller ?
Don't know if it's your problem because not enough code...
But i think this can help : Symfony2-Doctrine: ManyToMany relation is not saved to database
And official documentation :Owning and Inverse Side on a ManyToMany association