Maison  >  Article  >  développement back-end  >  Interprétation de base Laravel de la requête

Interprétation de base Laravel de la requête

不言
不言original
2018-07-06 14:54:374101parcourir

Cet article présente principalement l'interprétation de base de Request dans Laravel, qui a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

Request

De nombreux frameworks. Les requêtes du client sont résumées en classes pour une utilisation facile par les applications, et Laravel ne fait pas exception. La classe IlluminateHttpRequest est une abstraction des requêtes clients dans le framework Laravel. Elle est construite sur le composant Request fourni par le framework Symfony. L'article d'aujourd'hui examinera brièvement comment Laravel crée un objet Request. Je ne dirai pas grand-chose sur les fonctionnalités que l'objet Request offre aux applications. Après avoir fini d'expliquer le processus de création, vous saurez où aller à la source. Recherchez les méthodes fournies par l'objet Request. Certaines aide-mémoire en ligne répertorient certaines méthodes fournies par Request, mais elles ne sont pas complètes et certaines d'entre elles ne sont pas expliquées. Par conséquent, je le recommande toujours si vous êtes curieux de savoir si Request l'a fait. obtenu les fonctionnalités souhaitées pendant le développement. Accédez au code source de Request pour voir s'il existe une méthode correspondante. Les résultats d'exécution de chaque méthode sont clairement indiqués dans les commentaires de la méthode. Venons-en au fait.

Création de l'objet Request

On peut voir dans le fichier index.php de l'application Laravel que l'objet Request a été créé avant le lancement officiel de l'application Laravel :

//public/index.php
$app = require_once __DIR__.'/../bootstrap/app.php';

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    //创建request对象
    $request = Illuminate\Http\Request::capture()
);

La requête HTTP du client est un objet de la classe IlluminateHttpRequest

class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
    //新建Request实例
    public static function capture()
    {
        static::enableHttpMethodParameterOverride();

        return static::createFromBase(SymfonyRequest::createFromGlobals());
    }
}

Vous pouvez voir dans le code source de la classe IlluminateHttpRequest qu'elle hérite de la classe Symfony Request, donc IlluminateHttpRequest De nombreuses fonctions implémentées dans la classe sont basées sur les fonctions fournies par Symfony Reques. À partir du code ci-dessus, vous pouvez voir que la méthode capture s'appuie également sur des instances de la classe Symfony Request lors de la création d'un nouvel objet Request.

namespace Symfony\Component\HttpFoundation;
class Request
{
    /**
     * 根据PHP提供的超级全局数组来创建Smyfony Request实例
     *
     * @return static
     */
    public static function createFromGlobals()
    {
        // With the php's bug #66606, the php's built-in web server
        // stores the Content-Type and Content-Length header values in
        // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields.
        $server = $_SERVER;
        if ('cli-server' === PHP_SAPI) {
            if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) {
                $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH'];
            }
            if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) {
                $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE'];
            }
        }

        $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server);

        if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded')
            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))
        ) {
            parse_str($request->getContent(), $data);
            $request->request = new ParameterBag($data);
        }

        return $request;
    }
    
}

Il y a un point dans le code ci-dessus qui nécessite des explications supplémentaires. À partir de PHP5.4, le serveur Web intégré de PHP peut être démarré via l'interpréteur de ligne de commande, par exemple :

php -S localhost:8000 -t htdocs

-S 9581b3ba3b9ee3c707d01b5722440004:298c9bd6ad6e8c821dc63aa0473d6209 Run with built-in web server.
-t ea23c61ebf6b70b26359136364366495     Specify document root ea23c61ebf6b70b26359136364366495 for built-in web server.

Mais il y a un bug dans le serveur Web intégré qui stocke les deux en-têtes de requête CONTENT_LENGTH et CONTENT_TYPE dans HTTP_CONTENT_LENGTH et HTTP_CONTENT_TYPE, afin d'unifier les champs d'en-tête de requête dans le serveur intégré et le serveur réel, un traitement spécial est effectué ici.

Les instances Symfony Request sont créées via des tableaux super globaux en PHP. Ces tableaux super globaux incluent $_GET, $_POST, $_COOKIE, $_FILES et $_SERVER couvrant PHP Tous les tableaux super globaux liés. aux requêtes HTTP. Lors de la création d'une instance Symfony Request, les instances ParamterBag ServerBag FileBag HeaderBag fournies dans le package Symfony seront créées sur la base de ces tableaux globaux. Ces sacs sont fournis par Symfony à des fins différentes. accès et paramétrage de l'API du composant HTTP. Les lecteurs intéressés par les ParamterBag exemples fournis par Symfony peuvent vérifier eux-mêmes le code source. Je n'entrerai pas dans les détails ici.

class Request
{

    /**
     * @param array                $query      The GET parameters
     * @param array                $request    The POST parameters
     * @param array                $attributes The request attributes (parameters parsed from the PATH_INFO, ...)
     * @param array                $cookies    The COOKIE parameters
     * @param array                $files      The FILES parameters
     * @param array                $server     The SERVER parameters
     * @param string|resource|null $content    The raw body data
     */
    public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
    }
    
    public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
    {
        $this->request = new ParameterBag($request);
        $this->query = new ParameterBag($query);
        $this->attributes = new ParameterBag($attributes);
        $this->cookies = new ParameterBag($cookies);
        $this->files = new FileBag($files);
        $this->server = new ServerBag($server);
        $this->headers = new HeaderBag($this->server->getHeaders());

        $this->content = $content;
        $this->languages = null;
        $this->charsets = null;
        $this->encodings = null;
        $this->acceptableContentTypes = null;
        $this->pathInfo = null;
        $this->requestUri = null;
        $this->baseUrl = null;
        $this->basePath = null;
        $this->method = null;
        $this->format = null;
    }
    
}

Vous pouvez voir que la classe Symfony Request possède de nombreux attributs en plus de ceux mentionnés ci-dessus. Ces attributs forment ensemble une abstraction complète des requêtes HTTP, auxquelles nous pouvons facilement accéder via les attributs d'instance , Method et d'autres attributs de ces requêtes HTTP. Charset

Après avoir obtenu l'instance Symfony Request, Laravel clonera l'instance et réinitialisera certaines de ses propriétés :

namespace Illuminate\Http;
class Request extends ....
{
    //在Symfony request instance的基础上创建Request实例
    public static function createFromBase(SymfonyRequest $request)
    {
        if ($request instanceof static) {
            return $request;
        }

        $content = $request->content;

        $request = (new static)->duplicate(
            $request->query->all(), $request->request->all(), $request->attributes->all(),
            $request->cookies->all(), $request->files->all(), $request->server->all()
        );

        $request->content = $content;

        $request->request = $request->getInputSource();

        return $request;
    }
    
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
    {
        return parent::duplicate($query, $request, $attributes, $cookies, $this->filterFiles($files), $server);
    }
}
    //Symfony Request中的 duplicate方法
    public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
    {
        $dup = clone $this;
        if (null !== $query) {
            $dup->query = new ParameterBag($query);
        }
        if (null !== $request) {
            $dup->request = new ParameterBag($request);
        }
        if (null !== $attributes) {
            $dup->attributes = new ParameterBag($attributes);
        }
        if (null !== $cookies) {
            $dup->cookies = new ParameterBag($cookies);
        }
        if (null !== $files) {
            $dup->files = new FileBag($files);
        }
        if (null !== $server) {
            $dup->server = new ServerBag($server);
            $dup->headers = new HeaderBag($dup->server->getHeaders());
        }
        $dup->languages = null;
        $dup->charsets = null;
        $dup->encodings = null;
        $dup->acceptableContentTypes = null;
        $dup->pathInfo = null;
        $dup->requestUri = null;
        $dup->baseUrl = null;
        $dup->basePath = null;
        $dup->method = null;
        $dup->format = null;

        if (!$dup->get('_format') && $this->get('_format')) {
            $dup->attributes->set('_format', $this->get('_format'));
        }

        if (!$dup->getRequestFormat(null)) {
            $dup->setRequestFormat($this->getRequestFormat(null));
        }

        return $dup;
    }
Une fois l'objet Request créé, nous pouvons facilement l'appliquer dans l'application Laravel Capacités fournies, lors de l'utilisation de l'objet Request, si vous ne savez pas s'il réalise la fonction souhaitée, il est très simple d'aller directement dans le fichier de code source de

pour le vérifier. Toutes les méthodes sont répertoriées dans cette source. fichier de code. , par exemple : IlluminateHttpRequest

/**
 * Get the full URL for the request.
 * 获取请求的URL(包含host, 不包括query string)
 *
 * @return string
 */
public function fullUrl()
{
    $query = $this->getQueryString();

    $question = $this->getBaseUrl().$this->getPathInfo() == '/' ? '/?' : '?';

    return $query ? $this->url().$question.$query : $this->url();
}

/**
 * Get the full URL for the request with the added query string parameters.
 * 获取包括了query string 的完整URL
 *
 * @param  array  $query
 * @return string
 */
public function fullUrlWithQuery(array $query)
{
    $question = $this->getBaseUrl().$this->getPathInfo() == '/' ? '/?' : '?';

    return count($this->query()) > 0
        ? $this->url().$question.http_build_query(array_merge($this->query(), $query))
        : $this->fullUrl().$question.http_build_query($query);
}
La station par laquelle passe la requête

Après avoir créé l'objet Request, le noyau Http de Laravel continuera à s'exécuter : chargez le fournisseur de services pour guider le Application Laravel, démarrez l'application et laissez la requête passer par le middleware de base, recherchez la route correspondant à la requête via la correspondance du routeur, exécutez la route correspondante et la requête atteint la méthode du contrôleur via le middleware via le routage.

Résumé

Lorsque la requête atteint enfin la méthode de contrôleur correspondante, sa mission est essentiellement terminée. Dans la méthode du contrôleur, les paramètres d'entrée sont obtenus à partir de la requête, puis exécutent une certaine partie de la requête. Une fois que la logique métier obtient le résultat, celui-ci sera converti en un objet Réponse et renvoyé au client qui a initié la demande.

Cet article traite principalement de l'objet Request dans Laravel. Il souhaite principalement que tout le monde sache comment découvrir les fonctionnalités que Request dans Laravel nous offre actuellement pour éviter de réinventer la roue dans notre code métier pour implémenter Request. . méthodes déjà fournies.

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'étude de chacun. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !

Recommandations associées :

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn