Einfache Konventionen

Ich bin ein absoluter Laravel Fan, das vorneweg. Jedoch gibt es so gewisse Dinge, die es zu wissen gibt – oder die man einfach wissen muss um die Performance von Laravel nicht negativ zu beeinflussen oder sie gar noch zu verbessern.

Welche Fehler können auf Performanceprobleme hinweisen?

Apache & PHP-FPM memory usage: Diesen Fehler von PLESK kennen vielleicht die Meisten unter uns, gerade wenn die Relationships komplizierter werden und die Anwendung komplexer. Dies bedeutet einen Performancefehler in der Anwendung.

Tipps: Relationships

Gib die Parameter an!

Laravel selbst schreibt in der eigenen Doku von Funktionen wie return $this->morphTo(); oder einem simplen return $this->belongsTo(User::class);. Das ist zweifelsohne sehr praktisch, oder? Schließlich passiert all die “Magic” unter der Haube und Laravel weiß wie von Geisterhand wohin “gemorphed” wird und wohin es “belongt”.

Doch ganz so simpel ist es nicht, wenn du dir das nachfolgende Codebeispiel ansiehst:

public function taggable()
{ 
    return $this->morphTo(__FUNCTION__);
}

public function user()
{
    return $this->belongsTo(User::class, 'user_id', 'id', __FUNCTION__)
}

Erklärung:

Wenn wir uns die Funktion morphTo ansehen, dann finden wir da “eigentlich” weitere Attribute, wie $name = null, $type = null und $id = null.

Und darunter siehst du, wie Laravel den Namen “errät” (also guess). Dass dies aber jetzt zusätzlich Ressourcen benötigt, das dürfte auf der Hand liegen…

Dementsprechend “läuft” Laravel den Stack Trace (oder auch Debug Trace) ab, also genau den Stapel an Befehlen der dem jetzigen voranging. Das bedeutet: Laravel “schaut”, wie der Name sein könnte. Hier “function taggable”, also “taggable”. Und genau diese Schritte sind unnötig und zu vermeiden.

// MorphTo Example

public function morphTo($name = null, $type = null, $id = null)
{
        
   $name = $name ?: $this->guessBelongsToRelation();

   list($type, $id) = $this->getMorphs(
       Str::snake($name), $type, $id
   );

        
   return empty($class = $this->{$type})
                ? $this->morphEagerTo($name, $type, $id)
                : $this->morphInstanceTo($class, $name, $type, $id);
}

protected function guessBelongsToRelation()
{
   list($one, $two, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);

   return $caller['function'];
}

// BelongsToMany Example

public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null, $parentKey = null, $relatedKey = null, $relation = null)
{
      
   if (is_null($relation)) {
      $relation = $this->guessBelongsToManyRelation();
   }

   $instance = $this->newRelatedInstance($related);

   $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();

   $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();

   if (is_null($table)) {
       $table = $this->joiningTable($related);
   }

   return $this->newBelongsToMany(
       $instance->newQuery(), $this, $table, $foreignPivotKey,
       $relatedPivotKey, $parentKey ?: $this->getKeyName(),
       $relatedKey ?: $instance->getKeyName(), $relation
   );
}

protected function guessBelongsToManyRelation()
{
   $caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function ($trace) {
       return ! in_array($trace['function'], Model::$manyMethods);
   });

   return ! is_null($caller) ? $caller['function'] : null; 
}

Fazit: Versuche nach Möglichkeit zukünftig bei performanten Anwendungen die “guess” Attribute mitzuliefern und nicht aus “Faulheit” zu überspringen. Und ja 😎 ich weiß… Das ist ja nur eine Kleinigkeit ;-)… Aber viele Kleinigkeiten führen zu einer großen Wirkung. Daher ist das nicht wirklich ein Argument zu sagen “ach, ich lass es mal bleiben”. Viel Spaß beim Coden 🙂

Andreas Pabst Top Speaker – IT Coach – Rhetorik Trainer hat 4,87 von 5 Sternen 73 Bewertungen auf ProvenExpert.com