ArticleAttributes: description: Article attributes description type: object properties: title: required: true type: string minLength: 16 maxLength: 256 facets: index: idx_title: index description: required: true type: string minLength: 32 maxLength: 1024 facets: spell_check: true spell_language: en url: required: false type: string minLength: 16 maxLength: 255 facets: index: idx_url: unique show_in_top: description: Show at the top of main page required: false type: boolean status: description: The state of an article enum: ["draft", "published", "postponed", "archived"] facets: state_machine: initial: ['draft'] draft: ['published'] published: ['archived', 'postponed'] postponed: ['published', 'archived'] archived: [] topic_id: description: ManyToOne Topic relationship required: true type: integer minimum: 1 maximum: 6 facets: index: idx_fk_topic_id: foreign references: id on: topic onDelete: cascade onUpdate: cascade rate: type: number minimum: 3 maximum: 9 format: double date_posted: type: date-only time_to_live: type: time-only deleted_at: type: datetime
php artisan api:generate oas/openapi.yaml --migrations
<?php namespace Modules\V1\Http\Controllers; class ArticleController extends DefaultController { }
<?php namespace Modules\V2\Entities; use Illuminate\Database\Eloquent\SoftDeletes; use rjapi\extension\BaseModel; class Article extends BaseModel { use SoftDeletes; // >>>props>>> protected $dates = ['deleted_at']; protected $primaryKey = 'id'; protected $table = 'article'; public $timestamps = false; public $incrementing = false; // <<<props<<< // >>>methods>>> public function tag() { return $this->belongsToMany(Tag::class, 'tag_article'); } public function topic() { return $this->belongsTo(Topic::class); } // <<<methods<<< }
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateArticleTable extends Migration { public function up() { Schema::create('article', function(Blueprint $table) { $table->bigIncrements('id'); $table->string('title', 256); $table->index('title', 'idx_title'); $table->string('description', 1024); $table->string('url', 255); $table->unique('url', 'idx_url'); // Show at the top of main page $table->unsignedTinyInteger('show_in_top'); $table->enum('status', ["draft","published","postponed","archived"]); // ManyToOne Topic relationship $table->unsignedInteger('topic_id'); $table->foreign('topic_id', 'idx_fk_topic_id')->references('id')->on('topic')->onDelete('cascade')->onUpdate('cascade'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('article'); } }
// >>>routes>>> // Article routes Route::group(['prefix' => 'v2', 'namespace' => 'Modules\\V2\\Http\\Controllers'], function() { // bulk routes Route::post('/article/bulk', 'ArticleController@createBulk'); Route::patch('/article/bulk', 'ArticleController@updateBulk'); Route::delete('/article/bulk', 'ArticleController@deleteBulk'); // basic routes Route::get('/article', 'ArticleController@index'); Route::get('/article/{id}', 'ArticleController@view'); Route::post('/article', 'ArticleController@create'); Route::patch('/article/{id}', 'ArticleController@update'); Route::delete('/article/{id}', 'ArticleController@delete'); // relation routes Route::get('/article/{id}/relationships/{relations}', 'ArticleController@relations'); Route::post('/article/{id}/relationships/{relations}', 'ArticleController@createRelations'); Route::patch('/article/{id}/relationships/{relations}', 'ArticleController@updateRelations'); Route::delete('/article/{id}/relationships/{relations}', 'ArticleController@deleteRelations'); }); // <<<routes<<<
<?php namespace Modules\V1\Http\Requests; use rjapi\extension\BaseFormRequest; class ArticleFormRequest extends BaseFormRequest { // >>>props>>> public $id = null; // Attributes public $title = null; public $description = null; public $url = null; public $show_in_top = null; public $status = null; public $topic_id = null; public $rate = null; public $date_posted = null; public $time_to_live = null; public $deleted_at = null; // <<<props<<< // >>>methods>>> public function authorize(): bool { return true; } public function rules(): array { return [ 'title' => 'required|string|min:16|max:256|', 'description' => 'required|string|min:32|max:1024|', 'url' => 'string|min:16|max:255|', // Show at the top of main page 'show_in_top' => 'boolean', // The state of an article 'status' => 'in:draft,published,postponed,archived|', // ManyToOne Topic relationship 'topic_id' => 'required|integer|min:1|max:6|', 'rate' => '|min:3|max:9|', 'date_posted' => '', 'time_to_live' => '', 'deleted_at' => '', ]; } public function relations(): array { return [ 'tag', 'topic', ]; } // <<<methods<<< }
http://example.com/v1/article?include=tag&page=2&limit=10&sort=asc
http://example.com/v1/article/1?include=tag&data=["title", "description"]
http://example.com/v1/article/1?include=tag&order_by={"title":"asc", "created_at":"desc"}
http://example.com/v1/article?include=tag&filter=[["updated_at", ">", "2018-01-03 12:13:13"], ["updated_at", "<", "2018-09-03 12:13:15"]]
POST http://laravel.loc/v1/article { "data": { "type":"article", "attributes": { "title":"Foo bar Foo bar Foo bar Foo bar", "description":"description description description description description", "fake_attr": "attr", "url":"title title bla bla bla", "show_in_top":1 } } }
{ "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar", "description": "description description description description description", "url": "title title bla bla bla", "show_in_top": 1 }, "links": { "self": "laravel.loc/article/1" } } }
GET http://laravel.loc/article/1
or save it for future use. GET http://laravel.loc/v1/article?include=tag&filter=[["updated_at", ">", "2017-01-03 12:13:13"], ["updated_at", "<", "2019-01-03 12:13:15"]] { "data": [ { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 1", "description": "The quick brovn fox jumped ower the lazy dogg", "url": "http://example.com/articles_feed 1", "show_in_top": 0, "status": "draft", "topic_id": 1, "rate": 5, "date_posted": "2018-02-12", "time_to_live": "10:11:12" }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "1" } ] } } } ], "included": [ { "type": "tag", "id": "1", "attributes": { "title": "Tag 1" }, "links": { "self": "laravel.loc/tag/1" } } ] }
GET http://laravel.loc/v1/article/1?include=tag&data=["title", "description"] { "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 123456", "description": "description description description description description 123456", }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "3" }, { "type": "tag", "id": "1" }, { "type": "tag", "id": "2" } ] } } }, "included": [ { "type": "tag", "id": "3", "attributes": { "title": "Tag 4" }, "links": { "self": "laravel.loc/tag/3" } }, { "type": "tag", "id": "1", "attributes": { "title": "Tag 2" }, "links": { "self": "laravel.loc/tag/1" } }, { "type": "tag", "id": "2", "attributes": { "title": "Tag 3" }, "links": { "self": "laravel.loc/tag/2" } } ] }
PATCH http://laravel.loc/v1/article/1/relationships/tag { "data": { "type":"article", "id":"1", "relationships": { "tag": { "data": [{ "type": "tag", "id": "2" },{ "type": "tag", "id": "3" }] } } } }
{ "data": { "type": "article", "id": "1", "attributes": { "title": "Foo bar Foo bar Foo bar Foo bar 1", "description": "The quick brovn fox jumped ower the lazy dogg", "url": "http://example.com/articles_feed 1", "show_in_top": 0, "status": "draft", "topic_id": 1, "rate": 5, "date_posted": "2018-02-12", "time_to_live": "10:11:12" }, "links": { "self": "laravel.loc/article/1" }, "relationships": { "tag": { "links": { "self": "laravel.loc/article/1/relationships/tag", "related": "laravel.loc/article/1/tag" }, "data": [ { "type": "tag", "id": "2" }, { "type": "tag", "id": "3" } ] } } }, "included": [ { "type": "tag", "id": "2", "attributes": { "title": "Tag 2" }, "links": { "self": "laravel.loc/tag/2" } }, { "type": "tag", "id": "3", "attributes": { "title": "Tag 3" }, "links": { "self": "laravel.loc/tag/3" } } ] }
php artisan api:generate oas/openapi.yaml --migrations --regenerate --merge=last
<?php return [ 'name' => 'V2', 'query_params'=> [ // - 'limit' => 15, 'sort' => 'desc', 'access_token' => 'db7329d5a3f381875ea6ce7e28fe1ea536d0acaf', ], 'trees'=> [ // 'menu' => true, ], 'jwt'=> [ // jwt 'enabled' => true, 'table' => 'user', 'activate' => 30, 'expires' => 3600, ], 'state_machine'=> [ // finite state machine 'article'=> [ 'status'=> [ 'enabled' => true, 'states'=> [ 'initial' => ['draft'], 'draft' => ['published'], 'published' => ['archived', 'postponed'], 'postponed' => ['published', 'archived'], 'archived' => [''], ], ], ], ], 'spell_check'=> [ // 'article'=> [ 'description'=> [ 'enabled' => true, 'language' => 'en', ], ], ], 'bit_mask'=> [ // permissions ( true/false / ) 'user'=> [ 'permissions'=> [ 'enabled' => true, 'flags'=> [ 'publisher' => 1, 'editor' => 2, 'manager' => 4, 'photo_reporter' => 8, 'admin' => 16, ], ], ], ], 'cache'=> [ // 'tag'=> [ 'enabled' => false, // tag 'stampede_xfetch' => true, 'stampede_beta' => 1.1, 'ttl' => 3600, ], 'article'=> [ 'enabled' => true, // article 'stampede_xfetch' => true, 'stampede_beta' => 1.5, 'ttl' => 300, ], ], ];
Source: https://habr.com/ru/post/427741/
All Articles