foreach слишком медленный с Blade в Laravel 5.2 - PullRequest
0 голосов
/ 12 ноября 2018

Я работаю с Laravel 5.2, и у меня есть раздел, который отвечает слишком медленно, я обнаружил, что большая задержка происходит в цикле foreach, это занимает одну секунду на строку, и я перечисляю около 100 регистров, которые делают сайточень медленно.Это редко, потому что я показываю только 7 столбцов, а в таблице всего 213 строк, что очень мало, если в таблице 16 столбцов.

Что я могу сделать?Это блок foreach.Это занимает столько времени, только в производственной среде

@foreach($tickets as $ticket)
          <tr>
            <td>
              {{ $ticket->id }}
            </td>
            <td>
              {{ $ticket->creator->worksAt->nombre }}
            </td>
            <td>
              {{ $ticket->patient->toArray()['rut'] }}
            </td>
            <td>
              {{ $ticket->getProcessName() }}
            </td>
            <td>
              {{ $ticket->created_at->format('d M Y') }}
            </td>
            @if ($ticket->getProcessSla() == $ticket->getLatency() )
              <td  class="alert-warning">
            @elseif ($ticket->getProcessSla() < $ticket->getLatency() )
              <td  class="alert-danger">
            @else
              <td  class="alert-success">
            @endif
              {{ $ticket->getLatency() }} días
              (Límite: {{ $ticket->getProcessSla() }})
            </td>
            <td>
              @if ( null !== Auth::user()->roles->find($ticket->getProfileId()) )
                {{ Form::open(array('action'=>'StageController@redirect')) }}
                  {{ Form::hidden('ticket_id', $ticket->cryptId()) }}
                  {{ Form::hidden('process_id', $ticket->cryptProcessId()) }}
                  {{ Form::submit('Iniciar', ['class'=>'btn btn-xs btn-block btn-primary']) }}
                {{ Form::close() }}
              @endif
            </td>
          </tr>
    @endforeach

Модель билета это

 <?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Http\Controllers\Controller;
use Crypt;
use DB;

class Ticket extends Model
{


protected $fillable = [
  'patient_id',
  'id_empresa',
  'id_usuario',
  'requiere_clinico',
  'requiere_ept',
  'activo',
  'responsable',

  'ept_id',
  'clinico_id',
  'is_massive',
  'inasistente',

  'creacion_original',
  'ficha_id'

];




/*
 * Relations
 */
public function creator()
{
  return $this->belongsTo('App\User', 'id_usuario');
  //'App\Partner', 'clinical_provider', 'id_client', 'id_provider'
}


public function assignedTo()
{
  return $this->belongsTo('App\User', 'responsable', 'id');
}

public function appointment()
{
  return $this->hasMany('App\Appointment', 'id_ticket');
}

public function annulments()
{
  return $this->hasMany('App\Anullment');
}

public function eptCriteria()
{
  return $this->hasOne('App\EptCriteria');
}


public function patient()
{
  return $this->belongsTo('App\Patient');
}

public function enterprise()
{
  return $this->belongsTo('App\Enterprise', 'id_empresa');
}

public function process(){
  return $this->belongsToMany('App\Process', 'flows', 'id_ticket', 'id_proceso');
}

public function witness(){
  return $this->belongsToMany('App\Witness')->withTimestamps();
}

public function documents()
{
  return $this->hasMany('App\Document', 'id_ticket');
}

public function flows()
{
  return $this->hasMany('App\Flow', 'id_ticket');
}

public function comments()
{
  return $this->hasMany('App\Models\Tickets\Comment', 'ticket_id');
}

/**
 * Esto permite dejar la evidencia de cuando se envió el contacto a las empresas
 * @return [type] [description]
 */
public function enterpriseContacts(){
  return $this->hasMany('App\Enterprisecontact');
}

public function getProcessName(){
  return \App\Process::find($this->process()->max('id_proceso'))->nombre;
}

public function getProcessDescription(){
  return \App\Process::find($this->process()->max('id_proceso'))->descripcion;
}

public function getProfileId(){
return \App\Process::find($this->process()->max('id_proceso'))->id_perfil;
}

public function getProcessSla(){
  return \App\Process::find($this->process()->max('id_proceso'))->sla;
}

public function getLatency(){
  $created = new \Carbon\Carbon($this->created_at);
  return $created->startOfDay()->diffInDays();
}
public function getProcessId(){

  return \App\Process::find($this->process()->max('id_proceso'))->id;
}

public function getClinicalAppointment(){
  return $this->appointment()->where('tipo_citacion', '=', 1)->first()['fecha'];
}


public function cryptProcessId(){
  return  Crypt::encrypt($this->getProcessId());
}

public function cryptId(){
  return  Crypt::encrypt($this->id);
}

public function scopeMassive($query){
  $query->where('activo', 1)
        ->where('is_massive', 1);
}

public function eptTest()
{
  return $this->hasMany('App\EptTest');
}

public function clinicalMovements()
{
  return $this->hasMany('App\Models\MR\Movimiento');
}


 }

1 Ответ

0 голосов
/ 13 ноября 2018

Давайте посчитаем количество запросов и других операций здесь:

  1. $ticket->creator: запрос
  2. creator->worksAt возможно, другой запрос (предположим, что исходный код не предоставлен)
  3. $ticket->patient: запрос
  4. $ticket->getProcessName(): запрос
  5. $ticket->getProcessSla(): запрос
  6. Auth::user()->roles: запрос
  7. $ticket->cryptId(): шифрование
  8. $ticket->cryptProcessId(): шифрование + запрос (для процесса поиска)

Всего: 7 запросов + 2 шифрования на один билет, количество раз 213 строк.

Соответствует 1 491 запросам и 426 шифрам . Не удивительно, что это медленно? Это не foreach.

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

...