Search code examples
laravelopenapiswagger-php

$ref "#/components/responses/" not found for @OA\Response(response=200)


I am trying to implement openAPI documentation in a Laravel project. I am using darkaonline/l5-swagger package, which is built on top of swagger-php to generate the documentation. I am facing a problem with references. I want to export the response of an API call to an external file outside the controller, that I am documenting, and for this purpose I'm using references. However, in this particular project I get this annoying error when generating the documentation:

Upon running:

php artisan l5-swagger:generate

I get the following output

  $ref "#/components/responses/" not found for @OA\Response(response=201) in \App\Http\Controllers\Organization\OrganizationController->get() in /data/www/nnaydenov/laravel-sandbox/app/Http/Controllers/Organization/OrganizationController.php on line 58

  at vendor/zircote/swagger-php/src/Loggers/DefaultLogger.php:31
     27▕         } else {
     28▕             $error_level = E_USER_WARNING;
     29▕         }
     30▕ 
  ➜  31▕         trigger_error($message, $error_level);
     32▕     }
     33▕ }
     34▕ 

      +33 vendor frames 
  34  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

Here is my controller:

class OrganizationController extends Controller
{
    /**
     * @OA\Get(
     *     path="second-example",
     *     operationId="secondExample",
     *     @OA\Response(
     *         response=200,
     *         description="Hello from my awesome description",
     *         @OA\JsonContent(
     *             @OA\Property(
     *                 property="foo",
     *                 type="string",
     *                 example="bar",
     *             )
     *         )
     *     ),
     *     @OA\Response(
     *         ref="#/components/responses/foo",
     *         response=201
     *     )
     * )
     */
    public function get($id = null)
    {
        // ...
    }
}

Here is the file that contains the response, I want to reference. It is located in app/Something/SomethingElse:

<?php

/**
 * @OA\Response(
 *   response="foo",
 *   description="Sample description",
 *   @OA\JsonContent(
 *         @OA\Property(
 *             property="foo",
 *             type="string",
 *             example="bar",
 *         )
 *     )
 * )
 */

The top level annotations, located at app\Http\Controllers\Controller:

namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

/**
 * @OA\Info(
 *      version="1.0.0",
 *      title="Api documentation",
 *      description="Api documentation",
 *      @OA\Contact(
 *          email="[email protected]"
 *      ),
 *      @OA\License(
 *          name="Apache 2.0",
 *          url="http://www.apache.org/licenses/LICENSE-2.0.html"
 *      )
 * )
 *
 * @OA\Server(
 *      url=L5_SWAGGER_CONST_HOST,
 *      description="Demo API Server"
 * )
 *
 * @OA\Tag(
 *     name="Projects",
 *     description="API Endpoints of Projects"
 * )
 */
class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    // ...
}

I guess there is something wrong with the project, I am trying to implement this at, because the same code works in a plain Laravel 8 project. However, I don't know how to debug this issue. I tried to manually create an openapi.json file using

./vendor/bin/openapi . -o openapi.json

But this results into numerous errors, which I haven't managed to fix. Any suggestions as to what the cause of this error might be or how to even debug this?


Solution

  • If this is a new project chances are that you are now using swagger-php V4. In version 4 the analyser code uses reflection. This was done to make it possible to use either annotations or PHP 8 attributes.

    One downside is that stand-alone docblocks are no longer detected as there is no reflection to access those.

    The simplest way to fix this is to add a class FooResponse{} line after the annotations and swagger-php should find it again.

    The same applies to other top level annotations like @OA\Info or others.

    See: https://zircote.github.io/swagger-php/guide/faq.html#warning-required-oa-info-not-found

    In practice that would mean to add class FooResponse {} to the annotation:

    <?php
    
    /**
     * @OA\Response(
     *   response="foo",
     *   description="Sample description",
     *   @OA\JsonContent(
     *         @OA\Property(
     *             property="foo",
     *             type="string",
     *             example="bar",
     *         )
     *     )
     * )
     */
    class FooResponse {}