![](/img/trans.png)
[英]Laravel livewire - how to pass geo coordinates of user to livewire component
[英]How to persist data objects in Laravel/Livewire component?
我們有一個鏈接到視圖的 Livewire 組件,旨在顯示 data.table 超過 100,000 條記錄,每條記錄顯示許多(最多 300 條)子記錄,來自多種關系(主要是一對多和多對多). 在長時間的優化和調試工作之后,為了獲得 Eloquent 集合(以 15 個為一組分頁)的繁重查詢現在需要大約 15-20 秒才能完成。 該視圖還旨在通過激活模態 windows 允許 CRUD 操作。我們需要解決的主要問題是顯示添加或編輯模態 window 的大延遲。此時,我們不需要運行 data.table再次查詢,因為底層記錄還沒有改變。 主要查詢應該只在初始加載時運行,或者在記錄添加或更新之后運行,此時分頁的 data.table 可能已更改。
這是組件的摘錄,顯示了相關代碼:
public function render()
{
//******************** SECTION A ***************
//This is the eloquent collection we use to generate the data-table in the view
//$q is a public property, binded to a input box, for searching purposes. $sortBy and $sortAsc are used to order the data-table.
$fonos = Fono::select('id','cod','titulo','sello_cod','ritmo_cod','propiedad_cod')
->with(['propiedad:id,cod,propiedad','sello:id,cod,sello','ritmo:id,cod,ritmo','artistas:id,cod,artista','autores:id,cod,autor','operadores:id,cod,operador','isrcs:id,isrc']) //Eager loading relationships to reduce queries (only required fields)
->when( $this->q, function($query) {
return $query->where(function( $query) {
$query->where('titulo', 'like', '%'.$this->q . '%')
->orWhere('cod', 'like', '%' . $this->q . '%')
->orWhere('isrc', 'like', '%' . $this->q . '%')
->orWhere('famoso_por', 'like', '%' . $this->q . '%')
->orWhereHas('sello', function ( $query) {
$query->where('sello', 'like', '%' . $this->q . '%');})
->orWhereHas('autores', function ( $query) {
$query->where('cod', 'like', '%' . $this->q . '%');})
->orWhereHas('autores', function ( $query) {
$query->where('autor', 'like', '%' . $this->q . '%');})
->orWhereHas('artistas', function ( $query) {
$query->where('cod', 'like', '%' . $this->q . '%');})
->orWhereHas('artistas', function ( $query) {
$query->where('artista', 'like', '%' . $this->q . '%');})
->orWhereHas('operadores', function ( $query) {
$query->where('cod', 'like', '%' . $this->q . '%');})
->orWhereHas('operadores', function ( $query) {
$query->where('operador', 'like', '%' . $this->q . '%');})
->orWhereHas('isrcs', function ( $query) {
$query->where('isrc', 'like', '%' . $this->q . '%');})
;
});
})
->orderBy($this->sortBy, $this->sortAsc ? 'ASC' : 'DESC')->paginate(15);
//******************** SECTION B ***************
//Here we load other Eloquent models (some with thousands of records), that are used to populate several selects (drop-down lists), that are visible when the modal window is activated to add or edit a record.
$tipos_fonos = TipoFono::select('cod','tipo_fono')->get();
$sellos = Sello::select('cod','sello')->get();
$ritmos = Ritmo::select('cod','ritmo')->get();
$generos = Genero::select('cod','genero')->get();
$idiomas = Idioma::select('id','idioma')->get();
$propiedades = Propiedad::select('cod','propiedad')->get();
$territorios = Territorio::select('cod','territorio')->get();
$clases_artistas = ClaseArtista::select('id','clase_artista')->get();
$artistasLista = Artista::select('cod','artista')->get();
$papelesLista = PapelArtista::select('id','papel_artista')->get();
$autoresLista = AutorFono::select('cod','autor')->get();
$operadoresLista = Operador::select('cod','operador')->get();
$tipos_autores = TipoAutor::select('id','cod','tipo_autor')->get();
//******************** SECTION C ***************
//Finally, we pass the objects to the view
return view('livewire.admin.fonos', [
'fonos' => $fonos,
'tipos_fonos' => $tipos_fonos,
'sellos' => $sellos,
'ritmos' => $ritmos,
'generos' => $generos,
'idiomas' => $idiomas,
'propiedades' => $propiedades,
'territorios' => $territorios,
'clases_artistas' => $clases_artistas,
'artistasLista' => $artistasLista,
'papelesLista' => $papelesLista,
'tipos_autores' => $tipos_autores,
'autoresLista' => $autoresLista,
'operadoresLista' => $operadoresLista,
]);
}
顯然,我們需要一種方法來避免不必要的查詢,但我們發現了實現該目標的重要限制。 例如:
我們試圖在初始加載時在 memory 中存儲用於填充 select 元素的 Eloquent 模型(集合),因為該數據在生命周期中不會更改。 因此,我們將這些查詢移至 mount 方法,例如:
public function mount() { // This runs once, like a constructor class //Load all models for select drop-downs //all the variables are declared as public properties and also included in the $rules array (ie 'lw_generos.*.cod' => 'nullable') $this->lw_tipos_fonos = TipoFono::select('cod','tipo_fono')->get(); $this->lw_sellos = Sello::select('cod','sello')->get(); $this->lw_ritmos = Ritmo::select('cod','ritmo')->get(); $this->lw_generos = Genero::select('cod','genero')->get(); $this->lw_idiomas = Idioma::select('id','idioma')->get(); $this->lw_propiedades = Propiedad::select('cod','propiedad')->get(); $this->lw_territorios = Territorio::select('cod','territorio')->get(); $this->lw_clases_artistas = ClaseArtista::select('id','clase_artista')->get(); $this->lw_artistasLista = Artista::select('cod','artista')->get(); $this->lw_papelesLista = PapelArtista::select('id','papel_artista')->get(); $this->lw_autoresLista = AutorFono::select('cod','autor')->get(); $this->lw_operadoresLista = Operador::select('cod','operador')->get(); $this->lw_tipos_autores = TipoAutor::select('id','cod','tipo_autor')->get(); }
所以,為了與這個修改保持一致,我們更改了 render 方法的 C 部分:
return view('livewire.admin.fonos', [ 'fonos' => $fonos, 'tipos_fonos' => $this->lw_tipos_fonos, 'sellos' => $this->lw_sellos, 'ritmos' => $this->lw_ritmos, 'generos' => $this->lw_generos, 'idiomas' => $this->lw_idiomas, 'propiedades' => $this->lw_propiedades, 'territorios' => $this->lw_territorios, 'clases_artistas' => $this->lw_clases_artistas, 'artistasLista' => $this->lw_artistasLista, 'papelesLista' => $this->lw_papelesLista, 'autoresLista' => $this->lw_autoresLista, 'operadoresLista' => $this->lw_operadoresLista, 'tipos_autores' => $this->lw_tipos_autores, ]);
這種方法的問題是它會產生一個錯誤:
Symfony\Component\ErrorHandler\Error\FatalError 最大執行時間超過 30 秒 Symfony\Component\ErrorHandler\Error\FatalError::__construct vendor/laravel/framework/src/Illuminate/Collections/Arr.php:115
注意:我們嘗試直接在視圖中使用 Eloquent collections 的公共變量,而不顯式傳遞它們,但結果是一樣的。 我們還考慮過將屬性聲明為私有或受保護的,但數據不會持久化(並且 Livewire 文檔指出私有或受保護的屬性不會在組件更新后繼續存在)。
我們正在努力避免在視圖渲染期間發生的不必要的查詢。 $fonos Eloquent 集合應僅在數據更改(以模態形式完成的修改)或使用搜索輸入時更新。 在其他情況下,集合應作為 object 存儲在 memory 中,准備傳遞給視圖。 但實現該目標存在障礙:首先,分頁為 collections 的 eloquent 目前無法存儲為 Livewire 屬性(僅允許 JavaScript 兼容數據)。 其次,即使我們可以將集合分配給公共屬性,我們也會遇到與前一點所述相同的錯誤。
我們正在使用 Laravel 8.28.1 和 Livewire 2.3.18。
我們通過使用 Livewire 計算屬性和緩存查詢結果解決了這個問題。 例如:
public function getBancosProperty(){
/* Caching */
$expire = Carbon::now()->addMinutes(10);
$bancos = Cache::remember('bancos', $expire, function() {
return Banco::select('cod','banco')->orderBy('banco')->get();
});
return $bancos;
}
希望這對其他人有幫助。
問候。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.