Created
April 14, 2020 17:27
-
-
Save dsazup/996cd6ca7f1ff50cc31c0823fe26b2a7 to your computer and use it in GitHub Desktop.
Laravel response()->to()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use Illuminate\Routing\ResponseFactory; | |
use Illuminate\Support\ServiceProvider; | |
use Illuminate\Contracts\Support\Responsable; | |
use Illuminate\Contracts\View\Factory as ViewFactoryContract; | |
use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract; | |
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | |
class AppServiceProvider extends ServiceProvider | |
{ | |
/** | |
* Register any application services. | |
* | |
* @return void | |
*/ | |
public function register() | |
{ | |
// | |
} | |
/** | |
* Bootstrap any application services. | |
* | |
* @return void | |
*/ | |
public function boot() | |
{ | |
$this->app->singleton(ResponseFactoryContract::class, function ($app) { | |
return new class($app[ViewFactoryContract::class], $app['redirect']) extends ResponseFactory implements Responsable { | |
protected $callbacks = []; | |
public function to($type, $callback) { | |
$this->callbacks[$type] = $callback; | |
return $this; | |
} | |
public function toResponse($request) | |
{ | |
throw_unless($callback = $this->callbacks[$request->format()] ?? null, NotFoundHttpException::class); | |
return app()->call($callback); | |
} | |
}; | |
}); | |
} | |
} |
Here's an adapted version using macros instead of extending the response factory, I had issues with return types when extending
<?php
namespace App\Providers;
use Closure;
use Illuminate\Routing\ResponseFactory;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
ResponseFactory::macro('to', function (): mixed {
ResponseFactory::macro('do', function (Closure $callback): mixed {
throw_unless($callback, NotFoundHttpException::class);
return app()->call($callback, ['format' => request()->hasHeader('Turbo-Frame') ? 'turbo_frame' : request()->format()]);
});
if (count(func_get_args()) > 0) {
return $this->do(...func_get_args());
}
return $this;
});
}
}
I also added support to work with hotwired Turbo frames
In the controller I would have something like this
//controller
/**
* Show the form for editing the specified resource.
*/
public function edit(Course $course): Renderable
{
return respond_to()->do(fn ($format) => match ($format) {
'turbo_frame' => view('admin.courses._form', [
'course' => $course,
]),
'html' => view('admin.courses.edit', [
'course' => $course,
]),
});
}
Then I have the helper respond_to
use Illuminate\Routing\ResponseFactory;
if (! function_exists('respond_to')) {
function respond_to(): ResponseFactory
{
return response()->to();
}
}
But you can just as easily call response()->to($callback)
I just found adding an extra to()->do($callback)
more "railsy" and descriptive
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice. that's some rails-like magic 🪄 helped me out. thanks.