Запрос Laravel :: all () не следует вызывать статически

95

В Laravel, я пытаюсь позвонить $input = Request::all();по store()методе в моем контроллере, но я получаю следующее сообщение об ошибке:

Нестатический метод Illuminate\Http\Request::all()не следует вызывать статически, исходя $thisиз несовместимого контекста.

Любая помощь в определении лучшего способа исправить это? (Я слежу за Ларакастом)

лось
источник
@patricus, извините, я должен был сказать 5.
Moose
Похоже, вы не используете фасад. У вас есть use Illuminate\Http\Request;заявление в вашем контроллере?
Патрикус
@patricus, у меня есть `use Illuminate \ Http \ Request; заявление в верхней части моего контроллера.
Moose
1
@patricus У меня нет Illuminate\Http\Requestпакета в / vendor. Нужно ли мне скачивать это отдельно?
Moose
В Illuminateпакеты включены как часть Laravel / рамочный пакет. Если вы хотите посмотреть любой исходный код Laravel, вы найдете его под/vendor/laravel/framework/src/Illuminate/...
patricus

Ответы:

232

Сообщение об ошибке связано с тем, что вызов не проходит через Requestфасад.

+ Изменить

use Illuminate\Http\Request;

Чтобы

use Request;

и он должен начать работать.

В файле config / app.php вы можете найти список псевдонимов классов. Там вы увидите, что базовый класс Requestимеет псевдоним Illuminate\Support\Facades\Requestкласса. Из - за этого, использовать Requestфасад в файл пространства имен, необходимо указать использовать базовый класс: use Request;.

редактировать

Поскольку этот вопрос, похоже, привлекает некоторый трафик, я хотел немного обновить ответ, так как Laravel 5 был официально выпущен.

Хотя вышеизложенное все еще технически верно и будет работать, этот use Illuminate\Http\Request;оператор включен в новый шаблон контроллера, чтобы помочь разработчикам перейти к использованию внедрения зависимостей вместо использования фасада.

При внедрении объекта Request в конструктор (или методы, доступные в Laravel 5) Illuminate\Http\Requestследует вводить именно объект, а не Requestфасад.

Таким образом, вместо изменения шаблона контроллера для работы с фасадом запроса лучше рекомендуется работать с данным шаблоном контроллера и перейти к использованию внедрения зависимостей (через конструктор или методы).

Пример через метод

<?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');
    }
}

Пример через конструктор

<?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');
    }
}
Патрик
источник
3
Ответ правильный, однако я бы предпочел использовать Illuminate \ Support \ Facades \ Request; потому что лично я думаю, что привычка Laravel использовать псевдонимы всего в корневом пространстве имен противоречит идее наличия пространств имен в первую очередь. Это также затрудняет создание документации по API, поскольку apigen / phpdoc не сможет найти класс «Request».
delatbabel
4
Фактически, вам не нужно менять Boilerplate контроллера artisan make :. Если вы хотите использовать запрос, не вводя его в метод, просто используйте $ input = \ Request :: all () (обратите внимание на \). Если вы хотите использовать инъекцию, чем используйте общедоступную myFunction (Request $ request () {$ input = $ request-> all ()} Или вставьте ее в конструктор и назначьте переменной класса
shock_gone_wild
2
Почему я не могу использовать, Request::all();пока использую use Illuminate\Http\Request; ?
SA__
@SA__ Request :: all () - это фасадный способ. так что вы должны use Illuminate\Support\Facades\Request; вместоuse Illuminate\Http\Request;
Табунг
@redA есть ли способ преобразовать Request :: all () для использования прямым способом (а не через класс фасада)?
cid
7

используйте request()вместо этого помощника. Вам не нужно беспокоиться о useзаявлениях, и, следовательно, такого рода проблемы больше не повторится.

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

просто

ясный
источник
6

Внедрите объект запроса в контроллер с помощью волшебной инъекции Laravel, а затем получите доступ к функции нестатически. Laravel автоматически вводит конкретные зависимости в автоматически загружаемые классы.

class MyController() 
{

   protected $request;

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

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

}
Джонатан Кроу
источник
4

Фасад - это еще один класс Request, для доступа к нему используйте полный путь:

$input = \Request::all();

Из laravel 5 вы также можете получить к нему доступ через request()функцию:

$input = request()->all();
Лука К.
источник
3

Я подумал, что для будущих посетителей будет полезно дать небольшое объяснение того, что здесь происходит.

Illuminate\Http\Requestкласс

У Illuminate\Http\Requestкласса Laravel есть метод с именем all(на самом деле allметод определяется в трейте, который Requestиспользует класс, называемом Illuminate\Http\Concerns\InteractsWithInput). Сигнатура allметода на момент написания выглядит так:

public function all($keys = null)

Этот метод не определен как staticи поэтому, когда вы пытаетесь вызвать метод в статическом контексте, т.е. Illuminate\Http\Request::all()вы получите сообщение об ошибке, отображаемое в вопросе OP. allМетод является методом экземпляра и имеет дело с информацией, которая присутствует в экземпляре Requestкласса, поэтому называть его таким образом , не имеет смысла.

Фасады

Фасад в Laravel предоставляет разработчикам удобный способ доступа к объектам в контейнере IoC и вызова методов для этих объектов. Разработчик может вызвать метод «статически» на фасаде, например Request::all(), на фасаде , но фактический вызов метода на реальном Illuminate\Http\Request объекте не является статическим.

Фасад работает как прокси - он обращается к объекту в контейнере IoC и передает вызов статического метода этому объекту (нестатически). Например, возьмем Illuminate\Support\Facades\Requestфасад, вот как он выглядит:

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

Под капотом базовый Illuminate\Support\Facades\Facadeкласс использует некоторую магию PHP, а именно __callStaticметод:

  • Слушайте вызов статического метода, в данном случае allбез параметров
  • Возьмите базовый объект из контейнера IoC, используя ключ, возвращаемый getFacadeAccessor, в данном случае Illuminate\Http\Requestобъект
  • Динамически вызывать метод, который он получил статически для полученного объекта, в этом случае allвызывается нестатически для экземпляра Illuminate\Http\Request.

Вот почему, как указал @patricus в своем ответе выше, изменив useоператор / import для ссылки на фасад, ошибки больше нет, потому что, что касается PHP, allбыл правильно вызван для экземпляра Illuminate\Http\Request.

Сглаживание

Псевдонимы - еще одна функция, которую Laravel предоставляет для удобства. Он работает, эффективно создавая классы псевдонимов, которые указывают на фасады в корневом пространстве имен. Если вы посмотрите на свой config/app.phpфайл, под aliasesключом вы найдете длинный список сопоставлений строк с классами фасадов. Например:

'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 создает для вас эти псевдонимы классов на основе вашей конфигурации, и это позволяет вам использовать классы, доступные в корневом пространстве имен (на что указывают строковые ключи aliasesконфигурации), как если бы вы использовали сам фасад:

use Request:

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

        // ...
    }
}

Замечание о внедрении зависимостей

Хотя фасады и псевдонимы по-прежнему предусмотрены в Laravel, можно и обычно рекомендуется идти по пути внедрения зависимостей. Например, использование внедрения конструктора для достижения того же результата:

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();

        // ...
    }
}

У этого подхода есть ряд преимуществ, но, по моему личному мнению, самым большим преимуществом внедрения зависимостей является то, что он упрощает тестирование кода. Объявляя зависимости ваших классов в качестве аргументов конструктора или метода, становится очень легко имитировать эти зависимости и изолированно тестировать свой класс.

Джонатон
источник
1
use Illuminate\Http\Request;
public function store(Request $request){
   dd($request->all());
}

то же самое в контексте, говоря

use Request;
public function store(){
   dd(Request::all());
}
Рави Джи
источник
1

также это происходит, когда вы импортируете следующую библиотеку в файл api.php. это происходит из-за предложения некоторой среды IDE импортировать его из-за того, что класс маршрута не обнаружен .

просто удалите его, и все будет работать нормально.

use Illuminate\Routing\Route;

Обновить:

кажется, если вы добавите эту библиотеку, это не приведет к ошибке

use Illuminate\Support\Facades\Route;
газы
источник
это сработало для меня, но я до сих пор не понимаю, почему причина IDE не применима ко мне, потому что я создал проект и использую vscode.
Альдо Окваре
0

Я столкнулся с этой проблемой даже с use Illuminate\Http\Request;линией в верхней части моего контроллера. Продолжал тянуть за волосы, пока не понял, что делаю $request::ip()вместо $request->ip(). Может случиться с вами, если вы не спали всю ночь и смотрите на код в 6 утра приоткрытыми глазами.

Надеюсь, это поможет кому-то в будущем.

dotNET
источник
0

Я заставляю его работать с определением области действия

общедоступная функция pagar (\ Illuminate \ Http \ Request $ request) {//

Джулиан Ланфранко
источник
2
Пожалуйста, не только покажите, какой код работает, но и объясните, почему вы это сделали.
creyD 08