PHP code example of mitsuki / router

1. Go to this page and download the library: Download mitsuki/router library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

mitsuki / router example snippets


use Mitsuki\Attributes\Controller;
use Mitsuki\Attributes\Route;
use Mitsuki\Controller\BaseController;
use Mitsuki\Http\Responses\JsonResponse;
use Mitsuki\Http\Request;

#[Controller('posts')]
class PostController extends BaseController
{
    #[Route('posts.index', '', ['GET'])]
    public function index(): JsonResponse
    {
        return $this->json(['data' => ['post 1', 'post 2', 'post 3']]);
    }

    #[Route('posts.store', '', ['POST'])]
    public function store(Request $request): JsonResponse
    {
        return $this->json([
            'title' => $request->request->get('title'),
        ]);
    }

    #[Route('posts.show', '{id}', ['GET'])]
    public function show(int $id): JsonResponse
    {
        return $this->json(['data' => 'post 1']);
    }

    #[Route('posts.update', '{id}', ['PUT'])]
    public function update(Request $request, int $id): JsonResponse
    {
        return $this->json(['id' => $id]);
    }

    #[Route('posts.destroy', '{id}', ['DELETE'])]
    public function destroy(int $id): JsonResponse
    {
        return $this->json([], status: 204);
    }
}

public function __construct(
    private RouteCollection    $routeCollection,
    private RequestContext     $requestContext,
    private ContainerInterface $container,
    private ControllerResolver $controllerResolver,
    string                     $cacheDir
)

use Mitsuki\Hermite\Router;
use Mitsuki\Controller\Resolvers\ControllerResolver;
use Psr\Container\ContainerInterface;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventDispatcher;

return [
    'project.root' => dirname(__DIR__) . '/src',
    'cache.dir'    => dirname(__DIR__) . '/var/caches',

    ControllerResolver::class => fn($c) => 
        new ControllerResolver($c->get('project.root')),

    Router::class => function (ContainerInterface $c) {
        $router = new Router(
            $c->get(RouteCollection::class),
            $c->get(RequestContext::class),
            $c,
            $c->get(ControllerResolver::class),
            $c->get('cache.dir')
        );

        $controllers = $c->has('controllers') ? $c->get('controllers') : [];
        $router->load($controllers);

        return $router;
    },

    ControllerResolverInterface::class => fn($c) => new class($c->get(Router::class)) implements ControllerResolverInterface {
        public function __construct(private Router $router) {}
        public function getController(Request $request): callable|false
        {
            return $this->router->getCallable($request);
        }
    },

    HttpKernelInterface::class => function (ContainerInterface $c) {
        $argumentResolver = new ArgumentResolver(
            null,
            [
                new RequestAttributeValueResolver(),
                new RequestValueResolver(),
                new DefaultValueResolver(),
            ]
        );

        return new HttpKernel(
            new EventDispatcher(),
            $c->get(ControllerResolverInterface::class),
            new RequestStack(),
            $argumentResolver
        );
    },

    RequestContext::class => \DI\create(RequestContext::class),
    RouteCollection::class => \DI\create(RouteCollection::class),
];

use Mitsuki\Http\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

$kernel = $container->get(HttpKernelInterface::class);

$request  = Request::create('/posts', 'GET');
$response = $kernel->handle($request);

echo $response->getStatusCode();  // 200
echo $response->getContent();     // JSON data

test('GET /posts returns index with paginated data - E2E', function () {
    $request  = Request::create('/posts', 'GET');
    $response = $this->app->get(HttpKernelInterface::class)->handle($request);
    
    $data = json_decode($response->getContent(), true);
    
    expect($response->getStatusCode())->toBe(200)
        ->and($data['data'])->toHaveCount(3);
});

test('returns 404 Not Found for unknown routes', function () {
    $request = Request::create('/unknown', 'GET');
    
    expect(fn() => $this->app->get(HttpKernelInterface::class)->handle($request))
        ->toThrow(NotFoundHttpException::class);
});