paknahad / jsonapi-bundle Goto Github PK
View Code? Open in Web Editor NEWthe fastest way to generate API based on jsonapi.org using woohoolabs/yin
License: MIT License
the fastest way to generate API based on jsonapi.org using woohoolabs/yin
License: MIT License
Hello @paknahad @kocsismate,
When I write a relationship method in my transformer
public function getRelationships($order): array
{
return [
'customer' => $order->getCustomer(),
];
}
in yin AbstractResourceTransformer
the variable $relationshipCallback
https://github.com/woohoolabs/yin/blob/65e6bc15aa6efdcef8c17a4b246ba581192f5b7b/src/JsonApi/Transformer/AbstractResourceTransformer.php#L204
is an object (a proxy one) handled by symfony
.
yin require a string
, no ?
Regards,
I tried to POST two entities (User and Address) and associate them, but it looks like the code expects both entities to be already persisted. I wonder if this is possible with the current code structure?
The exception listener passes null as exception code, it would be nice to pass the exception code of the thrown exception instead.
I'll create a PR for this change.
Can you please tell me what the reason may be that I am not obtaining the target object in my queries
Hello,
I can see that class Controller
is deprecated
https://github.com/symfony/framework-bundle/blob/master/Controller/Controller.php#L17
Is it legitimate to use AbstractController
instead ?
Regards,
Another thing I found while using your Querifier bundle.
In Querifier bundle sort is expected to be array and in jsonapi bundle it is expected to be a string. Its not a big issue, I have overriden Sorter given by jsonapi bundle to fix it but maybe you can check if sort is array and then do not do the explode().
So basically I check if sort is array in parseSortingString method ( it does not have argument type which actually saves the day - link ) and if it is array, just implode it and continue with parent method.
I can do a PR if you want :)
Hello.
I have an entity which have one-to-many relationship to other entity. But when I get a request, the response doesn't have a relationships
field.
When I get a request with include
parameter, the response has relationships
in data object and includes
.
But how can I get all attributes and relationships in data object without include
?
When using this bundle we have encountered 2 things with the Hydrators.
The generated CreateEntityHydrator and UpdateEntityHydrator contain duplicate code. Wouldn't it be better to move the field list to the AbstractEntityHydrator?
Not all values get set correctly. A datetime field for example should go through new \DateTime() (or new DateTimeImmutable()). It would be very nice if the generated code would be correct out of the box.
I hve no idea currently on how to fix these issues, I just wanted to share our experience so far. I works very nice btw, the out-of-the-box experience with make:api is very nice!
Hi,
can you make a new tag for #68 so it is available via composer?
I am planning to do a couple of more fixes, but I'm not sure I will have time this week.
I tried this excelent bundle today and got a deprecation warning.
Class WoohooLabs\Yin\JsonApi\Document\AbstractCollectionDocument is deprecated, use WoohooLabs\Yin\JsonApi\Schema\Document\AbstractCollectionDocument instead.
[▼
"exception" => SilencedErrorContext^ {#874 ▶}
]
{▼
/.../vendor/woohoolabs/yin/src/JsonApi/Document/AbstractCollectionDocument.php:13 {▶}
/.../src/JsonApi/Document/User/UsersDocument.php:12 {▼
› */
› class UsersDocument extends AbstractCollectionDocument
› {
}
}
Hello @paknahad,
thank you for this great Symfony bundle, which saves a lot of time and is the best I could find on symfony and json-api standard.
I started writing functional api tests in Codeception for a project which is using this jsonapi-bundle and I encountered a problem.
In a nutshell, all tests cases after the first one will fail with a "Invalid json" error message. This can be reproduced either by using a @dataProvider
or by simply having multiple test functions in a single test class. The effect is the same. You can read a detailed description of the issue here woohoolabs/yin#81
The reason being is that Paknahad\JsonApiBundle\Controller
is caching jsonapi responses between tests, and the json api responses in the response buffer get mixed up. The same output buffer is reused over and over and this gives a corrupt json after the first test.
Is there some way to disable this caching in test environments or do you have some other suggestion on this issue?
Is there any way currently to set a prefix for the generated routes when running php bin/console make:api
? I was not able to find any and the enforced routes seem to be deeply ingrained in the generation process (e.g. just changing the annotation on the controller does not updated the route information provided from the API responses).
Suggestion: keep asking for another Entity name until the user returns blank!
PS: This bundle is amazing! Keep up the good work!
Hi!
I noticed that all of the validation errors for attributes array are formatted correctly, but if you send a wrong type, that causes WoohooLabs' exception ResourceTypeUnacceptable
, you will get an Internal server error with code 500. After digging in to the code, I found that this could be fixed in JsonApiErrorHandlerEvent::toErrorDocument
, by calling the exception's toErrorDocument
method, if the exception is an instance of JsonApiExceptionInterface
.
What do you think? Is there a better way to do this?
Hello,
actually I didn't find any way to disable pagination in the response of the jsonapi.
Is it possible to add a parameter or something like that to make it easy possible?
Validating fields with validExistence set to false creates an exception when calling the getValidator method.
"Argument 1 passed to App\\JsonApi\\Hydrator\\JobPosition\\AbstractJobPositionHydrator::getValidator() must be of the type string, null given, called in /var/www/html/vendor/paknahad/jsonapi-bundle/src/Hydrator/ValidatorTrait.php on line 89"
.
Parameter is not nullable but can be null due to validExistence set to false.
I'm integrating this package and it seems to work great so far! However, I've got one issue that I'm not sure of how to implement it. So for example I want to fetch a list of Project
s. I do this while I'm logged in with a User
. Every Project
is coupled to a User
in the database. So I'm trying to add a default filter on Project
like WHERE user_id = x
before this package does its magic.
Can this be achieved?
@paknahad Thx for solving last issue :) Here is a new one :)
When using FOSUser bundle and you try to generate json api via make:api it breaks on unique and nullable indexes in $fields array ( ApiCrud.php#L318 )
This is due to mapping xml in FOSUser bundle not having unique and nullable attributes ( User.orm.xml#L9 ). Probably there are more cases when some bundle does not have those fields defined in xml mapping. It is fixable by setting default value when no unique/nullable index or by setting those fields to unique via UniqueEntity constraint, eg.: @UniqueEntity(fields={"username"}, message="Username is taken")
I think preferable way would be that those indexes have some default values that developer can override. I am happy to make a PR if you want :)
?filter[numeric_field]=5%
I get this error:
Conversion failed when converting the nvarchar value '5%' to data type int.
This seems to be related with COUNT; this occurs when using $paginator->getCount()
in the documents' collection:
SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT id_11 FROM (SELECT p0_.numeric_field AS numeric_field_0, [...] FROM patients p0_ WHERE p0_.numeric_field = ?)[...]
It's using =
instead of like
.
This is a restriction imposed in Finder, to only use "like" on strings:
jsonapi-bundle/src/Helper/Filter/Finder.php
Lines 109 to 111 in c62899c
I will create a PR for this issue to describe how the Finder strategy works.
It seems there are no Request objects in RequestStack when doing OPTIONS (preflight request) on a route that uses your Controller since it requires JsonApi object and it is created via factory.
Quick way to fix this is to check if there is a Request object in RequestStack and if there is not, just create a new, empty one.
I can do a PR if you agree on a fix :)
Hi. IDK if put this here or in paknahad/jsonapi-bundle, because this happens when using this extension.
I get this error (when authenticating using NelmioApiDocs or via Postman) when I use a custom Finder or paknahad/jsonapi-querifier-bundle:
[critical] Uncaught Error: Argument 1 passed to Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory::createRequest() must be an instance of Symfony\Component\HttpFoundation\Request, null given, called in ./vendor/paknahad/jsonapi-bundle/src/Factory/JsonApiFactory.php on line 45
When
APP_DEBUG
is set totrue
, this break the JSON response with the warning as plain text, so only works withAPP_DEBUG=false
.
Seems to be related with the requestStack, like an issue in AdactiveSAS/saml2-bridge-bundle#28
jsonapi-bundle/src/Factory/JsonApiFactory.php
Lines 41 to 46 in 98c75e1
Maybe my config is wrong?
My services.yaml
config is:
services:
paknahad_json_api.helper_filter.finder:
class: Paknahad\JsonApiQuerifierBundle\Finder\Querifier
public: false
tags:
- { name: paknahad.json_api.finder }
Am I missing something?
Hey, first time using this bundle so hopefully im not missing something super obvious with this..
It appears that there is a Transformer missing when I run the make:api
command.
The relationship is below - but when trying to getRelationships()
- the AgentPhoneResourceTransformer
is missing
Is this something I am doing wrong?
Thanks!
#[ORM\Entity(repositoryClass: AgentRepository::class)]
class Agent {
... code
#[Groups(['agent'])]
#[OneToMany(
mappedBy: 'agent',
targetEntity: AgentPhone::class)
]
private $phones;
}
#[ORM\Table(name: 'phone')]
#[ORM\Entity(repositoryClass: AgentPhoneRepository::class)]
#[ORM\HasLifecycleCallbacks]
class AgentPhone {
... code
#[ManyToOne(targetEntity: Agent::class, inversedBy: 'phones')]
#[JoinColumn(name: 'associated_id', referencedColumnName: 'id')]
private ?Agent $agent;
}
Hi,
first of all: Thanks for the amazing bundle. Really impressive to generate a JSON-API right out of the box!
I have 2 questions though:
First:
I create an User-Entity with php bin/console make:entity User
and generate the API for it with php bin/console make:api User
. Works great!
Now I want to modify the User-Entity later on using the update-functionality of php bin/console make:api User
. The API does not represent these changes though.
If I run php bin/console make:api User
again I get errors that the files are already existing (e.g. "[ERROR] The file "src/Controller/UserController.php" can't be generated because it already exists").
What is the proposed way to update the api?
If I just delete the controller and the JsonApi
-directory that the command created it works fine.
But I'm not sure if this is the way to go or am I missing something? :)
Second:
This is kind of related to my first question. If I don't want to display all fields of an Entity in the API-Response, I just adjust the getAttributes()
-method in the related ResourceTransformer
, right?
But if the only way to update the API when an Entity changes later on is to delete the JsonApi
-directory this way to restrict the displayed content is quite fragile.
Thanks for you help and the awesome bundle! ;)
After upgrading "psr/http-message" from version 1.1 to 2.0 this bundle can't be used anymore and you get the following error log:
php.CRITICAL: Fatal Compile Error: Declaration of WoohooLabs\Yin\JsonApi\Request\AbstractRequest::withCookieParams(array $cookies) must be compatible with Psr\Http\Message\ServerRequestInterface::withCookieParams(array $cookies): Psr\Http\Message\ServerRequestInterface {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Compile Error: Declaration of WoohooLabs\\Yin\\JsonApi\\Request\\AbstractRequest::withCookieParams(array $cookies) must be compatible with Psr\\Http\\Message\\ServerRequestInterface::withCookieParams(array $cookies): Psr\\Http\\Message\\ServerRequestInterface at /var/www/symfony/vendor/woohoolabs/yin/src/JsonApi/Request/AbstractRequest.php:212)"} []
request.CRITICAL: Uncaught PHP Exception Symfony\Component\ErrorHandler\Error\FatalError: "Compile Error: Declaration of WoohooLabs\Yin\JsonApi\Request\AbstractRequest::withCookieParams(array $cookies) must be compatible with Psr\Http\Message\ServerRequestInterface::withCookieParams(array $cookies): Psr\Http\Message\ServerRequestInterface" at /var/www/symfony/vendor/woohoolabs/yin/src/JsonApi/Request/AbstractRequest.php line 212 {"exception":"[object] (Symfony\\Component\\ErrorHandler\\Error\\FatalError(code: 0): Compile Error: Declaration of WoohooLabs\\Yin\\JsonApi\\Request\\AbstractRequest::withCookieParams(array $cookies) must be compatible with Psr\\Http\\Message\\ServerRequestInterface::withCookieParams(array $cookies): Psr\\Http\\Message\\ServerRequestInterface at /var/www/symfony/vendor/woohoolabs/yin/src/JsonApi/Request/AbstractRequest.php:212)"} []
php.CRITICAL: Uncaught Error: Class "WoohooLabs\Yin\JsonApi\Request\JsonApiRequest" not found {"exception":"[object] (Error(code: 0): Class \"WoohooLabs\\Yin\\JsonApi\\Request\\JsonApiRequest\" not found at /var/www/symfony/vendor/paknahad/jsonapi-bundle/src/Factory/JsonApiFactory.php:43)"} []
{ "meta": { "code": 0, "message": "Cannot use object of type App\\Entity\\Test as array", "file": "/app/src/JsonApi/Hydrator/Test/AbstractTestHydrator.php", "line": 68, "trace": [ { "file": "/app/vendor/woohoolabs/yin/src/JsonApi/Hydrator/UpdateHydratorTrait.php", "line": 160, "function": "setId" }, { "file": "/app/vendor/woohoolabs/yin/src/JsonApi/Hydrator/UpdateHydratorTrait.php", "line": 108, "function": "hydrateIdForUpdate" }, { "file": "/app/vendor/woohoolabs/yin/src/JsonApi/Hydrator/AbstractHydrator.php", "line": 34, "function": "hydrateForUpdate" }, { "file": "/app/vendor/woohoolabs/yin/src/JsonApi/JsonApi.php", "line": 94, "function": "hydrate" }, { "file": "/app/src/Controller/TestController.php", "line": 87, "function": "hydrate" }, { "file": "/app/vendor/symfony/http-kernel/HttpKernel.php", "line": 149, "function": "edit" }, { "file": "/app/vendor/symfony/http-kernel/HttpKernel.php", "line": 66, "function": "handleRaw" }, { "file": "/app/vendor/symfony/http-kernel/Kernel.php", "line": 188, "function": "handle" }, { "file": "/app/public/index.php", "line": 37, "function": "handle" } ] }, "links": { "self": "/api/v2/tests/2" }, "errors": [ { "status": "500", "code": "INTERNAL_SERVER_ERROR", "title": "Internal Server Error" } ] }
In the following function:
`protected function setId($test, string $id): ? array
{
if ($id) {
$test['id'] = $id;
return $test;
}
return null;
}`
The current filtering only supports a limited set of possibilities.
I would love the ability to have advanced filtering options available like AND/OR, greater than, etc.
I have done some research and JSON API does not dictate any standards and nothing is close to beeing the default implementation.
Some interesting options for standards I found:
To me searching for a standard outside JSONAPI makes the most sense for implementation although even there there doesn't seem to be a reliable standard.
In my previous PR I made a small mistake with Finder file location and an incorrect Request class usage. Sorry I missed that!
I'm creating a new PR to fix this. I tested that PR with my own bundle for RQL support (which works!) to verify that everything works as expected.
When error is caused by ClassLoader
when you have a typo in a class name, it triggers a fatal error on PHP (when debug is true, this results in an HTML error page instead of a JSON:API error page with meta.
For example:
namespace App\Schemes\Entities;
class PatientScheme extends ResourceObject
{
}
I get this unuseful error:
...instead of:
{
"meta": {
"message": "Attempted to load class \"ResourceObject\" from namespace \"App\\Schemes\\Entities\".\nDid you forget a \"use\" statement for \"App\\Schemes\\JsonApi\\ResourceObject\"?"
// ...
},
// ...
"errors": [
// ...
]
}
I was trying to generate Api for User class, and I was getting this error:
[ERROR] "" is not valid as a PHP class name (it must start with
a letter or underscore, followed by any number of
letters, numbers, or underscores)
As it turns out, my repository class annotation was missing in User class:
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
Wouldn't it be better if the error said "Repository class not found" or something like that?
Hi @paknahad @kocsismate ,
As jsonapi
spec specify it, we should be able to filter with multiple values
https://jsonapi.org/recommendations/#filtering
However, /books?filter[id]=1,2
does not show 2 books
The query generated is
SELECT t0.id AS id_1, t0.name AS name_2 FROM author t0 INNER JOIN book_author ON t0.id = book_author.author_id WHERE book_author.book_id = 1
instead of
SELECT t0.id AS id_1, t0.name AS name_2 FROM author t0 INNER JOIN book_author ON t0.id = book_author.author_id WHERE book_author.book_id in (1,2)
Regards,
The Maker bundle now supports entities outside of the /entity map. As I want to better structure my code I use this feature.
The make:api cannot handle it currently as it crashes with a fatal error.
I might be able to make a patch but I'm not sure yet as I'm not familiar with the Maker bundle yet.
When you omit a field that cannot be blank, you get a 500 error because this snippet from Controller.php
does not allow null:
$errorSource = new ErrorSource(
$pointer,
$fieldError->getInvalidValue()
);
Argument 2 passed to WoohooLabs\\Yin\\JsonApi\\Schema\\ErrorSource::__construct() must be of the type string, null given, called in /app/vendor/paknahad/jsonapi-bundle/src/Controller/Controller.php on line 65
I checked but I think sorting is not supported yet right?
Fortunately there is a spec for sorting:
https://jsonapi.org/format/#fetching-sorting
I'll try and see if I can make a PR for this.
Hi,
we have been using your bundle for a while and it's great, but today I came across a problem of filtering by calculated field. I would like to filter the list of my Offer entities by dynamic field tags
. Tags are detected by some complex logic and not stored to database, but added on the fly. I found a way to do the filtering by extending the Paknahad\JsonApiBundle\Helper\ResourceCollection
, but the bundle does not allow me to add ?filter[tag]=tagName
to request because it is not an actual field in the table. The error message I am getting is:
"message": "No entity found for entity App\Entity\Offer and field tags",
Is there a way to achieve custom filters?
Thanks
We wanted to create a /batch
route by using the HttpKernel:
foreach($requests as $request) {
// ...
$req = Request::create(
$request['relative_url'],
$request['method'],
$options
);
$response = $kernel->handle($req);
}
However, since the ResourceCollection service (and probably others like JsonApi) sets the request on construction, it doesn't work with follow up requests:
/**
* ResourceCollection constructor.
*/
public function __construct(RequestStack $requestStack, FinderCollection $finderCollection, Paginator $paginator, FieldManager $fieldManager)
{
$this->request = $requestStack->getCurrentRequest();
// ...
}
It will handle the same request over and over again.
Hi @paknahad,
I can see that ValidatorTrait
validate fields using doctrine
fields name, is not accurate to use getAttributeHydrator
return fields
I mean, when I create object (POST
on /book
in my https://github.com/waghanza/book-manager), fields (in data
on my json) are validated according to what doctrine know, not what hydratator know
Regards,
Hello.
I get TypeError: Argument 2 passed to WoohooLabs\Yin\JsonApi\Schema\Error\ErrorSource::__construct() must be of the type string, object given, called in /app/vendor/paknahad/jsonapi-bundle/src/Controller/Controller.php on line 47
when I trying to use Symfony DateTime validation, because of $fieldError->getInvalidValue()
returns DateTime object instead of string.
Hi,
I am create a symfony
app that could run either on php 7.1
or php 7.2
My composer.json
add following constraints :
{
"require": {
"php": "~7.1 | ~7.2",
....
}
}
However, when trying composer require paknahad/jsonapi-bundle
, I have
[InvalidArgumentException]
Package paknahad/jsonapi-bundle at version has a PHP requirement incompatible with your PHP version (7.1.17)
My composer.json
is not specifying that this app could run on 7.2
?
Regards,
After generating an API with command: php bin/console make:api
I always get an error:
Argument 1 passed to Paknahad\JsonApiBundle\Maker\ApiCrud::generateDocumentation() must be an instance of Doctrine\Common\Persistence\Mapping\ClassMetadata, instance of Doctrine\ORM\Mapping\ClassMetadata given, called in /var/w
ww/symfony/vendor/paknahad/jsonapi-bundle/src/Maker/ApiCrud.php on line 272
Symfony Version: 5.2
I created this PR to add support for PHP 8, but you didn't create a new release for it.
Can you please create a new release for it?
For security reasons, we have to limit the client in filtering some fields & tables.
I would prefer to check client access to tables and fields in voters.
@mnugter what do you think? let me know, please.
Hi!
I have a problem with the installation.
I use symfony/orm-pack v2.1.0
(Symfony 4.4.19), but the package has dependency described as "symfony/orm-pack": "^1.0
Do you plan to raise the version of symfony/orm-pack
?
Thank you.
Is there a way to configure the package to opt out of sending the jsonapi spec version on each response?
"jsonapi": { "version":"1.0" }
Thanks
First of all, thank you for making this much-needed Symfony bundle.
So I am trying to execute this command php bin/console make:api
seems like it doesn't recognize MongoDB ODM Documents.
So my question is does it only work with ORM currently?
Hi,
make:api gives below error on running
Fatal error: Interface 'phootwork\lang\Arrayable' not found in /vendor/paknahad/jsonapi-bundle/src/Collection/Swagger/Swagger.php on line 10
"phootwork/collection" should be part of "require" section instead of "require-dev". It's needed for generating Swagger doc.
It's deprecated
Hi @paknahad,
I'm trying to use jsonapi-bundle
, but I have an error message
The controller must return a response (Object(Zend\\Diactoros\\Response) given).
when using this code
(generated) :
public function index(Request $request, ProductRepository $productRepository): ResponseInterface
{
$query = $this->generateQuery($productRepository, $request);
$paginator = new Paginator($query, $request);
return $this->jsonApi()->respond()->ok(
new ProductsDocument(new ProductResourceTransformer()),
new ResourceCollection(
$paginator->getPagination(),
$paginator->getCount(),
$paginator->getPage(),
$paginator->getSize()
)
);
}
Regards,
Hi @paknahad
Any take on supporting Symfony 5? jsonapi-bundle require proxy-manager-bridge ^4.1
but Symfony 5 uses "symfony/proxy-manager-bridge": "5.0.*"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.