I just got into api documentation and tried to use Swagger
here is my php file with routes that I want to document:
<?php
use OpenApi\Annotations as OA;
/**
* #OA\Info(title="My First API", version="0.1")
*/
return [
/**
* #OA\Get(
* path="/api/v1/test",
* #OA\Response(response="200", description="An example resource")
* )
*/
'GET api/v1/test' => 'test/index',
];
But when I run ./vendor/bin/openapi api/config/routes.php cli only outputs errors:
Warning: Required #OA\Info() not found
Warning: Required #OA\PathItem() not found
openapi: 3.0.0
I then tried Swagger2 and it worked just fine
Im using php8.1 from php:8.1-fpm-alpine docker image, the latest zircote/swagger-php package and the Yii2 framework
Alternatively, you could also add -b ./vendor/autoload.php to the openapi command to setup autoloading for swagger-php.
Either way I am surprised that this works with swagger-php v4 as that requires annotations to be anchored to a structural element (class, interface, etc.)
The main idea here is to annotate your actual controllers (or whatever it is called in your framework), so the code that handles a request so the documentation is close to the actual code.
Here is solution
https://github.com/DarkaOnLine/L5-Swagger/issues/443
Add in your base Controller
<?php
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(title="My First API", version="0.1")
*/
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
Turns out openapi was not autoloading classes from my subfolders
The solution is very simple: generate docs from inside of a console application (for example I have a php yii open-api/generate-docs command)
That way composer and yii2 load all of the classes needed for swagger
You also have to anchor all of the attributes to specific classes so the approach in the original question will not work; my solution was to create a compiled router with each route having a separate class with php8.1 attributes
Related
I've had to try and work with an older package meant for php into my Laravel project.
I've added two custom classes, both are in the same folder "Classes" under the main "app" folder in my Laravel project.
One of these classes is recognized from a generated controller for my Laravel project. My paymentsController has use App\Classes\Quickbooks_Payments; in the top.
However, going to that Classes' file, I hit the following error through a route leading to my controller:
Class 'App\Classes\Quickbooks_Loader' not found
Now this is where this above is referenced in my paymentsController file:
<?php
namespace App\Classes\Quickbooks_Payments;
use App\Classes\Quickbooks_Loader;
/**
* QuickBooks Payments class
*
*/
/**
* Utilities class (for masking and some other misc things)
*/
QuickBooks_Loader::load('/QuickBooks/Utilities.php');
This last line is where the above error is referenced. And I do have both the Quickbooks_Loader.php and the Quickbooks_Payments.php in the same folder. My Quickbooks_Loader.php file starts off as such:
<?php
namespace App\Classes\QuickBooks_Loader;
So I know this is likely because of my inexperience with custom/imported classes. What am I doing wrong and how should I properly "import" these custom classes and have them recognized without any issues?
Change namespace in both classes you've shown to:
namespace App\Classes;
And run composer du
Also, make sure the class looks like this and not like you've shown (I'm not sure about did you cut something or not):
<?php
namespace App\Classes;
use App\Classes\Quickbooks_Loader;
class Quickbooks_Payments
{
public function __construct()
{
dd('It\'s working!');
}
}
I'm trying to use PHP SQL Query Builder in a project I'm working on. I am installing it manually. I did this by copying the src directory into my project and then using the following code within my class:
$this->builder = new NilPortugues\Sql\QueryBuilder\Builder\GenericBuilder();
The error I get whenever the builder is used is:
[18-Apr-2017 12:57:48 UTC] PHP Fatal error: Interface 'NilPortugues\Sql\QueryBuilder\Builder\BuilderInterface' not found in /home/thomassm/public_html/php/lib/sqlbuilder/Builder/GenericBuilder.php on line 24
GenericBuilder.php
namespace NilPortugues\Sql\QueryBuilder\Builder;
use NilPortugues\Sql\QueryBuilder\Builder\Syntax\WriterFactory;
use NilPortugues\Sql\QueryBuilder\Manipulation\AbstractBaseQuery;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryInterface;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryFactory;
use NilPortugues\Sql\QueryBuilder\Manipulation\Select;
use NilPortugues\Sql\QueryBuilder\Syntax\Column;
use NilPortugues\Sql\QueryBuilder\Syntax\Table;
/**
* Class Generic.
*/
class GenericBuilder implements BuilderInterface
{//...}
BuilderInterface.php
namespace NilPortugues\Sql\QueryBuilder\Builder;
use NilPortugues\Sql\QueryBuilder\Manipulation\QueryInterface;
/**
* Interface BuilderInterface.
*/
interface BuilderInterface
{
/**
* #param QueryInterface $query
*
* #return string
*/
public function write(QueryInterface $query);
/**
* #param QueryInterface $query
*
* #return string
*/
public function writeFormatted(QueryInterface $query);
}
I assume the error is somehow caused by the way the files are called, any suggestions?
I am installing it manually. I did this by copying the src directory into my project and then using the following code within my class: ...
Every source file should be included through include/requrie before using. But PHP allow to setup autoloading for classes, interfaces and traits. In short, when runtime meets an undefined class then a special callback invokes, which can load the relevant file.
Although formally the autoloading rules can be arbitrary, but most of the modern projects supports the common community standard: PSR-4 Autoloader. So, you need an implementation of this standard.
As said in the library description, the recommended way to install is through Composer:
php composer.phar require nilportugues/sql-query-builder
Composer provides own PSR-4 implementation and generates file vendor/autoload.php. Usually this file included at the application entry point. It allow using the classes from all required libraries.
You can use the packages without the Composer (relevant answer). But it requires a lot of work (you still need an PSR-4 autoloader) and this way is rarely used today.
I am really new to symfony but a long year developer. Now I decided to look at symfony but as it is with new things, problems aint far :)
I want to include a class into my project. Everytime I create a instanec of the class
$fw = new FloydWarshall($graph, $nodes);
i'll receive an internal error 500.
What am I doing wrong ?
Structure:
app/
...
bin/
...
src/AppBundle/
Controller/MyController.php
Entity/
...
Model/
fw.class.php
Reposetory/
...
var/
...
vendor/
...
web/
...
So in my class the namespace looks like
namespace AppBundle\Controller;
use AppBundle\Entity\lpNodes;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use AppBundle\Model\FloydWarshall;
....
In my fw.class.php the header looks like:
<?php
/**
* #package FloydWarshall
* #author Janne Mikkonen <janne dot mikkonen at julmajanne dot com>
* #date $Date: 2013/03/23 05:10:48 $
* #version $Revision: 1.1.1 $
* #license GNU General Public License, version 2 http://www.opensource.org/licenses/GPL-2.0
**/
namespace AppBundle\Model;
class FloydWarshall {
the constructor of FloydWarshall:
/**
* Constructor
* #param array $graph Graph matrice.
* #param array $nodenames Node names as an array.
*/
public function __construct($graph, $nodenames='') {
$this->weights = $graph;
$this->nodes = count($this->weights);
if ( ! empty($nodenames) && $this->nodes == count($nodenames) ) {
$this->nodenames = $nodenames;
}
$this->__floydwarshall();
}
As per comment, Symfony 3 uses either PSR-0 or PSR-4. Assuming that you're using Composer, you configure which one to support in your composer.json file.
With PSR-4, your filenames must correspond to your class names, and your directory names must match your namespaces. So if your entity is called FloydWarshall in the namespace AppBundle\Entity:
it must be in the directory src/AppBundle/Entity
the file must be called FloydWarshall.php
The reason for this strictness is the autoloader which comes with Composer. When you do new AppBundle\Entity\FloydWarshall, the autoloader knows where to find the file for that class. In your case, you had named it fw.class.php so the autoloader couldn't find it.
Tangentially to the question, are you using the dev environment? If you are, Symfony will give you a very helpful error message which will help you to diagnose the problem much quicker.
I have a Symfony project to which I added some non-symfony php files containing various classes. But for some reason the classes are not loaded when loading the website, even though the IDE sees them properly.
So, I have a class that needs other classes:
namespace rootspace\FrontBundle\Controller;
use rootspace\FrontBundle\Networks\TwitterOAuth;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class TwitterController extends Controller
{
public function connectAction(){
// The TwitterOAuth instance
$connection = new TwitterOAuth('abc', '123');
}
}
And then the class which fails to load (that needs yet another file)
namespace rootspace\FrontBundle\Networks;
/* Load OAuth lib. You can find it at http://oauth.net */
//require_once('OAuth.php'); -- should this be commented out?
/**
* Twitter OAuth class
*/
class TwitterOAuth {
/* Contains the last HTTP status code returned. */
}
Lastly, the third file
namespace rootspace\FrontBundle\Networks;
use Symfony\Component\Config\Definition\Exception\Exception;
class OAuthConsumer
{
public $key;
public $secret;
}
(...)
I assume the actual filenames don't matter, right? Nor their structure? PhpStorm sees all the classes properly, I can right-click through them, but it fails when deployed.
Thanks for help
Edit - the whole error message says
Attempted to load class "TwitterOAuth" from namespace "rootspace\FrontBundle\Networks" in D:\Dropbox\project\src\rootspace\FrontBundle\Controller\TwitterController.php line 15. Do you need to "use" it from another namespace?
This is because Symfony's autoloader follows PSR standards (PSR-0, PSR-4) which says that fully qualified (with namespace) class name translates to file location and name. So in fact file names does matter.
So in your case rootspace\FrontBundle\Networks\TwitterOAuth class should be located in rootspace/FrontBundle/Networks directory in file called TwitterOAuth.php
If classes you are using does not follow PSR standards you can also register them manually in app/autoloader.php file
Check these for more info:
How can I add a namespace to Symfony 2.1?:
How to autoload class
And check this answer
I forgot to add a .php extension to my filename
I am trying to use ExclusionPolicy however I keep getting an "Annotation does not exist, or could not be auto-loaded" error.
Here is the exact error being thrown out:
[Semantical Error] The annotation
"#JMS\SerializerBundle\Annotation\ExclusionPolicy" in class
Acme\DemoBundle\Entity\Attributes does not exist, or could not be
auto-loaded.
My code is as follows:
namespace Acme\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints;
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Expose;
/**
* Acme\DemoBundle\Entity\Attributes
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Acme\DemoBundle\Entity\AttributesRepository")
*
* #ExclusionPolicy("all")
*/
class Attributes
{
...
}
your problem is caused by using the wrong namespace.
Instead of:
use JMS\SerializerBundle\Annotation\ExclusionPolicy;
use JMS\SerializerBundle\Annotation\Expose;
It should be:
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
Notice "Bundle" is gone. In Ver 0.11 it was extracted to its own repository.
The changelog is as follows:
Namespace Changes
The core library has been extracted to a dedicated repository
schmittjoh/serializer to make it easier re-usable in any kind of PHP
project, not only in Symfony2 projects. This results in several
namespace changes. You can adjust your projects by performing these
replacements (in order):
JMS\SerializerBundle\Serializer -> JMS\Serializer
JMS\SerializerBundle -> JMS\Serializer
JMS\Serializer\DependencyInjection -> JMS\SerializerBundle\DependencyInjection
Dependency Changes
You might need to increase versions of jms/di-extra-bundle, and also
jms/security-extra-bundle depending on your stability settings.
Sometimes it is also necessary to run a composer update twice because
of a bug in composer's solving algorithm.