2016-08-05 38 views
1

Ich habe ein Paket, das automatisch eine PHP-Datei ohne Namespaced laden muss, wenn das Paket in einer Anwendung enthalten ist.Automatisches Einschließen der Datei in ein Paket, wenn sie als Abhängigkeit in Composer enthalten ist

Unten ist meine allgemeine Verzeichnisstruktur

packages/ 
    +-- PackageA/ 
     +-- Entities/ 
     +-- Mappers/ 
     +-- Services/ 
     +-- composer.json 
     +-- constants.php 

apps/appA/ 
    +-- vendors/ 
    +-- autoload/ 
    +-- composer.json 

apps/appB/ 
    +-- vendors/ 
    +-- composer.json 

ich die Anweisungen befolgt hat here einen Pfad Repository PackageA eine Abhängigkeit bei der Herstellung für appA/ zu verwenden. Dieser Teil funktioniert reibungslos.

Einige Dateien innerhalb von PackageA erfordern Zugriff auf Konstanten, meist Dateipfade. Dies ist, was „constants.php“ ist für, und diese Werte werden prozedural definiert:

<?php 

define('XML_REPO_PATH', __DIR__ . '/../blah/xml/'); 

// --etc-- 

ich ursprünglich dachte, die das automatische Laden von Mechanismus ‚Dateien‘ zu verwenden, in „packages/PackageA/composer.json“ mit:

Dies erfordert jedoch nicht constants.php, wenn PackageA als eine Abhängigkeit in appA enthalten ist. Um dies zu beheben, anstatt "files": [...] des Setzens in "packages/PackageA/composer.json", habe ich die folgenden in der Autoload-Abschnitt von "app/appsA/composer.json":

"files": ["vendors/packages/PackageA/constants.php"] 

Dies ist nicht sehr wünschenswert, weil jede Anwendung mit PackageA würde dies benötigen. Ich würde denken, dass die Natur des Komponisten es mir erlauben würde, sicherzustellen, dass Dateien innerhalb von PackageA Zugriff auf bestimmten prozeduralen Code haben (d. H. Dazu gedacht sind), wie im Fall von Konfigurationskonstanten. Gibt es eine Möglichkeit, dies zu tun?

+0

Gibt es einen Grund, warum Sie Ihrer Datei 'constants.php' keinen Namespace hinzufügen können und regelmäßig Autoloading verwenden? – Chris

+0

@Chris, weil ich in PHP <5.6 Klassenkonstanten nicht mit anderen Konstanten wie '__DIR__' verketten kann – jeremy

Antwort

1

Verwenden Sie nicht die files Autoloader-Funktion des Composers, um Konfigurationsdateien oder Dateien mit Konstanten einzuschließen. Bitte denken Sie über die Auswirkungen auf die Performance für alle anderen Bibliotheken nach. Eine Datei im Abschnitt files wird bei jedem Aufruf Ihres Skripts geladen, unabhängig davon, ob Sie PackageA verwenden oder nicht. Denken Sie auch über mögliche Zusammenstöße von konstanten Namen aufgrund von nicht namespaced konstanter Verwendung nach. files Autoloading ist nur! soll für Legacy-Code verwendet werden, der sonst nicht funktioniert. Sie sollten es vermeiden.

weil in PHP < 5.6 i nicht Klassenkonstanten mit anderen Konstanten wie __DIR__

Das Hauptproblem verketten kann, ist nicht die Verkettung, sondern dass die Konstanten Datei ist keine Klasse. Autoloading funktioniert hier nicht, da der Autoloader von Composer nur Klassen lädt.

So könnte eine Lösung eine leere Klasse für Konstanten einführen, aber die Nebenwirkungen oben hinzufügen. Dann namespace es unter Ihrem Lieferanten \ PackageA Regenschirm. Dies ermöglicht es Ihnen, use vendor\PackageA\Constants; in anderen Klassen, hinzufügen, um das Autoloading auszulösen, nicht wahr?

Sie fügen eine leere Klasse ein, aber wenn die Datei automatisch geladen wird, treten die Defines als Nebeneffekte auf. Eine gute IDE fügt dieser Datei ein Fehler-Flag hinzu, da dies zu Nebenwirkungen führt.Es ist immer noch hässlich, weil andere Entwickler nicht wissen, woher die Defines kommen, wenn sie einfach eine Klasse enthalten - aber besser als autoloadingfiles.

composer.json

"autoload": { 
    "psr-4": { "\Vendor\PackageA\\" : "./src/packages/PackageA/" } 
} 

constants.php

<?php 

namespace Vendor\PackageA; 

class Constants 
{ 
    // @todo PHP 5.6 namespaced class constants 
} 

// global side effect: constant definition 
define('XML_REPO_PATH', __DIR__ . '/../blah/xml/'); 

// etc.. 

Die Best-Practice ist wahrscheinlich eine Configuration-Klasse mit einem Konstruktor zu verwenden, die für die Konfiguration Ihres Pakets ein Konfigurationsobjekt oder ein Array akzeptiert. Dieses Entkopplungspaket und Anwendung von fest codierten globalen Konfigurationen. Im Grunde Konfigurationsinjektion (App-Umgebung in Package, Package konfiguriert sich selbst basierend auf diesem Kontext).

+0

Ich ging diese Route, und, wie Sie vorgeschlagen, verließ ich einen '@ Todo'-Kommentar für, wenn wir auf ein upgrade * echte * Version von PHP – jeremy

+0

Froh, ich könnte helfen :) –