amranich/ajax-router

高效处理您的AJAX请求

v1.0.7 2023-12-04 15:41 UTC

This package is auto-updated.

Last update: 2024-09-04 17:36:35 UTC


README

packagist tests License

入门

composer require amranich/ajax-router

您可以将此代码片段复制/粘贴以快速开始。

我们在这里使用Guzzle PSR-7接口实现,但只要它实现了相同的接口,您可以使用任何其他您喜欢的库。

<?php

require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use AmraniCh\AjaxRouter\Route;
use AmraniCh\AjaxRouter\Router;
use AmraniCh\AjaxRouter\Dispatcher;
use GuzzleHttp\Psr7\ServerRequest;
use Lazzard\Psr7ResponseSender\Sender;

try {
    $request = ServerRequest::fromGlobals();
    
    // the 'X-requested-with' header is commonly used to inform the server that a request 
    // is sent via the XMLHttpRequest object on the client-side, a lot of JavaScript libraries 
    // like jQuery already send this header automatically, this check can add a small security
    // layer to your app because HTTP headers can be spoofed very easily, so don't count on
    // only that check.
    if (!$request->hasHeader('X-requested-with') 
        || strtolower($request->getHeader('X-requested-with')[0]) !== 'XMLHttpRequest') {
        throw new BadRequestException("Accept only AJAX requests.");
    }
    
    // to organize your project, you can put your routes in a separate file like in an array
    // and require it in the second parameter of the router constructor.  
    $router = new Router($request, 'route', [
    
        // ?route=getPost&id=1005
        Route::get('getPost', function ($params) {
        
            // PSR7 responses are a little annoying to work with, you always have extra HTTP layers 
            // in your app that extend the base PSR7 response class, think of a class like JsonResponse, 
            // and in the constructor add the content-type header and pass it to the parent class.
            $response = new Response;

            $response->getBody()->write(json_encode([
                'id' => $params['id'],
                'title' => 'Best Places to Visit in Marrakech',
                'description' => 'Example of post description',
                'created_at' => '2022-02-27 03:00:05'
            ]));

            return $response->withHeader('Content-type', 'application/json');
        }),
    ]);

    $dispatcher = new Dispatcher($router);
    $dispatcher->dispatch();

} catch (Exception $ex) {
    $response = new Response(
        $ex->getCode() ?: 500,
        ['Content-type' => 'application/json'],
        json_encode(['message' => $ex->getMessage()])
    );

    $sender = new Sender;
    $sender($response);
}

使用技巧

路由到控制器/类方法

如果您想将业务逻辑放在单独的类或控制器中,您可以将请求路由到它们,如下所示

Route::get('getPost', [PostController::class, 'getPost']);

或者

Route::get('getPost', 'PostController@getPost');

// register the controller class or instance in the router
$router->registerControllers([
    PostController::class,
]);

如果控制器/类有一些必须通过构造函数传递的依赖项,您仍然可以在自己身上实例化控制器

$router->registerControllers([
    new PostController($dependencyOne, $dependencyTwo)
]);

捕获路由操作异常

我想捕获仅在我路由操作中发生的异常,而不是由库或其他地方抛出的异常,我该如何做呢?

回答

$dispatcher->onException(function (\Exception $ex) {
    // $ex exception thrown by a route action
});

获取当前路由

您可以使用Route类的静态方法getCurrentRoute访问当前路由对象。

$route = Router::getCurrentRoute();
$route->getName();
$route->getMethods();
$route->getValue();

背景

很久以前,当我主要使用纯PHP开发Web应用程序时,这个库的想法出现在我的脑海中。其中一些应用程序在单个PHP文件中执行大量AJAX请求,该文件可能有数百行代码,这些代码根据请求中发送的函数/方法名称处理这些请求,因此我开始思考我可以如何改进这些请求的处理方式,以及如何提高代码的可读性和可维护性。

奖项

此包赢得了phpclasses.org颁发的PHP创新奖(2022年2月)。

🏆奖项:一个elePHPant吉祥物。https://php.ac.cn/elephpant.php

📜证书:https://amranich.dev/certs/phpclasses-february-2022-innovation-award.pdf

他们支持这个项目