master

laravel/framework

Last updated at: 29/12/2023 09:23

Response.php

TLDR

The Response.php file in the Illuminate\Http namespace contains a class named Response that extends the Symfony Response class. This class is responsible for creating HTTP responses. It includes methods for setting the content of the response, determining if the content should be converted to JSON, and converting the content to JSON if necessary.

Methods

__construct

This method is the constructor for the Response class. It takes three optional parameters: $content, $status, and $headers. It initializes the ResponseHeaderBag for the $headers, sets the content of the response using the setContent method, and sets the status code and protocol version.

setContent

This method sets the content of the response. It takes one parameter: $content. If the content is "JSONable", it sets the appropriate header and converts the content to JSON. If the content implements the Renderable interface, it calls the render method on the object. Finally, it calls the setContent method of the parent class with the updated content.

shouldBeJson

This method determines if the given content should be converted to JSON. It takes one parameter: $content. It checks if the content is an instance of Arrayable, Jsonable, ArrayObject, JsonSerializable, or if it is an array.

morphToJson

This method converts the given content to JSON. It takes one parameter: $content. If the content is an instance of Jsonable, it calls the toJson method on the object. If the content is an instance of Arrayable, it calls toArray and then uses json_encode to convert the resulting array to JSON. Otherwise, it uses json_encode on the content directly.

Classes

<?php

namespace Illuminate\Http;

use ArrayObject;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Support\Traits\Macroable;
use InvalidArgumentException;
use JsonSerializable;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

class Response extends SymfonyResponse
{
    use ResponseTrait, Macroable {
        Macroable::__call as macroCall;
    }

    /**
     * Create a new HTTP response.
     *
     * @param  mixed  $content
     * @param  int  $status
     * @param  array  $headers
     * @return void
     *
     * @throws \InvalidArgumentException
     */
    public function __construct($content = '', $status = 200, array $headers = [])
    {
        $this->headers = new ResponseHeaderBag($headers);

        $this->setContent($content);
        $this->setStatusCode($status);
        $this->setProtocolVersion('1.0');
    }

    /**
     * Set the content on the response.
     *
     * @param  mixed  $content
     * @return $this
     *
     * @throws \InvalidArgumentException
     */
    #[\Override]
    public function setContent(mixed $content): static
    {
        $this->original = $content;

        // If the content is "JSONable" we will set the appropriate header and convert
        // the content to JSON. This is useful when returning something like models
        // from routes that will be automatically transformed to their JSON form.
        if ($this->shouldBeJson($content)) {
            $this->header('Content-Type', 'application/json');

            $content = $this->morphToJson($content);

            if ($content === false) {
                throw new InvalidArgumentException(json_last_error_msg());
            }
        }

        // If this content implements the "Renderable" interface then we will call the
        // render method on the object so we will avoid any "__toString" exceptions
        // that might be thrown and have their errors obscured by PHP's handling.
        elseif ($content instanceof Renderable) {
            $content = $content->render();
        }

        parent::setContent($content);

        return $this;
    }

    /**
     * Determine if the given content should be turned into JSON.
     *
     * @param  mixed  $content
     * @return bool
     */
    protected function shouldBeJson($content)
    {
        return $content instanceof Arrayable ||
               $content instanceof Jsonable ||
               $content instanceof ArrayObject ||
               $content instanceof JsonSerializable ||
               is_array($content);
    }

    /**
     * Morph the given content into JSON.
     *
     * @param  mixed  $content
     * @return string
     */
    protected function morphToJson($content)
    {
        if ($content instanceof Jsonable) {
            return $content->toJson();
        } elseif ($content instanceof Arrayable) {
            return json_encode($content->toArray());
        }

        return json_encode($content);
    }
}