api-ecosystem-for-laravel/dingo-api

Laravel 11 Support

nasrulhazim opened this issue · 16 comments

Hi,

Will there any new release on supporting Laravel 11?

Thank you.

Any update regarding Laravel 11 support.

Any update regarding Laravel 11 support.

i have submitted my PR on the upgrade - #43

Yes, absolutely it will be supported soon.
https://github.com/api-ecosystem-for-laravel/dingo-api/releases/tag/v4.2.0-beta1

Please try it, and let me know how well it works for you.

Yes, absolutely it will be supported soon. https://github.com/api-ecosystem-for-laravel/dingo-api/releases/tag/v4.2.0-beta1

Please try it, and let me know how well it works for you.

I noticed that, this package have another dependency from https://github.com/dingo/blueprint .

Still figuring out, how to upgrade the package as there's some deprecation issue need to be solve. Don't have any idea how to do that at the moment.

@specialtactics , I've made PR for dingo/blueprint to support Laravel 11. See this PR for more details. Just need it to be merge into master and tag.

Then we are good to go to latest stable version.

It seems that the author no longer maintains it

Seems like there is a bug, because of type hints in newer symhfony versions. In Dingo\Api\Http\Response for line 127 $this->content = $this->getOriginalContent() ?? '';.
Type hint for content property has been added and it should always be a string.
Because of this, if any response contains something that isn't a string, for example an StdClass, there is always an error.
Couldn't find a straight forward fix for this(Probably need to transform and then assign it once its already been converted to a string), but maybe i'm just returning responses wrong.

Two separate things, I've tagged new version of blueprint based on PR mentioned above by @nasrulhazim

The other issue mentioned by @MartinsRucevskis I will have a look at now.

Ok, I pushed a fix which think it should fix it, although I'm not sure what would happen if you have a nested set of stdClasses.

@MartinsRucevskis can you please try v4.2.0 (non-beta). Hopefully this is the last of any issues, but please post more feedback if you have issues upgrading to Laravel 11.

@specialtactics Thank You, but won't really be able to test the fix for now. Will try maybe next week.
But anyways, looking at the PR, this wont fix the actual issue, since the error occurs earlier in the flow.
As of my memory, the actual problem was somewhere else. The content should have been a string already when getting to morph method(maybe? Dont remember corectlly), but stdClass isnt being treated as json.
And the transformer didnt return a string. If im not mistaken interface didn't allow for it to return a string. and hence $this->content = static::$transformer->transform() failed.
But a temporary fix like this i think should work.

  public function morph($format = 'json')
    {
        $content = $this->getOriginalContent() ?? '';
        $this->fireMorphingEvent();
        if (isset(static::$transformer) && static::$transformer->transformableResponse($content)) {
            $content = static::$transformer->transform($content);
        }
        $formatter = static::getFormatter($format);
        $formatter->setOptions(static::getFormatsOptions($format));
        $defaultContentType = $this->headers->get('Content-Type');
        // If we have no content, we don't want to set this header, as it will be blank
        $contentType = $formatter->getContentType();
        if (! empty($contentType)) {
            $this->headers->set('Content-Type', $formatter->getContentType());
        }
        $this->fireMorphedEvent();
        if ($content instanceof EloquentModel) {
            $this->content = $formatter->formatEloquentModel($content);
            ....

Hey @MartinsRucevskis no problem, when you can. I would appreciate if you could post the exception with stack trace, and even better if you could provide a reproducible example.

[2024-06-07 04:55:33] local.ERROR: Cannot assign array to property Symfony\Component\HttpFoundation\Response::$content of type string {"exception":"[object] (TypeError(code: 0): Cannot assign array to property Symfony\Component\HttpFoundation\Response::$content of type string at /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Http/Response.php:127)
[stacktrace]
#0 /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Routing/Router.php(537): Dingo\Api\Http\Response->morph('json')
#1 /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Routing/Router.php(508): Dingo\Api\Routing\Router->prepareResponse(Object(Dingo\Api\Http\Response), Object(Dingo\Api\Http\Request), 'json')
#2 /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Http/Middleware/Request.php(123): Dingo\Api\Routing\Router->dispatch(Object(Dingo\Api\Http\Request))
#3 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(144): Dingo\Api\Http\Middleware\Request->Dingo\Api\Http\Middleware\{closure}(Object(Dingo\Api\Http\Request))
#4 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#5 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#6 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#7 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#8 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#9 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\TrimStrings->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#10 /app/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#11 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Http\Middleware\ValidatePostSize->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#12 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(110): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#13 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#14 /app/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(62): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#15 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Http\Middleware\HandleCors->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#16 /app/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(57): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#17 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Illuminate\Http\Middleware\TrustProxies->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#18 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Dingo\Api\Http\Request))
#19 /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Http/Middleware/Request.php(122): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#20 /app/vendor/api-ecosystem-for-laravel/dingo-api/src/Http/Middleware/Request.php(101): Dingo\Api\Http\Middleware\Request->sendRequestThroughRouter(Object(Dingo\Api\Http\Request))
#21 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(183): Dingo\Api\Http\Middleware\Request->handle(Object(Dingo\Api\Http\Request), Object(Closure))
#22 /app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(119): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#23 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#24 /app/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#25 /app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1168): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#26 /app/public/index.php(17): Illuminate\Foundation\Application->handleRequest(Object(Illuminate\Http\Request))
#27 /app/vendor/laravel/framework/src/Illuminate/Foundation/resources/server.php(16): require_once('/app/public/ind...')
#28 {main}
"}

Seems like there's a simple solution.
In Dingo\Api\Http\Response replace all $this->content with $content. Add $this->content = $content; at the end.

    public function morph($format = 'json')
    {
        $content = $this->getOriginalContent() ?? '';

        $this->fireMorphingEvent();

        if (isset(static::$transformer) && static::$transformer->transformableResponse($content)) {
            $content = static::$transformer->transform($content);
        }

        $formatter = static::getFormatter($format);

        $formatter->setOptions(static::getFormatsOptions($format));

        $defaultContentType = $this->headers->get('Content-Type');

        // If we have no content, we don't want to set this header, as it will be blank
        $contentType = $formatter->getContentType();
        if (! empty($contentType)) {
            $this->headers->set('Content-Type', $formatter->getContentType());
        }

        $this->fireMorphedEvent();

        if ($content instanceof EloquentModel) {
            $content = $formatter->formatEloquentModel($content);
        } elseif ($content instanceof EloquentCollection) {
            $content = $formatter->formatEloquentCollection($content);
        } elseif (is_array($content) || $content instanceof ArrayObject || $content instanceof Arrayable) {
            $content = $formatter->formatArray($content);
        } elseif ($content instanceof stdClass) {
            $content = $formatter->formatArray((array) $content);
        } else {
            if (! empty($defaultContentType)) {
                $this->headers->set('Content-Type', $defaultContentType);
            }
        }

        $this->content = $content;

        return $this;
    }

Has been tagged as v4.2.1, any feedback appreciated.

Seems like there are no outstanding reports of bugs. I've also updated the tests and added github ci through actions for both laravel 10 and 11 (intending to support both for a while yet), and fixed some other minor bugs.

I will close this thread, if there are any more issues, please start a new issue for that specific problem.