Laravel如何自定义类似boot()的全局函数实现全局搜索?
Let me break this down for you and fix your issue step by step:
First up, the code you wrote with static::created(function(Request $request){...}) is totally off the mark. That syntax is for Eloquent model event listeners—it’s meant to run code when a specific model is created. But since you’re putting this in AppServiceProvider, the static here refers to the provider class itself (not a model), so this code will never trigger, and it has nothing to do with passing data to your search bar.
Here are the correct ways to achieve your goal of making search-related data available globally to your header:
Option 1: Use View::share directly in your existing boot method
This is the simplest approach if you just need to pass basic data (like popular search terms or categories) to every page’s header:
public function boot() { parent::boot(); // Keep your existing header data logic here // ... // Add this: Fetch and share search-specific data globally $searchData = [ 'popularKeywords' => ['Laravel', 'PHP', 'Web Development'], // Replace with DB queries 'categories' => \App\Models\Category::active()->get() // Example: Get active categories ]; // Share data with all views—access it via $searchData in your templates \Illuminate\Support\Facades\View::share('searchData', $searchData); // Alternatively, share individual variables if you prefer: // \Illuminate\Support\Facades\View::share('popularKeywords', $searchData['popularKeywords']); }
Then in your header template (e.g., resources/views/layouts/header.blade.php), you can use the data directly:
<input type="text" placeholder="Search..." list="popularKeywords"> <datalist id="popularKeywords"> @foreach($searchData['popularKeywords'] as $keyword) <option value="{{ $keyword }}"> @endforeach </datalist>
Option 2: Use a View Composer (better for complex logic)
If your search data logic is more involved, or you only want to load the data when the header view is actually rendered (instead of every page load), use a view composer:
public function boot() { parent::boot(); // Keep your existing header logic here // ... // Register a composer that only runs when your header view loads \Illuminate\Support\Facades\View::composer('layouts.header', function ($view) { // Fetch search data here (customize to your needs) $popularKeywords = \App\Models\SearchHistory::orderBy('count', 'desc')->take(5)->pluck('keyword'); recentSearches = session('recent_searches', []); // Pass data directly to the header view $view->with([ 'popularKeywords' => $popularKeywords, 'recentSearches' => recentSearches ]); }); }
This way, the data query only runs when the layouts.header view is used, which is more efficient. You can then use $popularKeywords and $recentSearches directly in your header template.
Option 3: Custom method (for cleaner code organization)
If you want to separate your search data logic into its own "boot-like" method (to keep your main boot method clean), just define a custom method and call it from boot:
public function boot() { parent::boot(); // Existing header logic // ... // Call your custom search data setup method $this->setupGlobalSearchData(); } // Custom method to handle search data logic private function setupGlobalSearchData() { $searchData = [ 'popularKeywords' => \App\Models\SearchHistory::topKeywords(), // Use a model helper method 'recentSearches' => session('recent_searches', []) ]; \Illuminate\Support\Facades\View::share('searchData', $searchData); }
Remember: The framework only automatically runs the register and boot methods in service providers. Any custom methods need to be called from one of these two to execute.
内容的提问来源于stack exchange,提问作者Ali Özzen

