2015-12-17 2 views
9

Ich verwende SensioLabs Insight, um meine Codequalität zu kontrollieren.Warum die absoluten Pfadkonstanten __DIR__ und __FILE__ in Symfony nicht verwendet werden sollten

Für eine einfache Datei-Upload, habe ich den absoluten Pfad meiner Upload-Verzeichnis erhalten:

protected function getUploadRootDir() 
{ 
    // the absolute directory path where uploaded 
    return __DIR__.'/../../../../web/'.$this->getUploadDir(); 
} 

-Code direkt von der offiziellen Dokumentation (How to handle file uploads with Doctrine)

Aber SLInsight wirft eine Warnung, wenn der Code kommt analysiert enthält __DIR__ oder __FILE__ PHP magische Konstanten:

__DIR__ und __FILE__ Konstanten können Konflikte mit dem überschreibenden System der Symfony-Ressource verursachen.

Wie die Verwendung dieser Konstanten Konflikte mit Symfony verursachen kann?

Und wie kann ich sie in meinem Code vermeiden?

+1

Der Titel ist irreführend. Es wird ** empfohlen ** die absoluten Pfadkonstanten '__FILE__' und' __DIR__' generell zu verwenden. Es ist besser, stattdessen den Datei-Locator von Symfony * zu verwenden, wenn Sie Symfony (oder den Datei-Locator) * in Ihrem Projekt verwenden. – axiac

+0

Richtig, ich habe es aktualisiert. Danke – chalasr

+0

Um ehrlich zu sein, wenn ich diesen Code sehe, wäre meine Reaktion "es muss einen besseren Weg geben als das". Sie codieren hart, dass der Pfad, den Sie haben wollen, genau 4 Stufen hoch ist, dann ein Verzeichnis namens "Web" und dann ein dynamisches Segment. Das sieht sehr fragil und unflexibel aus. Sicherlich sollte dieser ganze Pfad relativ zu einer bestimmten Basis irgendwo konfiguriert sein. – IMSoP

Antwort

11

Bei der Datei-Upload-Klasse, können Sie wahrscheinlich diese Fehlermeldung ignorieren. In anderen Fällen ist es besser, den Symfony-Datei-Locator anstelle der Hardcoding-Dateipfade zu verwenden. Zum Beispiel:

$path = $this->get('kernel')->locateResource('@AppBundle/Resources/config/services.xml'); 

Statt:

$path = __DIR__.'/../../../src/Acme/AppBundle/Resources/config/services.xml' 
+0

Hallo Herr Eguiluz, ist es richtig, diesen Code in einem Entity-Modell zu verwenden? (* Ich dachte früher, dass das Aufrufen eines Kernels oder eines anderen Dienstes innerhalb des Modells nicht 'sehr sauber' war .... *) – pbenard

+3

Nun, ich würde sagen, dass das Hochladen des Verzeichnisses von einer Entität bereits nicht sauber ist. Die Entität sollte nicht dafür verantwortlich sein, zu wissen, wo die hochgeladenen Dateien gespeichert sind (was vielleicht nicht einmal lokal, sondern zum Beispiel auf S3 ist). –

+0

Danke für diese Erklärung Herr, und ein tolles ** Dankeschön ** für Ihren ganzen Job. – pbenard

7

Nun, das ist etwas, was SensioLabs Insight nicht richtig handhabt. Es warnt vor der Verwendung der Konstanten wegen des überschreibenden Systems der Ressource, aber in vielen Fällen werden diese Konstanten an Stellen verwendet, die nichts mit dem überschreibenden System zu tun haben (dies ist wahrscheinlich für Ihren Code hier der Fall). So können Sie die Warnung in diesem Fall ignorieren

+0

Heute Morgen wurde die Warnung bei einem Komponententest ausgelöst. Diese Regel sollte auf Klassen beschränkt sein, die das Symfony-Ressourcenüberschreibungssystem verwenden können. http://prnt.sc/aa68cw – chalasr

0

Wenn Sie einen Drittanbieter-Bundle erstellen und einige Ressourcen suchen möchten, die (gut) Lösung von @Javier vorgeschlagen, da es nicht anwendbar löst eine Ausnahme:

ServiceNotFoundException in ContainerBuilder.php line 816: 
You have requested a non-existent service "kernel". 

In diesem Fall ist die Lösung $this->getPath(), ein Verfahren, mit dem aus dem BundleNameBundleSymfony\Component\HttpKernel\Bundle\Bundle c geerbt zu verwenden ist, Mädel.

Dies liefert das gleiche Ergebnis von realpath(__DIR__).

So tun $this->getPath() . '/Resources/config/doctrine/mappings' ist die gleiche wie realpath(__DIR__ . '/Resources/config/doctrine/mappings').

vorgeschlagen Ursprünglich here.

+0

Der 'kernel'-Dienst ist zur Kompilierzeit nicht verfügbar (erstens, weil er synthetisch ist), so dass Sie ihn nicht aus einem Compiler-Durchlauf verwenden können, aber er funktioniert tatsächlich aus jedem Laufzeitkontext. Hier ist der Kontext eine Entität, daher sollten wir keinen Service verwenden, und da meine Entität keine Bundle-Instanz ist (da dies keinen Sinn ergeben würde), ist "getPath" nicht verfügbar. Also ignorieren die Warnung, wie in den beiden vorherigen Antworten angegeben, bleiben die beste Lösung, die ich denke – chalasr

+0

Ja, ich weiß. Ich habe die Antwort hinzugefügt, da diese Frage angezeigt wird, wenn nach dem Problem im Bundle-Erstellungskontext gesucht wird. Aber die hier vorgeschlagenen Lösungen sind nicht geeignet. Also fügte ich die Antwort hinzu, wer also im Rahmen der Bundle-Erstellung nach einer Lösung sucht, kann sie trotzdem finden. Ist für die interne Verknüpfung ... – Aerendir

Verwandte Themen