จะส่งข้อมูลไปยังมุมมองทั้งหมดใน Laravel 5 ได้อย่างไร?


125

ฉันต้องการให้ข้อมูลเริ่มต้นบางส่วนสามารถเข้าถึงได้ในทุกมุมมองในแอปพลิเคชัน Laravel 5 ของฉัน

ฉันพยายามค้นหาแล้ว แต่พบเฉพาะผลลัพธ์สำหรับ Laravel 4 เท่านั้นฉันได้อ่านเอกสาร 'การแบ่งปันข้อมูลกับทุกมุมมอง' ที่นี่แต่ฉันไม่เข้าใจว่าต้องทำอย่างไร รหัสต่อไปนี้ควรวางไว้ที่ไหน?

View::share('data', [1, 2, 3]);

ขอบคุณสำหรับความช่วยเหลือของคุณ.


คุณต้องการรหัสเริ่มต้นเพื่อจัดการข้อกำหนดนี้หรือไม่?
Safoor Safdar

1
แจ้งให้ทราบโดยใช้ View :: share ในผู้ให้บริการซึ่งผลลัพธ์ของการเรียกฐานข้อมูลจะเกิดข้อผิดพลาดกับแอปพลิเคชันเมื่อเรียกใช้การย้ายฐานข้อมูลการรีเฟรชหรือพยายามเรียกใช้ช่วงค่ำด้วยการเชื่อมต่อฐานข้อมูลที่ไม่สามารถเข้าถึงได้ (เรื่องยาว. env.dusk.local คือ ใช้หลังจากเรียกใช้ผู้ให้บริการเท่านั้น) ดังที่กล่าวไว้ด้านล่างในตัวควบคุมฐานหรือมิดเดิลแวร์นั้นดีที่สุด
Andy Lobel

นอกจากนี้โปรดใช้ความระมัดระวังในการใช้*กับ view composer โดยเฉพาะอย่างยิ่งหากใช้ db queries เนื่องจากมันถูกเรียกใช้สำหรับทุก sub view, component, ฯลฯ ดังนั้นคุณจึงสามารถเรียกใช้ queries ที่ไม่จำเป็นได้หลายร้อยรายการสิ่งที่ดีที่สุดคือการใช้มุมมองพื้นฐานเช่นเลย์เอาต์ จากนั้นส่งผ่านข้อมูลตามต้องการ
Andy Lobel

คำตอบ:


222

เป้าหมายนี้สามารถบรรลุได้ด้วยวิธีการต่างๆ

1. การใช้ BaseController

วิธีที่ฉันชอบจัดเตรียมสิ่งต่างๆฉันสร้างBaseControllerชั้นเรียนที่ขยายขอบเขตของ Laravel Controllerและตั้งค่าสิ่งต่างๆทั่วโลกที่นั่น ตัวควบคุมอื่น ๆ ทั้งหมดจะขยายจากBaseControllerคอนโทรลเลอร์ของ Laravel แทน

class BaseController extends Controller
{
  public function __construct()
  {
    //its just a dummy data object.
    $user = User::all();

    // Sharing is caring
    View::share('user', $user);
  }
}

2. การใช้ตัวกรอง

หากคุณทราบข้อเท็จจริงว่าคุณต้องการตั้งค่าบางสิ่งสำหรับการดูในทุกคำขอตลอดทั้งแอปพลิเคชันคุณสามารถทำได้โดยใช้ตัวกรองที่ทำงานก่อนคำขอ - นี่คือวิธีที่ฉันจัดการกับวัตถุ User ใน Laravel

App::before(function($request)
{
  // Set up global user object for views
  View::share('user', User::all());
});

หรือ

คุณสามารถกำหนดตัวกรองของคุณเอง

Route::filter('user-filter', function() {
    View::share('user', User::all());
});

และเรียกมันผ่านการเรียกตัวกรองง่ายๆ

อัปเดตตามเวอร์ชัน 5. *

3. การใช้มิดเดิลแวร์

ใช้View::shareกับmiddleware

Route::group(['middleware' => 'SomeMiddleware'], function(){
  // routes
});



class SomeMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

4. การใช้ View Composer

View Composer ยังช่วยผูกข้อมูลเฉพาะเพื่อดูในรูปแบบต่างๆ คุณสามารถเชื่อมโยงตัวแปรกับมุมมองเฉพาะหรือมุมมองทั้งหมดได้โดยตรง ตัวอย่างเช่นคุณสามารถสร้างไดเร็กทอรีของคุณเองเพื่อจัดเก็บไฟล์ view composer ตามความต้องการ และไฟล์ผู้แต่งมุมมองเหล่านี้ผ่านบริการให้โต้ตอบกับมุมมอง

วิธีการดูผู้แต่งสามารถใช้วิธีที่แตกต่างกันตัวอย่างแรกอาจมีลักษณะเหมือนกัน:

คุณสามารถสร้างApp\Http\ViewComposersไดเร็กทอรี

ผู้ให้บริการ

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer("ViewName","App\Http\ViewComposers\TestViewComposer");
    }
}

หลังจากนั้นให้เพิ่มผู้ให้บริการนี้ใน config / app.php ในส่วน "ผู้ให้บริการ"

TestViewComposer

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;

class TestViewComposer {

    public function compose(View $view) {
        $view->with('ViewComposerTestVariable', "Calling with View Composer Provider");
    }
}

ViewName.blade.php

Here you are... {{$ViewComposerTestVariable}}

วิธีนี้สามารถช่วยเฉพาะ View ที่เจาะจงเท่านั้น แต่ถ้าคุณต้องการทริกเกอร์ ViewComposer กับมุมมองทั้งหมดเราต้องใช้การเปลี่ยนแปลงเดียวนี้กับ ServiceProvider

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider {
    public function boot() {
        view()->composer('*',"App\Http\ViewComposers\TestViewComposer");
    }
}

การอ้างอิง

เอกสาร Laravel

สำหรับการชี้แจงเพิ่มเติมตอน Laracast

หากยังมีบางอย่างไม่ชัดเจนจากด้านข้างของฉันโปรดแจ้งให้เราทราบ


ตัวอย่างของคุณไม่มีregister()เมธอด - ไม่ใช่ทางเลือก
Jonathan

@jonathan ขอบคุณที่ชี้ให้เห็น แต่ตัวอย่างมีเฉพาะส่วนที่ต้องดูแล มุมมองในการแบ่งปันข้อมูลด้วยมุมมอง
Safoor Safdar

คุณใส่ฟิลเตอร์ไว้ที่ไหน คำตอบที่ถูกต้องที่สุดคือตอนนี้ใช้กลุ่มมิดเดิลแวร์laravel.com/docs/5.3/middleware#middleware-groupsหรือมิดเดิลแวร์ระดับโลก
Toskan

7
นี่ไม่ใช่ความคิดที่ดีผู้สร้าง View จะสร้างอินสแตนซ์ของนักแต่งเพลงสำหรับแต่ละมุมมองซึ่งหมายความว่าหากคุณเรียกใช้ลูป 1,000 ครั้งจะมีการสร้างอินสแตนซ์ของนักแต่งเพลง 1,000 ครั้งและจะจัดการเหตุการณ์การเริ่มทำงาน 1,000 ครั้งซึ่งไม่ใช่สิ่งที่คุณต้องการ
Reza Shadman

4
@RezaShadman ถูกต้อง! ฉันเรียนรู้วิธีนี้ยาก แอปพลิเคชันของฉันทำงานช้ามากจนกระทั่งฉันติดตั้งเครื่องมือ laravel-debugbar เพื่อตรวจสอบ จากนั้นฉันก็รู้ว่าทั้ง 8 แบบสอบถามที่ถูกดำเนินการประมาณ 15 ครั้งสำหรับการโหลดหน้าเดียว เนื่องจากตัวสร้างมุมมองจะถูกเรียกใช้สำหรับไฟล์เบลดแต่ละไฟล์ที่รวมอยู่ *นั่นคือถ้าคุณกำลังใช้เครื่องหมายดอกจัน หากคุณไม่ได้ใช้งาน*คุณควรจะสบายดี
Syclone

66

คุณสามารถสร้างผู้ให้บริการของคุณเอง( ViewServiceProviderชื่อเป็นชื่อสามัญ) หรือคุณสามารถใช้ที่มีอยู่AppServiceProviderก็ได้

ในผู้ให้บริการที่คุณเลือกใส่รหัสของคุณในวิธีการบูต

public function boot() {
    view()->share('data', [1, 2, 3]);
}

สิ่งนี้จะทำให้$dataตัวแปรสามารถเข้าถึงได้ในทุกมุมมองของคุณ

หากคุณต้องการใช้ส่วนหน้าแทนตัวช่วยให้เปลี่ยนview()->เป็นView::แต่อย่าลืมuse View;ที่ด้านบนของไฟล์ของคุณ


ขอบคุณทำงานได้ดี ฟังก์ชั่นการบู๊ตมีไว้สำหรับสิ่งนี้หรือคุณแนะนำให้สร้างผู้ให้บริการของฉันเอง?
Ragnarsson

2
หากคุณมีเพียงหนึ่งหรือสองสิ่งที่จะแบ่งปันใส่เข้าไปก็ใช้ได้AppServiceProviderแต่ถ้าคุณมีอะไรมากกว่านั้นคุณควรพิจารณาสร้างผู้ให้บริการใหม่
Marwelln

มันใช้งานได้ แต่ฉันเพิ่งเห็นว่าวันนี้ใช้งานไม่ได้! ใช้composer updateยังไม่ทำงาน จริงๆแล้วมันไม่ได้ยิงboot()เลย ฉันต้องการแบ่งปันสองตัวแปร
itsazzad

11
โปรดทราบว่าการดำเนินการนี้จะไม่ได้ผลหากคุณกำลังเรียกข้อมูลบันทึกฐานข้อมูลเนื่องจากระบบจะเรียกข้อมูลนี้ก่อนดำเนินการย้ายข้อมูล โดยพื้นฐานแล้วคุณกำลังพยายามดึงบันทึกฐานข้อมูลก่อนที่จะมีอยู่ อย่างน้อยก็น่าจะเป็นเช่นนั้นสำหรับฉัน
lorey

1
น่าเสียดายที่ดูเหมือนจะใช้ไม่ได้กับการแบ่งปันผู้ใช้ที่ลงชื่อเข้าใช้ Auth :: user () คำตอบ # 1 ของ Safoor ซึ่งอยู่ด้านล่างคำตอบนี้ :)
Stan Smulders

11

ฉันพบว่านี่เป็นวิธีที่ง่ายที่สุด สร้างผู้ให้บริการใหม่และใช้'*'สัญลักษณ์แทนเพื่อแนบเข้ากับมุมมองทั้งหมด ทำงานใน 5.3 เช่นกัน :-)

<?php

namespace App\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     * @return void
     */
    public function boot()
    {
        view()->composer('*', function ($view)
        {
            $user = request()->user();

            $view->with('user', $user);
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

2
เพิ่มผู้ให้บริการนี้ในอาร์เรย์ของผู้ให้บริการใน config / app "App \ Providers \ ViewServiceProvider :: class"
Nadeem0035

8

วิธีที่ดีที่สุดคือการแชร์ตัวแปรโดยใช้ View::share('var', $value);

ปัญหาในการเขียนโดยใช้"*":

พิจารณาแนวทางต่อไปนี้:

<?php
// from AppServiceProvider::boot()
$viewFactory = $this->app->make(Factory::class);

$viewFacrory->compose('*', GlobalComposer::class);

จากตัวอย่างมุมมองใบมีด:

  @for($i = 0; $i<1000; $i++)
    @include('some_partial_view_to_display_i', ['toDisplay' => $i])
  @endfor

เกิดอะไรขึ้น?

  • GlobalComposerชั้น instantiated 1000App::makeครั้งที่ใช้
  • composing:some_partial_view_to_display_iมีการจัดการ เหตุการณ์1,000ครั้ง
  • composeฟังก์ชั่นภายในGlobalComposerชั้นที่เรียกว่า 1000 ครั้ง

แต่มุมมองบางส่วนsome_partial_view_to_display_iไม่เกี่ยวข้องกับตัวแปรที่ประกอบด้วยGlobalComposerแต่เพิ่มเวลาในการแสดงผลอย่างมาก

แนวทางที่ดีที่สุด?

ใช้View::shareกับมิดเดิลแวร์ที่จัดกลุ่ม

Route::group(['middleware' => 'WebMiddleware'], function(){
  // Web routes
});

Route::group(['prefix' => 'api'], function (){

});

class WebMiddleware {
  public function handle($request)
  {
    \View::share('user', auth()->user());
  }
}

ปรับปรุง

หากคุณกำลังใช้สิ่งที่คำนวณบนไปป์ไลน์มิดเดิลแวร์คุณสามารถฟังเหตุการณ์ที่เหมาะสมหรือใส่มิดเดิลแวร์แชร์มุมมองที่ด้านล่างสุดของไปป์ไลน์


4

ในเอกสารประกอบ:

โดยทั่วไปคุณจะโทรไปยังวิธีการแชร์ภายในวิธีการบูตของผู้ให้บริการ คุณมีอิสระที่จะเพิ่มลงใน AppServiceProvider หรือสร้างผู้ให้บริการแยกต่างหากเพื่อรองรับพวกเขา

ฉันเห็นด้วยกับ Marwelln เพียงใส่ไว้ในAppServiceProviderฟังก์ชันการบูต:

public function boot() {
    View::share('youVarName', [1, 2, 3]);
}

ฉันขอแนะนำให้ใช้ชื่อเฉพาะสำหรับตัวแปรเพื่อหลีกเลี่ยงความสับสนหรือข้อผิดพลาดกับตัวแปรอื่น ๆ ที่ไม่มี 'global'


3

เอกสารประกอบได้ยินhttps://laravel.com/docs/5.4/views#view-composersแต่ฉันจะทำลายมันลง

  1. มองหาไดเร็กทอรีapp \ Providersในไดเร็กทอรีรากของแอปพลิเคชันของคุณและสร้างไฟล์ComposerServiceProvider.phpแล้วคัดลอกและวางข้อความด้านล่างลงในไฟล์และบันทึก

    <?php
        namespace App\Providers;
        use Illuminate\Support\Facades\View;
        use Illuminate\Support\ServiceProvider;
    
        class ComposerServiceProvider extends ServiceProvider
        {
            /**
            * Register bindings in the container.
            *
            * @return void
            */
        public function boot()
        {
            // Using class based composers...
            View::composer(
                'profile', 'App\Http\ViewComposers\ProfileComposer'
            );
    
            // Using Closure based composers...
            View::composer('dashboard', function ($view) {
                //
            });
        }
    
        /**
        * Register the service provider.
        *
        * @return void
        */
        public function register()
        {
            //
        }
    }
  2. จากรากของแอปพลิเคชันของคุณให้เปิดConfig / app.phpและมองหาส่วน Providers ในไฟล์แล้วคัดลอกและวาง"App \ Providers \ ComposerServiceProvider" นี้ไปยังอาร์เรย์

เมื่อทำเช่นนี้เราได้สร้างผู้ให้บริการนักแต่งเพลง เมื่อคุณเรียกใช้แอปพลิเคชันของคุณด้วยมุมมองโปรไฟล์เช่นhttp: // yourdomain / something / profileผู้ให้บริการComposerServiceProviderจะถูกเรียกและคลาส App \ Http \ ViewComposers \ ProfileComposer จะสร้างอินสแตนซ์เรียกเมธอด Composer เนื่องจากโค้ดด้านล่างภายใน วิธีการบูตหรือฟังก์ชัน

 // Using class based composers...
 View::composer(
   'profile', 'App\Http\ViewComposers\ProfileComposer'
 );
  1. หากคุณรีเฟรชแอปพลิเคชันของคุณคุณจะได้รับข้อผิดพลาดเนื่องจากคลาสApp \ Http \ ViewComposers \ ProfileComposerยังไม่มีอยู่ ตอนนี้ให้สร้างมัน

ไปที่แอพไดเร็กทอรีพา ธ / Http

  • สร้างไดเร็กทอรีชื่อViewComposers

  • สร้างไฟล์ProfileComposer.php

    class ProfileComposer
    {
        /**
        * The user repository implementation.
        *
        * @var UserRepository
        */
        protected $users;
    
        /**
        * Create a new profile composer.
        *
        * @param  UserRepository  $users
        * @return void
        */
        public function __construct(UserRepository $users)
        {
            // Dependencies automatically resolved by service container...
            $this->users = $users;
        }
    
        /**
        * Bind data to the view.
        *
        * @param  View  $view
        * @return void
        */
        public function compose(View $view)
        {
            $view->with('count', $this->users->count());
        }
    }

ไปที่มุมมองของคุณหรือในกรณีนี้คือ Profile.blade.php และเพิ่ม

{{ $count }}

และจะแสดงจำนวนผู้ใช้ในหน้าโปรไฟล์

เพื่อแสดงจำนวนหน้าทั้งหมดเปลี่ยนไป

// Using class based composers...
View::composer(
    'profile', 'App\Http\ViewComposers\ProfileComposer'
);

ถึง

// Using class based composers...
View::composer(
    '*', 'App\Http\ViewComposers\ProfileComposer'
);

<? php และแอปเนมสเปซ \ Http \ ViewComposers; ใช้ Illuminate \ Contracts \ View \ View; หายไปจาก
ProfileComposer.php

1

View Composersผมคิดว่าวิธีที่ดีที่สุดคือด้วย หากมีคนมาที่นี่และต้องการค้นหาวิธีที่สามารถทำได้ด้วยวิธี View Composers โปรดอ่านคำตอบของฉัน => จะแชร์ตัวแปรในมุมมองทั้งหมดได้อย่างไร



1

ภายในโฟลเดอร์ config ของคุณคุณสามารถสร้างชื่อไฟล์ php ได้เช่น "variable.php" พร้อมเนื้อหาด้านล่าง:

<?php

  return [
    'versionNumber' => '122231',
  ];

ตอนนี้อยู่ในมุมมองทั้งหมดที่คุณสามารถใช้ได้เช่น

config('variable.versionNumber')

ฉันใช้วิธีนี้ในบางกรณีเนื่องจากข้อมูลเป็นข้อมูลทั่วโลกและคุณสามารถเข้าถึงได้จากทุกที่ ด้วยเหตุนี้ฉันจึงเรียกไฟล์ config "global.php" และฉันใส่อะไรก็ได้ที่ฉันต้องการให้เข้าถึงได้ในส่วนอื่น ๆ ทั้งหมดของโค้ดของฉัน ข้อ จำกัด เพียงอย่างเดียวคือสำหรับข้อมูลคงที่และได้รับการแคช ไม่ควรใช้วิธีนี้หากคุณมีการเปลี่ยนแปลงข้อมูลอยู่ตลอดเวลา
eResourcesInc

1

1) ใน (app \ Providers \ AppServiceProvider.php)

// in boot function
       view()->composer('*', function ($view) {
            $data = User::messages();
            $view->with('var_messages',$data);
        });

2) ในรูปแบบผู้ใช้ของคุณ

  public static function messages(){ // this is just example
        $my_id = auth()->user()->id;
        $data= Message::whereTo($my_id)->whereIs_read('0')->get(); 
        return $data; // return is required
    }

3) ในมุมมองของคุณ

 {{ $var_messages }}

0

วิธีการ Laravel 5.6: https://laravel.com/docs/5.6/views#passing-data-to-views

ตัวอย่างด้วยการแชร์คอลเล็กชันโมเดลไปยังมุมมองทั้งหมด (AppServiceProvider.php):

use Illuminate\Support\Facades\View;
use App\Product;

public function boot()
{
    $products = Product::all();
    View::share('products', $products);

}

2
สิ่งนี้จะทำให้เกิดปัญหาหากคุณพยายามสร้างแอปพลิเคชันใหม่ที่มีฐานข้อมูลว่างเปล่า
Chris Herbert

0

คุณมีสองทางเลือก:

1. แชร์ผ่านฟังก์ชั่น Boot ใน App \ Providers \ AppServiceProvider

public function boot() { view()->share('key', 'value'); }

และเข้าถึงตัวแปร $ key ในไฟล์มุมมองใด ๆ

หมายเหตุ: โปรดจำไว้ว่าคุณไม่สามารถเข้าถึงข้อมูล Session, Auth, Route ปัจจุบันได้ที่นี่ ตัวเลือกนี้ใช้ได้ดีก็ต่อเมื่อคุณต้องการแชร์ข้อมูลแบบคงที่ สมมติว่าคุณต้องการแบ่งปันข้อมูลบางส่วนตามผู้ใช้ปัจจุบันเส้นทางหรือตัวแปรเซสชันที่กำหนดเองใด ๆ ที่คุณไม่สามารถทำได้กับสิ่งนี้

  1. การใช้คลาสผู้ช่วยสร้างคลาสผู้ช่วยที่ใดก็ได้ในแอปพลิเคชันของคุณและลงทะเบียนใน Alias ​​array ในไฟล์ app.php ในโฟลเดอร์ config

'aliases' => [ ..., 'Helper' => App\HelperClass\Helper::class, ],

และสร้าง Helper.php ในโฟลเดอร์ HelperClass ภายในโฟลเดอร์ App

namespace App\HelperClass;

class Helper
{
    public static function Sample()
    {
        //Your Code Here
    }
}

และเข้าถึงได้ทุกที่เช่น Helper::Sample()

คุณจะไม่ถูก จำกัด ที่นี่ให้ใช้ Auth, Route, Session หรือคลาสอื่น ๆ

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