Can't generate API documentation in l5-swagger - php

I'm starting to study swagger.
I'm trying to do the same which is done in a book "Hands-On Full Stack Web Development with Angular 6 and Laravel 5".
Using php-fpm bash after typing command "php artisan l5-swagger:generate"
I have got this exception in VS Code terminal:
root#8e6435be9103:/application# php artisan l5-swagger:generate
Regenerating docs
ErrorException : Required #OA\Info() not found
at /application/vendor/zircote/swagger-php/src/Logger.php:39
35| $this->log = function ($entry, $type) {
36| if ($entry instanceof Exception) {
37| $entry = $entry->getMessage();
> 39| trigger_error($entry, $type);
40| };
41| }
42|
43| /**
Exception trace:
1 trigger_error("Required #OA\Info() not found")
/application/vendor/zircote/swagger-php/src/Logger.php:39
2 OpenApi\Logger::OpenApi\{closure}("Required #OA\Info() not found")
/application/vendor/zircote/swagger-php/src/Logger.php:71
And when I trying to open http://localhost:8081/api/documentation url it gives this error:
Failed to load API definition.
Fetch errorNot Found http://localhost:8081/docs/api-docs.json
I'am using php-fpm bash inside docker.
My OS is Ubuntu 18.04.3 LTS.
Can anyone help me to fix this problem.
Thank you!!!

You have to put some annotations in your code before running php artisan l5-swagger:generate. First, go to app/Http/Controllers/Controller.php and add a phpdoc comment block as follow before the class declaration:
/**
* #OA\Info(title="My First API", version="0.1")
*/
This annotation by itself is sufficient to resolve the issue that you described, but if you execute php artisan l5-swagger:generate again you will see the following Exception:
ErrorException : Required #OA\PathItem() not found
at /home/nathanael/dev/laravel-projects/laravel-swagger/vendor/zircote/swagger-php/src/Logger.php:39
35| $this->log = function ($entry, $type) {
36| if ($entry instanceof Exception) {
37| $entry = $entry->getMessage();
38| }
> 39| trigger_error($entry, $type);
40| };
41| }
42|
43| /**
Exception trace:
1 trigger_error("Required #OA\PathItem() not found")
/home/nathanael/dev/laravel-projects/laravel-swagger/vendor/zircote/swagger-php/src/Logger.php:39
2 OpenApi\Logger::OpenApi\{closure}("Required #OA\PathItem() not found")
/home/nathanael/dev/laravel-projects/laravel-swagger/vendor/zircote/swagger-php/src/Logger.php:71
Please use the argument -v to see more details.
That's because you must have at least one method in a controller with an annotation that describes a route.
You can easily create a resource in your application to test running php artisan make:controller ProjectsController -r and adding Route::resource('projects', 'ProjectsController') to routes/web.php.
After creating the controller open it and add the following phpdoc comment block before the index method, for example:
/**
* #OA\Get(
* path="/projects",
* #OA\Response(response="200", description="Display a listing of projects.")
* )
*/
Then, run php artisan l5-swagger:generate again and you must see a success message in the terminal.

Related

Laravel 8 - Programmatically run migration and seeder when database has no tables

After connecting to database, I want to programmatically run migration and seeder once the project detects that the database doesn't have any tables.
I think what I should do is inject the code below somewhere, but I don't know what file I should edit.
if (!Schema::hasTable('users')) {
$init_met = ini_get('max_execution_time');
set_time_limit(300);
Artisan::call('migrate:fresh');
Artisan::call('db:seed');
set_time_limit($init_met);
}
Or, is there an alternative way to do this instead of injecting the code?
Thanks in advance.
i'd suggest you to look at composer scripts section - there are a lot of events that could be used as trigger for your code. for example post-autoload-dump event fired after composer dumpautoload which is fired in most common calls like install, update or by itself. the benefit of using composer events is that you don't need to check for existing tables on each request.
the most easy way to achieve this is to create custom artisan command
php artisan make:command PrepareEmptyDatabase
then in app\Console\Commands\PrepareEmptyDatabase.php
<?php
namespace App\Console\Commands;
use Exception;
use App\Http\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
class PrepareEmptyDatabase extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'db:prepare-empty';
/**
* The console command description.
*
* #var string
*/
protected $description = 'check for users table and run migrations and seed if has not';
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
// don't forget to remove this if database user
// don't have access to dba tables
if (Schema::hasTable('users')) {
return Command::SUCCESS;
}
/*
// if your user doesn't have permission to access to dba tables
// you can simply try to do any request to users table
$needActions = false;
try {
User::first();
} catch (Exception $ex) {
$needActions = true;
}
if (!$needActions) {
return Command::SUCCESS;
}
*/
$init_met = ini_get('max_execution_time');
set_time_limit(300);
Artisan::call('migrate:fresh');
Artisan::call('db:seed');
set_time_limit($init_met);
return Command::SUCCESS;
}
}
and the last step is tie this command with composer event, so in composer.json
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"#php artisan package:discover",
"#php artisan db:prepare-empty"
]
},
now any time you install/update composer dependencies or just run composer dumpatoload application will run your custom command. or you can stick with any of provided in composer docs event on your taste
about running the same code after npm run dev
i'm not quite sure about place to search, guess its about webpack events, but your question tagged with laravel so i assume you're using laravel-mix and there are event hooks
quick googling says that nodejs can run bash scripts using nodejs child process
// webpack.mix.js
const exec = require('child_process')
// or import exec from 'child_process'
mix
.js('resources/assets/js/app.js', 'public/js')
// other configs
.after(() => {
exec.execSync('php artisan db:prepare-empty')
})
pay attention that this code will run on any mix even including npm run prod for example and i don't actually understand why do you need it in frontend build event (if only for testing purpose and even then its questionable)

Laravel Errors in tinker using factory->create() but not when running migration/seed commands in artisan

I am able to successfully run the migration/factory/seeders from the command line using php artisan migrate:fresh --seed
However when I try to manually create a category using tinker, I'm getting errors:
<warning>PHP Warning: Array to string conversion in /Users/[my_name]/Sites/blog/vendor/laravel/framework/src/Illuminate/Support/Str.php on line 99</warning>
TypeError: Illuminate\Database\Grammar::parameterize(): Argument #1 ($values) must be of type array, string given, called in /Users/[my_name]/Sites/blog/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php on line 886
And
<warning>PHP Warning: Array to string conversion in /Users/[my_name]/Sites/blog/vendor/laravel/framework/src/Illuminate/Support/Str.php on line 99</warning>
=> App\Models\Category {#4529
name: [
"quaerat",
"voluptatem",
],
slug: "array",
}
Factory code:
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
class CategoryFactory extends Factory
{
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
$name = $this->faker->words(2,true);
$slug = Str::of($name)->slug('-');
return [
'name' => ucwords($name),
'slug' => $slug
];
}
}
I have two questions:
Why do the two methods (make and create) cause different, albeit related, errors?
Why does tinker get tripped up when the normal migration/seed process works fine?
Please and thank you.
I still don't know why the two errors were different, but it's pedantic.
Thank you to #Rwd! I now know that we need to restart tinker after we change our application code in Laravel.
The string to array error was from a previous version of the code before I figured out to add the second parameter to $this->faker->words() — which is why it worked with php artisan migrate:fresh --seed and with in php artisan tinker \App\Models\Category::factory()->create();

problem while running php artisan route:list with jwt installed

I've followed this tutorial
https://tutsforweb.com/restful-api-in-laravel-56-using-jwt-authentication/
and it's working fine,
but when i try to run
php artisan route:list
i get this error ,
Tymon\JWTAuth\Exceptions\JWTException : The token could not be parsed from the request
at F:\My_Projects\Laravel\api-laravel-jwt\vendor\tymon\jwt-auth\src\JWT.php:185
181| */
182| public function parseToken()
183| {
184| if (! $token = $this->parser->parseToken()) {
> 185| throw new JWTException('The token could not be parsed from the request');
186| }
187|
188| return $this->setToken($token);
189| }
Exception trace:
1 Tymon\JWTAuth\JWT::parseToken()
F:\My_Projects\Laravel\api-laravel-jwt\vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php:223
2 Illuminate\Support\Facades\Facade::__callStatic("parseToken", [])
F:\My_Projects\Laravel\api-laravel-jwt\app\Http\Controllers\ProductController.php:14
Please use the argument -v to see more details.
and i've been trying to get around it, but couldn't succeed, any help?
This is a github Repo with my code:-
https://github.com/Imohamedgabr/laravel-5.7-jwt-starter
in the product controller, in this part:-
public function __construct()
{
$this->user = JWTAuth::parseToken()->authenticate();
}
it calls the parse token, that's why it goes to the jwt auth parse token and fails there.
so while there's no authenticated user provided, it fails.
hope this helps.

Symfony 4 - Default value for parameters with a class type hint can only be NULL

I have a similar problem than here : Symfony 4 : Default value for parameters with a class type can only be but when I launch composer commands... :
executing script security-checker security:check [KO]
[KO]
Script security-checker security:check returned with error code 255
!! PHP Fatal error: Default value for parameters with a class type hint can only be NULL in /xxx/vendor/symfony/console/Application.php on line 83
!!
Script #auto-scripts was called via post-update-cmd
When I launched for example : php7 composer.phar update, because I had the same problem for others commands...
I don't understand because I use the 7.1.8 PHP version... I installed the whole project with my PHP 7.1.8... :/
Code affected :
/**
* #param string $name The name of the application
* #param string $version The version of the application
*/
public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') // Line affected HERE (line 83)
{
$this->name = $name;
$this->version = $version;
$this->terminal = new Terminal();
$this->defaultCommand = 'list';
}
An idea for me ?
Thank you very much !
I don't know if it's OK to do that... I replaced this line in composer.json :
"security-checker security:check": "script"
by :
"security:check": "symfony-cmd"
I guess and hope the command is the same. I don't understand why. I follow the official documentation of Symfony 4 and I have the correct PHP version. :/
I don't know at all... TT__TT

DoctrineCacheBundle: Flush cache via SYmfony route

Over my Symfony project I use the DoctrineCacheBundle and I want when I visit http://example.com/api/cache/flush I want to uncache (flush) any cached key.
The sole reason is because I have applications that visit the url above in order to remove any cached result.
As far I searched the DoctrineCacheBundle uses a command in order to uncache the cached results (as you can see via php ./bin/console list doctrine:cache command):
Symfony 3.3.12 (kernel: app, env: dev, debug: true)
Usage:
command [options] [arguments]
Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-e, --env=ENV The environment name [default: "dev"]
--no-debug Switches off debug mode
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands for the "doctrine:cache" namespace:
doctrine:cache:clear Flush a given cache
doctrine:cache:contains Check if a cache entry exists
doctrine:cache:delete Delete a cache entry
doctrine:cache:flush [doctrine:cache:clear] Flush a given cache
doctrine:cache:stats Get stats on a given cache provider
But how can I do this programmatically?
The best way is to make your own Cache adapter by following one of theese 2 approaches:
Approach 1: Use dedicated manager for uncaching:
namespace AppBundle\CacheManagers;
use Doctrine\Common\Cache\FlushableCache;
class PurgeAllcachesManager
{
/**
* #var FlushableCache
*/
private $purgeCachingHandler=null;
public function __construct(FlushableCache $purgeCachingHandler)
{
$this->purgeCachingHandler=$purgeCachingHandler;
}
/**
* Method that does all the dirty job to uncache all the keys
*/
public function uncache()
{
$this->purgeCachingHandler->flushAll();
}
}
Approach2: Do as Doctrine does:
namespace AppBundle\CacheManagers;
use Doctrine\Common\Cache\Cache as CacheHandler;
class PurgeAllcachesManager
{
/**
* #var CacheHandler
*/
private $cacheHandler=null;
public function __construct(CacheHandler $cacheHandler)
{
$this->cacheHandler=$cacheHandler;
}
/**
* Method that does all the dirty job to uncache all the keys
* #throws Exception
*/
public function uncacheAllKeys()
{
if(!method_exists($this->purgeCachingHandler) ){
throw new Exception("You cannot empty the cache");
}
$this->purgeCachingHandler->flushAll();
}
//Yet another methods to handle the cache
}
Also have a look on this question for extra info on how to use it.

Categories