Solicitud de Laravel :: all () no debe llamarse estáticamente

90

En Laravel, estoy tratando de llamar $input = Request::all();a un store()método en mi controlador, pero obtengo el siguiente error:

El método Illuminate\Http\Request::all()no estático no debe llamarse estáticamente, asumiendo que se trata $thisde un contexto incompatible

¿Alguna ayuda para descubrir la mejor manera de corregir esto? (Estoy siguiendo un Laracast)

Alce
fuente
@patricus, lo siento, debería haber dicho 5.
Moose
Parece que no estás usando la fachada. ¿Tiene una use Illuminate\Http\Request;declaración en su controlador?
patricus
@patricus, tengo el ʻuse Illuminate \ Http \ Request; declaración en la parte superior de mi controlador.
Moose
1
@patricus Sin embargo, no tengo el Illuminate\Http\Requestpaquete en / vendor. ¿Tengo que descargarlo por separado?
Moose
Los Illuminatepaquetes se incluyen como parte del paquete laravel / framework. Si desea ver el código fuente de Laravel, lo encontrará en/vendor/laravel/framework/src/Illuminate/...
patricus

Respuestas:

222

El mensaje de error se debe a que la llamada no atraviesa la Requestfachada.

Cambio

use Illuminate\Http\Request;

A

use Request;

y debería empezar a funcionar.

En el archivo config / app.php, puede encontrar una lista de los alias de clases. Allí, verá que la clase base Requesttiene un alias para la Illuminate\Support\Facades\Requestclase. Debido a esto, utilizar la Requestfachada en un archivo de espacio de nombres, es necesario especificar el uso de la clase base: use Request;.

Editar

Dado que esta pregunta parece generar algo de tráfico, quería actualizar un poco la respuesta ya que Laravel 5 se lanzó oficialmente.

Si bien lo anterior sigue siendo técnicamente correcto y funcionará, la use Illuminate\Http\Request;declaración se incluye en la nueva plantilla del controlador para ayudar a impulsar a los desarrolladores en la dirección de usar la inyección de dependencia en lugar de confiar en la fachada.

Al inyectar el objeto Request en el constructor (o métodos, como están disponibles en Laravel 5), es el Illuminate\Http\Requestobjeto el que debe inyectarse, y no la Requestfachada.

Por lo tanto, en lugar de cambiar la plantilla del Controlador para que funcione con la fachada de Solicitud, es mejor trabajar con la plantilla del Controlador dada y avanzar hacia el uso de la inyección de dependencia (a través del constructor o métodos).

Ejemplo mediante método

<?php namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class UserController extends Controller {

    /**
     * Store a newly created resource in storage.
     *
     * @param  Illuminate\Http\Request  $request
     * @return Response
     */
    public function store(Request $request) {
        $name = $request->input('name');
    }
}

Ejemplo vía constructor

<?php namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class UserController extends Controller {

    protected $request;

    public function __construct(Request $request) {
        $this->request = $request;
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     */
    public function store() {
        $name = $this->request->input('name');
    }
}
patricus
fuente
3
La respuesta es correcta, sin embargo, por preferencia, usaría Illuminate \ Support \ Facades \ Request; porque personalmente creo que el hábito de Laravel de poner alias todo en el espacio de nombres raíz va en contra del punto de tener espacios de nombres en primer lugar. También hace que la documentación de la API sea más difícil de generar porque apigen / phpdoc no podrá encontrar la clase "Request".
delatbabel
4
De hecho, no es necesario cambiar el texto estándar de la marca artesanal: controlador. Si desea usar la Solicitud sin inyectarla en el método, simplemente use $ input = \ Request :: all () (Observe el \). Si desea usar la inyección en lugar de usar public myFunction (Request $ request () {$ input = $ request-> all ()} O inyectarlo en el constructor y asignarlo a una variable de clase
shock_gone_wild
2
¿Por qué no puedo usar Request::all();mientras lo uso use Illuminate\Http\Request; ?
SA__
@SA__ Request :: all () es una forma de fachada. así que tienes que use Illuminate\Support\Facades\Request; hacerlo en lugar deuse Illuminate\Http\Request;
Thabung
@redA ¿hay alguna manera de convertir Request :: all () para usar la forma directa (y no a través de la clase de fachada)?
cid
6

Inyecte el objeto de solicitud en el controlador usando la inyección mágica de Laravel y luego acceda a la función de forma no estática. Laravel inyectará automáticamente dependencias concretas en clases cargadas automáticamente

class MyController() 
{

   protected $request;

   public function __construct(\Illuminate\Http\Request $request)
   {
       $this->request = $request;
   }

   public function myFunc()
   {
       $input = $this->request->all();
   }

}
Jonathan Crowe
fuente
5

use el request()ayudante en su lugar. No tiene que preocuparse por las usedeclaraciones y, por lo tanto, este tipo de problema no volverá a ocurrir.

$input = request()->all();

sencillo

lucidlogic
fuente
4

La fachada es otra clase de Solicitud, acceda a ella con la ruta completa:

$input = \Request::all();

Desde laravel 5 también puedes acceder a él a través de la request()función:

$input = request()->all();
Luca C.
fuente
3

Pensé que sería útil para los futuros visitantes dar una pequeña explicación sobre lo que está sucediendo aquí.

La Illuminate\Http\Requestclase

La Illuminate\Http\Requestclase de Laravel tiene un método llamado all(de hecho, el allmétodo está definido en un rasgo que Requestusa la clase, llamado Illuminate\Http\Concerns\InteractsWithInput). La firma del allmétodo en el momento de escribir este artículo se ve así:

public function all($keys = null)

Este método no se define como staticy, por lo tanto, cuando intenta llamar al método en un contexto estático, es decir Illuminate\Http\Request::all(), obtendrá el error que se muestra en la pregunta de OP. El allmétodo es un método de instancia y trata con información que está presente en una instancia de la Requestclase, por lo que llamarlo de esta manera no tiene sentido.

Fachadas

Una fachada en Laravel proporciona a los desarrolladores una forma conveniente de acceder a objetos en el contenedor de IoC y llamar a métodos en esos objetos. Un desarrollador puede llamar a un método "estáticamente" en una fachada como Request::all(), pero la llamada al método real en el objeto real noIlluminate\Http\Request es estática.

Una fachada funciona como un proxy: se refiere a un objeto en el contenedor de IoC y pasa la llamada al método estático a ese objeto (de forma no estática). Por ejemplo, tome la Illuminate\Support\Facades\Requestfachada, así es como se ve:

class Request extends Facade
{
    protected static function getFacadeAccessor()
    {
        return 'request';
    }
}

Bajo el capó, la Illuminate\Support\Facades\Facadeclase base usa algo de magia PHP, es decir, el __callStaticmétodo para:

  • Escuche una llamada a un método estático, en este caso allsin parámetros
  • Agarre el objeto subyacente del contenedor de IoC utilizando la clave devuelta por getFacadeAccessor, en este caso un Illuminate\Http\Requestobjeto
  • Llame dinámicamente al método que recibió estáticamente en el objeto que ha recuperado, en este caso allse llama de forma no estática en una instancia de Illuminate\Http\Request.

Es por eso que, como @patricus señaló en su respuesta anterior, al cambiar la usedeclaración / import para hacer referencia a la fachada, el error ya no está allí, porque en lo que respecta a PHP, allse ha llamado correctamente en una instancia de Illuminate\Http\Request.

Aliasing

La creación de alias es otra característica que Laravel proporciona para mayor comodidad. Funciona creando efectivamente clases de alias que apuntan a fachadas en el espacio de nombres raíz. Si echa un vistazo a su config/app.phparchivo, debajo de la aliasesclave, encontrará una larga lista de asignaciones de cadenas a clases de fachada. Por ejemplo:

'aliases' => [

    'App' => Illuminate\Support\Facades\App::class,
    'Artisan' => Illuminate\Support\Facades\Artisan::class,
    'Auth' => Illuminate\Support\Facades\Auth::class,
    // ...
    'Request' => Illuminate\Support\Facades\Request::class,

Laravel crea estas clases de alias para usted, en función de su configuración y esto le permite utilizar las clases disponibles en el espacio de nombres raíz (como se indica en las claves de cadena de la aliasesconfiguración) como si estuviera usando la propia fachada:

use Request:

class YourController extends Controller
{
    public function yourMethod()
    {
        $input = Request::all();

        // ...
    }
}

Una nota sobre la inyección de dependencia

Si bien las fachadas y el aliasing todavía se proporcionan en Laravel, es posible y generalmente se recomienda seguir la ruta de inyección de dependencia. Por ejemplo, usando la inyección del constructor para lograr el mismo resultado:

use Illuminate\Http\Request;

class YourController extends Controller
{
    protected $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function yourMethod()
    {
        $input = $this->request->all();

        // ...
    }
}

Hay una serie de beneficios en este enfoque, pero en mi opinión personal, la mayor ventaja de la inyección de dependencia es que hace que su código sea más fácil de probar. Al declarar las dependencias de sus clases como argumentos de constructor o método, resulta muy fácil simular esas dependencias y realizar pruebas unitarias en su clase de forma aislada.

Jonathon
fuente
1
use Illuminate\Http\Request;
public function store(Request $request){
   dd($request->all());
}

es lo mismo en el contexto diciendo

use Request;
public function store(){
   dd(Request::all());
}
Ravi G
fuente
1

también sucede cuando importa la siguiente biblioteca al archivo api.php. esto sucede por la sugerencia de algunos IDE de importarlo por no encontrar la clase de ruta .

simplemente quítelo y todo funcionará bien.

use Illuminate\Routing\Route;

actualizar:

parece que si agrega esta biblioteca no dará lugar a un error

use Illuminate\Support\Facades\Route;
ghazyy
fuente
esto funcionó para mí, pero todavía no entiendo por qué el motivo del IDE no se aplicaría a mí, porque la forma en que generé el proyecto y uso vscode.
Aldo Okware
0

Estaba enfrentando este problema incluso con la use Illuminate\Http\Request;línea en la parte superior de mi controlador. Seguí tirando de mi cabello hasta que me di cuenta de que estaba haciendo en $request::ip()lugar de $request->ip(). Puede sucederle si no durmió en toda la noche y está mirando el código a las 6 am con los ojos entreabiertos.

Espero que esto ayude a alguien en el futuro.

punto net
fuente
0

lo hago funcionar con una definición de alcance

función pública pagar (\ Illuminate \ Http \ Request $ request) {//

Julián Lanfranco
fuente
2
No solo muestre qué código está funcionando, sino que también explique por qué hizo esto.
creyD