คำขอ Laravel :: all () ไม่ควรเรียกแบบคงที่


95

ใน Laravel ฉันพยายามเรียก$input = Request::all();ใช้store()เมธอดในคอนโทรลเลอร์ แต่ได้รับข้อผิดพลาดต่อไปนี้:

ไม่Illuminate\Http\Request::all()ควรเรียกวิธีการแบบไม่คงที่โดยสมมติว่า$thisมาจากบริบทที่เข้ากันไม่ได้

มีความช่วยเหลือในการหาวิธีที่ดีที่สุดในการแก้ไขปัญหานี้หรือไม่? (ฉันติดตาม Laracast)


@patricus ขอโทษฉันควรจะพูด 5.
มูส

ดูเหมือนว่าคุณไม่ได้ใช้ซุ้ม คุณมีuse Illuminate\Http\Request;คำสั่งในคอนโทรลเลอร์ของคุณหรือไม่?
patricus

@patricus ฉันมี `` ใช้ Illuminate \ Http \ Request; คำสั่งที่ด้านบนของตัวควบคุมของฉัน
Moose

1
@patricus ฉันไม่มีIlluminate\Http\Requestแพ็คเกจใน / ผู้ขายแม้ว่า ฉันต้องดาวน์โหลดแยกต่างหากหรือไม่?
Moose

Illuminateแพคเกจที่จะถูกรวมเป็นส่วนหนึ่งของแพคเกจ Laravel / กรอบ หากคุณต้องการดูซอร์สโค้ดของ Laravel คุณจะพบได้ใน/vendor/laravel/framework/src/Illuminate/...
patricus

คำตอบ:


231

ข้อความแสดงข้อผิดพลาดเกิดจากการโทรไม่ผ่านRequestซุ้ม

เปลี่ยน

use Illuminate\Http\Request;

ถึง

use Request;

และควรเริ่มทำงาน

ในไฟล์ config / app.php คุณจะพบรายการนามแฝงของคลาส ที่นั่นคุณจะเห็นว่าคลาสพื้นฐานRequestถูกเปลี่ยนชื่อเป็นIlluminate\Support\Facades\Requestคลาส ด้วยเหตุนี้การใช้Requestอาคารในไฟล์ namespaced use Request;คุณจะต้องระบุให้ใช้ชั้นฐาน:

แก้ไข

เนื่องจากคำถามนี้ดูเหมือนจะได้รับการเข้าชมฉันจึงต้องการอัปเดตคำตอบเล็กน้อยเนื่องจาก Laravel 5 ได้รับการเผยแพร่อย่างเป็นทางการ

แม้ว่าข้างต้นจะยังคงถูกต้องในทางเทคนิคและจะใช้งานได้ แต่use Illuminate\Http\Request;คำสั่งดังกล่าวจะรวมอยู่ในเทมเพลต Controller ใหม่เพื่อช่วยผลักดันนักพัฒนาไปในทิศทางของการใช้การฉีดแบบพึ่งพาเมื่อเทียบกับการใช้ Facade

เมื่อฉีดวัตถุ 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 ของช่างฝีมือ make: controller หากคุณต้องการใช้คำขอโดยไม่ต้องฉีดเข้าไปในเมธอดเพียงแค่ใช้ $ input = \ Request :: all () (สังเกต \) หากคุณต้องการใช้การฉีดมากกว่าใช้ myFunction สาธารณะ (ขอ $ request () {$ input = $ request-> all ()} หรือฉีดในตัวสร้างและกำหนดให้กับตัวแปรคลาส
shock_gone_wild

2
ทำไมฉันถึงใช้ไม่ได้Request::all();ในขณะที่ฉันใช้use Illuminate\Http\Request; ?
SA__

@SA__ ขอ :: all () เป็นซุ้มทาง เลยต้องไป use Illuminate\Support\Facades\Request; แทนuse Illuminate\Http\Request;
Thabung

@redA มีวิธีแปลง Request :: all () เพื่อใช้ทางตรง (และไม่ผ่านคลาสซุ้ม) หรือไม่?
cid

6

ฉีดวัตถุร้องขอลงในคอนโทรลเลอร์โดยใช้การฉีดเวทย์ของ Laravel จากนั้นเข้าถึงฟังก์ชันแบบไม่คงที่ Laravel จะฉีดการพึ่งพาคอนกรีตลงในคลาส autoloaded โดยอัตโนมัติ

class MyController() 
{

   protected $request;

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

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

}

6

ใช้ตัวrequest()ช่วยแทน คุณไม่ต้องกังวลเกี่ยวกับuseงบดังนั้นปัญหาแบบนี้จะไม่เกิดขึ้นอีก

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

เรียบง่าย


4

ซุ้มเป็นคลาสคำขออื่นเข้าถึงได้ด้วยเส้นทางแบบเต็ม:

$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วัตถุ
  • แบบไดนามิกเรียกวิธีการที่จะได้รับแบบคงที่บนวัตถุที่ได้ดึงในกรณีนี้จะเรียกว่าไม่ใช่แบบคงที่ในตัวอย่างของallIlluminate\Http\Request

นี่คือเหตุผลที่ @patricus ชี้ให้เห็นในคำตอบของเขาข้างต้นโดยการเปลี่ยนuseคำสั่ง / import เพื่ออ้างถึงส่วนหน้าข้อผิดพลาดจะไม่มีอีกต่อไปเนื่องจากเท่าที่เกี่ยวข้องกับ PHP allได้ถูกเรียกอย่างถูกต้องในอินสแตนซ์ของIlluminate\Http\Request .

นามแฝง

นามแฝงเป็นอีกคุณสมบัติหนึ่งที่ Laravel มอบให้เพื่อความสะดวก ทำงานได้อย่างมีประสิทธิภาพโดยการสร้างคลาสนามแฝงที่ชี้ไปยัง facades ในเนมสเปซรูท หากคุณดู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();

        // ...
    }
}

หมายเหตุเกี่ยวกับการฉีดแบบพึ่งพา

ในขณะที่ยังคงมี facades และ aliasing ใน 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
Aldo Okware

0

ฉันประสบปัญหานี้แม้จะมีuse Illuminate\Http\Request;บรรทัดที่ด้านบนของคอนโทรลเลอร์ก็ตาม เก็บไว้ดึงผมจนผมรู้ว่าผมทำแทน$request::ip() $request->ip()อาจเกิดขึ้นกับคุณได้หากคุณไม่ได้นอนทั้งคืนและกำลังดูรหัสตอน 6 โมงเช้าโดยลืมตาครึ่งหนึ่ง

หวังว่านี่จะช่วยใครบางคนบนท้องถนน


0

ฉันทำให้มันใช้งานได้กับการกำหนดขอบเขต

pagar ฟังก์ชั่นสาธารณะ (\ Illuminate \ Http \ Request $ request) {//


2
โปรดไม่เพียงแสดงโค้ดที่ใช้งานได้ แต่ยังอธิบายด้วยว่าทำไมคุณถึงทำเช่นนี้
creyD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.