2009-12-24 14 views
47

Ich möchte eine PHP-Klasse machen, sagen wir Myclass.php. Jetzt innerhalb dieser Klasse möchte ich nur die Klasse selbst und einige Instanzvariablen definieren. Alle Methoden müssen jedoch aus einer Myclass_methods.php-Datei stammen. Kann ich diese Datei einfach in den Klassenkörper aufnehmen?Kann ich Code in eine PHP-Klasse einbinden?

Ich habe gute Gründe, warum ich das trennen möchte. Kurz gesagt, ich werde ein Backend haben, in dem ich die Geschäftslogik einer Klasse ändern kann, während alle anderen Dinge unberührt bleiben müssen. Das System behält das ganze ORM und andere Sachen für mich bei.

Aber wenn dies eine schlechte Idee ist, könnte es besser sein, die ganze Klasse-Datei neu zu erstellen, nachdem die Geschäftslogik der Bearbeitung (so die benutzerdefinierten Methoden in diesem Fall).

Leistung Frage: Wird bei einer Anfrage Myclass.php nur einmal enthalten ist, eigentlich, dass Myclass_methods.php sollte auch nur einmal aufgenommen werden. Könnte falsch liegen. Experten?

+10

Tun Sie dies nicht, lernen Sie, OOP richtig zu verwenden. –

+0

Namespace verwenden! – zloctb

Antwort

153

Nein, Sie können keine Dateien in der Klasse Körper umfassen.
In einer Datei, die eine Klasse definiert, dürfen Sie nur Dateien in eine Methodenkörper oder außerhalb des Klassenkörpers einschließen.

Aus Ihrer Beschreibung Ich nehme Sie dies:

<?php // MyClass.php 
class MyClass 
{ 
    protected $_prop; 
    include 'myclass-methods.php'; 
} 

<?php // myclass-methods.php 
public function myMethod() 
{ 
    $this->$_prop = 1; 
} 

diesen Code laufen in

Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION 

führen wird, was möglich ist, wenn dies

<?php // MyClass.php 
class MyClass 
{ 
    protected $_prop; 
    public function __construct() // or any other method 
    { 
     include 'some-functions.php'; 
     foo($b); // echoes 'a'; 
    } 
} 

<?php // some-functions.php 
$b = 'a'; 
function foo($str) 
{ 
    echo $str; 
} 

es auf diese Weise tun , wird den Inhalt der Include-Datei in den Methodenbereich und nicht in den Klassenbereich importieren. Sie können Funktionen und Variablen in die Include-Datei aufnehmen, aber keine Methoden. Sie könnte, sollte aber nicht ganze Skripte hinein und ändern, was die Methode, z.

Das Patchen der Klasse auf diese Weise, um ein anderes Verhalten zu zeigen, ist jedoch nicht so, wie Sie es in OOP tun sollten. Es ist einfach falsch und sollte deine Augen bluten lassen.

Da Sie Verhalten dynamisch ändern, ist die Klasse erweitert auch nicht eine gute Option (siehe unten, warum). Was Sie wirklich tun wollen, ist ein interface schreiben und machen Sie Ihre Klasse Objekte verwenden diese Schnittstelle implementieren, so dass die entsprechenden Methoden zur Verfügung stellen. Dies ist ein Strategy Pattern und funktioniert wie folgt genannt:

<?php // Meowing.php 
interface Meowing 
{ 
    public function meow(); 
} 

Jetzt haben Sie den Vertrag, dass alle Meowing Behaviors gehorchen müssen, nämlich ein Miauen Verfahren mit.Als nächstes ein Miauen Verhalten definieren:

<?php // RegularMeow.php 
class RegularMeow implements Meowing 
{ 
    public function meow() 
    { 
     return 'meow'; 
    } 
} 

Nun, es zu benutzen, verwenden Sie:

<?php // Cat.php 
class Cat 
{ 
    protected $_meowing; 

    public function setMeowing(Meowing $meowing) 
    { 
     $this->_meowing = $meowing; 
    } 

    public function meow() 
    { 
     $this->_meowing->meow() 
    } 
} 

Durch das Miauen TypeHint zu setMeowing hinzufügen, stellen Sie sicher, dass die übergebene param die Miauen-Schnittstelle implementiert. Lassen Sie uns ein anderes Meowing Verhalten definieren:

<?php // LolkatMeow.php 
class LolkatMeow implements Meowing 
{ 
    public function meow() 
    { 
     return 'lolz xD'; 
    } 
} 

Jetzt können Sie leicht Austausch Verhalten wie folgt aus:

<?php 
require_once 'Meowing.php'; 
require_once 'RegularMeow.php'; 
require_once 'LolkatMeow.php'; 
require_once 'Cat.php'; 

$cat = new Cat; 
$cat->setMeowing(new RegularMeow); 
echo $cat->meow; // outputs 'meow'; 
// now to change the behavior 
$cat->setMeowing(new LolkatMeow); 
echo $cat->meow; // outputs 'lolz xD'; 

Während Sie auch die oben mit inheritance durch Definieren eines abstract BaseCat und miauen Verfahren gelöst haben könnte und dann Bei der Ableitung konkreter RegularCat- und Lolkat-Klassen müssen Sie überlegen, was Sie erreichen möchten. Wenn deine Katzen niemals die Art und Weise ändern, wie sie miauen, dann mach weiter und benutze die Vererbung, aber wenn dein RegularCat und Lolkat in der Lage sein sollen, willkürliche Miauen zu machen, dann benutze das Strategie-Muster.

Weitere design patterns in PHP, überprüfen Sie die folgenden Ressourcen:

+4

Der Ansatz von Katzen und Gemähten macht es. Ich hätte versucht, die Hunde und bellt Ansatz, aber ich realisiere, dass wäre ein komplettes Durcheinander gewesen. –

+0

** Veraltet! Sie können Dateien einschließen! ** Siehe: \t http://Stackoverflow.com/a/47951483/2377343 –

+0

@ T.Todua mit Traits ist eine ganz andere Sache, was hier gefragt wird, also nein, die Antwort steht noch und ist nicht überholt. – Gordon

8

Vielleicht ist es nicht eine Idee, die Kernklasse mit der entsprechenden Basisfunktionalität zu erstellen und dann mit den erforderlichen Methoden zu erweitern - es scheint ein logischer Ansatz zu sein.

+0

Auch Funktionen von der Klasse A in der Quelle a.php zu Klasse B in b.php aufzurufen wäre besser als include_once(). Etwas wie Pimpl Idiom. –

+0

Sie haben Recht, das macht Sinn. Habe über diese Option nicht nachgedacht. – openfrog

6

ich ich bin nicht starten werde sagen, Klar, warum dieses Problem nicht am besten gelöst wird eine Basisklasse, die die Methoden enthält, Unterklassen, die die Daten enthalten, und dynamisches Laden von Klassen. Ich nehme an, Sie haben einen guten Grund.

Sobald Ihr Provider PHP 5.4 unterstützt, können Sie mit Traits machen, was Sie wollen. Datei

Code:

if ($pet === 'dog') include 'dog.php'; 
elseif ($pet === 'cat') include 'cat.php'; 
else die('Unknown pet'); 

class Pet { 
    use PetSounds; 
} 

$myPet = new Pet(); 
$myPet->speak(); 

Datei cat.php

trait PetSounds { 
    function speak() { echo 'meow'; } 
} 

Datei dog.php

trait PetSounds { 
    function speak() { echo 'woof'; } 
} 

du noch sauberer machen könnte durch die Benennung enthalten beide Dateien gleich sind, Setzen Sie sie in verschiedene Unterverzeichnisse und verwenden Sie set_include_path() oder definieren Sie eine __autoload() -Funktion, zwischen der Sie auswählen können Sie. Wie ich schon sagte, könnte das gleiche Problem besser durch Vererbung gelöst werden. Wenn Sie jedoch ein Problem mit mehreren Vererbungstypen haben, wenn Sie beispielsweise vier Arten von Haustieren mit fünf Arten von Farben mit drei Haartypen haben und für jede der 60 verschiedenen Klassen eine andere Kombination von Methoden benötigen, ist dies die richtige Lösung .

5.4 ist momentan nur ein Release Candidate (Stand vom 24.02.2012) und sogar einmal veröffentlicht, werden die meisten Hosts es für viele Monate nicht unterstützen - meines dauerte 18 Monate nachdem 5.3 veröffentlicht wurde, bevor sie es unterstützen würden. Bis dahin müssen Sie vollständig getrennte und vollständige Klassendateien schreiben. Sie können Ihre Klassen jedoch mit einer eventuellen Änderung der Merkmale formatieren.

Jetzt können Sie teilweise bekommen, was Sie wollen mit magischen Methoden und haben ein einfaches Upgrade auf Merkmale, wenn sie verfügbar sind.

-Code Datei:

if ($pet === 'dog') include 'dog.php'; 
elseif ($pet === 'cat') include 'cat.php'; 
else die('Unknown pet'); 

class Pet { 
    public function __call($name, array $arguments) 
    { 
    array_unshift($arguments, $this); 
    return call_user_func_array("TraitFunc_$name", $arguments); 
    } 
} 

$myPet = new Pet(); 
$myPet->speak(); 

Datei cat.php

function TraitFunc_speak(Pet $that) { echo 'meow'; } 

Datei dog.php

function TraitFunc_speak(Pet $that) { echo 'woof'; } 

Sie beschränken sich jedoch dadurch, dass Ihre Funktionen können nicht privat Zugang und geschützt Klasseneigenschaften und Methoden und Sie können diese Methode nicht verwenden, um magische Methoden wie __g bereitzustellen et(). Eigenschaften werden beide dieser Beschränkungen lösen.

+0

Verdammt gute Antwort. – Teson

3

Was ist mit Eigenschaften für diese verwenden? Wäre das eine akzeptable Option? Das ist etwas, mit dem ich gerade experimentiere, und es scheint ziemlich lange zu funktionieren.

Eine vereinfachte Version von dem, was ich mache, ist im Grunde so. Ich habe eine Anwendung mit freigegebenen Kerndateien und mehreren Projekten. Innerhalb dieser Projekte habe ich Module. Ich möchte Funktionen haben, die für das gesamte Projekt auf einer Core-Ebene verfügbar sind, aber nur für das jeweilige Projekt.

Mein Projekt Controller

if(is_file(PROJECT_PATH.'/project_extensions.trait.php')){ 
    // additional functions for this specific project 
    require_once(PROJECT_PATH.'/project_extensions.trait.php'); 
}else{ 
    // no additional functions 
    trait Extensions{}; 
} 


Class Project{ 
    USE Extensions; 

    // default functions shared between all projects 
    function shared_stuff(){ 

    } 
} 

Extensions

trait Extensions{ 
    // project-specific extensions 
    function this_project_only(){ 
    echo 'Project Only'; 
    } 
} 

Moduldatei im Projekt-Datei

class MyModule extends Modules{ // modules extends projects in a different class not relevant here 

    function do_something(){ 
    echo $this->project_only(); 
    } 
} 
0

Eine alte Frage wieder aufleben lassen, aber das ist eine ziemlich einfache Lösung. Benötigen Sie die allgemeinen Funktionsaufrufe, um exklusiv für Ihre Klasse zu sein? Wenn nicht, fügen Sie einfach Ihre gemeinsamen Funktionsdateien in den gleichen Umfang wie Ihre Klasse ein. Sie müssen Methoden in Ihrer Klasse erstellen, aber sie müssen nur die allgemeine Funktion aufrufen. Hier ist ein einfaches SOAP-Server Beispiel:

<?php 

include 'post_function.php'; 

$server = new SoapServer(null, array('uri' => "http://localhost/")); 
$server->setClass( 'postsoapclass'); 
$server->handle(); 


class postsoapclass 
{ 
    public function animalNoise($animal) 
    { 
     return get_animal_noise($animal); 
    } 
} 

?> 

post_function.php

<?php 

function get_animal_noise($animal) 
{ 
    if(strtolower(trim($animal)) == 'pig') 
    { 
     return 'Oink'; 
    } 
    else 
    { 
     return 'This animal is mute'; 
    } 
} 

?> 
0

ich hatte zu tun, was man in den Fällen beschreiben, wo ich eine kostenlose Version und eine Premium-Version der gleichen Software erhalten.Denn, wie @Gordon erwähnt, können Sie nicht genau dies tun:

class SomeClass { 

    premium_file = "premium.php"; 
    if (file_exists($premium_file)) { 
    require($premium_file); 
    } 

Stattdessen mache ich das:

premium_file = "premium.php"; 
    if (file_exists($premium_file)) { 
    require($premium_file); 
    } 

    class SomeClass { 
    ... 

Für Funktionen, die Sie verweisen möchten, Klassenmethoden in der Hauptklasse zu erstellen, und rufen Sie die Methode der eingeschlossenen Datei, übergeben Sie den Zeiger $this als Parameter. Damit ich auf einen Blick sehen kann, wo Funktionen sind, werde ich den Namen der enthaltenen Funktionen wie folgt voranstellen:

Verwandte Themen