php.de

Zurück   php.de > Webentwicklung > PHP-Fortgeschrittene

PHP-Fortgeschrittene Arbeiten mit PHP ohne Einschränkungen

Antwort
 
LinkBack Themen-Optionen Thema bewerten
Alt 12.09.2011, 21:58  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.268
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard MeineKlassenListe<KlassenName>()

Hallo,

ich hab mal wieder ein kleines schönes Standardprojekt. Neues sauberes Datenbankmodell mit überschaubaren ~10 Entitäten plus Beziehungen untereinander.

Ich ziehe das ganze mit dem Zend Framework auf und mache es immer so, dass ich mir selbst OR-Mapper schreibe:

datenbank.tabelle (mit z.B. id, name, ..)
class Tabelle {
setId(), getId(),
setName(), getName(),
fromArray(), toArray()
}
class Tabelle_List extends ArrayObject (bildet einen Array dieser Objekte ab)
class Tabelle_Model_Abstract
class Tabelle_Model_Database
class Tabelle_Model_Interface
class Tabelle_Form_Add extends Zend_Form
class Tabelle_Form_Edit extends Tabelle_Form_Add

(mal etwas vereinfacht)
Jetzt geht mir die blöde Tipperei auf die Nerven, das für alle 10 Entitäten zu erstellen, da eigentlich alle dasselbe machen (und jetzt schon dabei bin, Code zu kopieren und Namen zu ersetzen). Ich möchte aber keine generischen Objekte ala
$abstract->setProperty("id", $id)
weil ich dieses total generische schwer zu debuggen finde und ein Workaround für Ausnahmen schlecht einzufügen ist (overwrite setProperty mit switch-case). Ein Freund magischer Methoden bin ich auch nicht, da machen die wenigsten Auto-Complete-Funktionen der IDEs nicht mit, es Performance-Vorbehalte gibt und es außerdem vielleicht deprecated in PHP 6 ist, wer weiß.

Einen Generator anwerfen finde ich auch doof, weil ich nämlich einen selber schreiben müsste und bei meinen Ansprüchen dauert das wieder ne Woche.

Jetzt kam mir gerade diese blöde aber ziemlich fix funktionierende Lösung:
PHP-Code:
<?php
abstract class ObjectList
{
    public static function 
build($class)
    {
        if (!
class_exists($class)) {
            throw new 
Exception("class [$class] not found");
        }
        
$listClass $class "List";
        if (
class_exists($listClassfalse)) {
            return new 
$listClass();
        }
        
$php self::_generateListClass($listClass$class);
        
$tempFile tempnam(sys_get_temp_dir(), "php");
        
file_put_contents($tempFile$php);
        include 
$tempFile;
        
unlink($tempFile);
        return new 
$listClass;
    }
    
    protected static function 
_generateListClass($listClass$singleClass)
    {
        
// nowdoc syntax:
        
$php = <<<'PHP_CLASS_DECLARATION'
<?php
class %__listClass__% extends ArrayObject
{
    public function 
offsetSet($offset$element)
    {
        if (!
$element instanceof %__singleClass__%) {
            
$type gettype($element);
            if (
$type === "object") {
                
$type .= "::" get_class($element);
            }
            throw new 
InvalidArgumentException("invalid element provided [$type], must be an instance of %__singleClass__%");
        }
        if (!(
$offset === null || (ctype_digit((string)$offset) && $offset >= 0))) {
            throw new 
InvalidArgumentException("invalid element offset provided, must be NULL or unsigned integer");
        }
        return 
parent::offsetSet($offset$element);
    }
    
    public function 
append($element)
    {
        return 
$this->offsetSet(null$element);
    }
}

PHP_CLASS_DECLARATION;
        
$php strtr($php, array(
            
"%__listClass__%" => $listClass,
            
"%__singleClass__%" => $singleClass
        
));
        return 
$php;
    }
}

class 
Test
{
  public function 
getName() {
    return 
spl_object_hash($this);
  }
}

class 
NotTest
{
    
}

$testList ObjectList::build("Test");
$testList ObjectList::build("Test");
$testList[] = new Test();
$testList[] = new Test();
foreach (
$testList as $test) {
  echo 
$test->getName(), "<br />";
}

$testList[] = new NotTest(); // Exception
Irgendwie auch nicht so das wahre, aber es funktioniert. Ich weiß, ich sollte den Skill haben zu wissen, dass das Code auf eval()-Niveau ist. Zugegeben es ist auch nur das Ziel erreicht, dass ich Tabelle_List erstellt habe und damit sicherstelle, dass in Tabelle_List auch nur Objekte vom Typ Tabelle stehen habe. Aber immerhin. Wie gesagt, ich könnte auch 10x (oder bei anderen Projekte 50x) eine <Datenbanktabelle>_List erstellen, aber es ärgert mich irgendwie, dass es kein MeineKlasse<Klasse>() Konstrukte wie in Java gibt und ich würde das gerne nachbauen.

Gibt es denn eine PHP-Extension, die soetwas wie MeineKlassenListe<KlassenName>() unterstützt?

Wie macht ihr das, wenn ihr soviel Gleiches zu tun habt, Doctrine benutzen?
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Alt 12.09.2011, 22:30  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 2.308
PHP-Kenntnisse:
Fortgeschritten
fab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblick
Standard

Zitat:
Einen Generator anwerfen finde ich auch doof, weil ich nämlich einen selber schreiben müsste und bei meinen Ansprüchen dauert das wieder ne Woche.
Naja, im Prinzip hast du damit doch genau das gemacht, einen Generator geschrieben. Auch wenn der on-the-fly arbeitet und die Datei direkt wieder löscht (warum eigentlich? Wäre doch nett, das zumindest zu cachen). Was ich bisher an Lösungen für Generics in PHP gesehen habe, läuft auch alles auf das selbe Prinzip hinaus.

Was ich gerne mal mache, wenn ich viele Klassen mit gleichartigem Boilerplate Code brauche, der sich nicht vermeiden lässt, ist Generierung mittels Ant-Skript: Ich erstelle eine Template-Datei und ein dynamisches Filterset, fertig ist der Generator.

Ein Beispiel, gekürzt:

Klassen-Template:
PHP-Code:
class {vendor}_{extension}_Model_Entity_{model}_Collection
    
extends Mage_Core_Model_Mysql4_Collection_Abstract
{
    
/**
     * standard collection feature
     * 
     * @param {vendor}_{extension}_Model_{model} ${model_l}
     * @param boolean $strict true for a strict comparison (same object), false
     *  for a by-attribute comparison. Defaults to true
     * @return boolean
     */
    
public function contains(
        {
vendor}_{extension}_Model_{model} ${model_l}, $strict true)
    {
        foreach (
$this->getIterator() as $item) {
            if (
$strict
                
? ($item === ${model_l})
                : (
$item->getData() == ${model_l}->getData())
            ) {
                return 
true;
            }
        }
        return 
false;
    }
    
// ...

Ant-Code:
Code:
    <target name="create-model-collection" depends="define-properties" if="model-name">
        <stringutil string="${model-name}" property="model-path">
            <replace regex="_" replacement="/"></replace>
        </stringutil>
        <copy tofile="${extension-code-dir}/Model/Entity/${model-path}/Collection.php" file="template/classes/Collection.php">
            <filterset refid="template-filter" />
        </copy>
    </target>

    <target name="define-properties" if="extension-name">
        <!-- ... -->
        <stringutil string="${model-name}" property="model-lc">
            <lowercase/>
        </stringutil>
        <filterset id="template-filter" begintoken="{" endtoken="}">
            <filter token="vendor" value="${extension-vendor}" />
            <filter token="extension" value="${extension-name}" />
            <filter token="model" value="${model-name}" />
            <filter token="model_l" value="${model-lc}" />
            <!-- ... -->
        </filterset>
    </target>
Die Properties ergeben sich teilweise aus der Konfiguration, teilweise aus Runtime-Parametern, und werden von verschiedenen Klassengeneratoren gemeinsam genutzt.
fab ist offline   Mit Zitat antworten
Alt 12.09.2011, 22:46  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.268
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Hm mit Ant ist natürlich auch ne tolle Idee, genauso wenig bin ich auf Templates gekommen (warum eigentlich? - ist ja naheligend).

Was ich ja super genial fände, wenn endlich Traits kämen. die könnte ich gerade gut gebrauchen. Wobei ich grade 10 RFCs offen habe, die - unabhängig von der Problematik hier im Thread - echt interessant klingen.

Ich glaube ich nehme deinen Vorschlag mit Templates mal auf. Abgesehen davon ist mir aufgefallen, dass ich ja nur eine Datei ObjectList bräuchte, die die Implementierung oben beinhaltet. Irgendwie zu verquer gedacht mal wieder.

Edit: Ich könnte ja für die Templates schonmal Trait-Syntax verwenden ..
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Alt 13.09.2011, 07:07  
Erfahrener Benutzer
 
Registriert seit: 21.12.2004
Beiträge: 5.235
PHP-Kenntnisse:
Fortgeschritten
mepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblick
mepeisen eine Nachricht über ICQ schicken mepeisen eine Nachricht über Skype™ schicken
Standard

Die Traits sind längst da
http://www.php.net/archive/2011.php#id2011-06-28-1
gut, alpha, aber immerhin.
__________________
www.php-maven.org PHP und Maven vereint: Build/Deploy/Produktion/Konfiguration, Projekt Management, CI, PHPUnit, zahlreiche Frameworks
Twitter @ https://twitter.com/#!/mepeisen und Facebook @ http://t.co/DZnKSUih
mepeisen ist gerade online   Mit Zitat antworten
Alt 13.09.2011, 09:06  
fab
Erfahrener Benutzer
 
Benutzerbild von fab
 
Registriert seit: 28.07.2010
Beiträge: 2.308
PHP-Kenntnisse:
Fortgeschritten
fab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblickfab ist ein Lichtblick
Standard

Traits erlauben nur leider keine Platzhalter in der Form.
fab ist offline   Mit Zitat antworten
Alt 19.09.2011, 19:46  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

... dann sollte sich endlich jemand Generics für PHP wünschen!
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 19.09.2011, 20:07  
Moderator
 
Benutzerbild von Chriz
 
Registriert seit: 11.05.2008
Beiträge: 6.268
Chriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer AnblickChriz ist ein wunderbarer Anblick
Standard

Ich hab da zuwenig Grundkenntnisse in dem Bereich, mach du doch mal?!
__________________
"Nuschel ich?" - "Was?"
Chriz ist offline   Mit Zitat antworten
Alt 19.09.2011, 22:26  
Erfahrener Benutzer
 
Registriert seit: 21.12.2004
Beiträge: 5.235
PHP-Kenntnisse:
Fortgeschritten
mepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblickmepeisen ist ein wunderbarer Anblick
mepeisen eine Nachricht über ICQ schicken mepeisen eine Nachricht über Skype™ schicken
Standard

Bitte nicht
__________________
www.php-maven.org PHP und Maven vereint: Build/Deploy/Produktion/Konfiguration, Projekt Management, CI, PHPUnit, zahlreiche Frameworks
Twitter @ https://twitter.com/#!/mepeisen und Facebook @ http://t.co/DZnKSUih
mepeisen ist gerade online   Mit Zitat antworten
Alt 19.09.2011, 22:39  
Moderator und Wett-König
 
Benutzerbild von dr.e.
 
Registriert seit: 21.05.2008
Beiträge: 3.657
PHP-Kenntnisse:
Fortgeschritten
dr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblickdr.e. ist ein Lichtblick
dr.e. eine Nachricht über Skype™ schicken
Standard

Warum denn nicht? Ein

PHP-Code:
$foo = new ArrayList<User>(); 
wäre hinsichtlich der Typensicherheit schon nicht das schlechteste. Was aber viel dringender - aber auch in diesem Zusammenhang - schön wäre ist die Deklaration von Rückgabe-Werten. Hast du eine Methode Group::getUsers(), so könnte diese "in schön" vielleicht bald so aussehen:

PHP-Code:
class Group {

   public function List<
UsergetUsers(){
   }


Sofern das die IDEs noch entsprechend unterstützen, braucht es zukünftig keine expliziten Type-Hints mehr. Für mich eine echte Erleichterung, denn die bisherige Typ-Deklaration von Typen wie "array" ist nicht wirklich schön.
__________________
Viele Grüße,
Dr.E.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Think about software design before you start to write code!
2. Discuss and review it together with experts!
3. Choose good tools (-> Adventure PHP Framework (APF))!
4. Write clean and reusable software only!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dr.e. ist offline   Mit Zitat antworten
Alt 19.09.2011, 23:14  
Erfahrener Benutzer
 
Benutzerbild von tr0y
 
Registriert seit: 26.07.2010
Beiträge: 4.874
PHP-Kenntnisse:
Fortgeschritten
tr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblicktr0y ist ein wunderbarer Anblick
tr0y eine Nachricht über MSN schicken
Standard

ich wär da mehr für sowas:

PHP-Code:
class Group {


   ( boolean ) function 
Method() {

   }


alternativ:

PHP-Code:
prototype pGroup {
   function 
Method() as boolean;
}

class 
Group satisfy pGroup {

   function 
Method() {

   }


Wenn wir schon mal beim Wünschen wären, würde ich gerne zusätzlich zum Type-hinting, Type-autocasting machne dürfen:
PHP-Code:
class Group {

   function 
Method( (string) existingClass $arg1 ) {

   }


alternativ:

PHP-Code:
prototype pGroup {
   function 
Methodstring $arg1 );

i-win-situation:

PHP-Code:
prototype pGroup {
   function 
Methodstring $arg1 ) as boolean;
}

class 
Group
   satisfy pGroup
   
implements iGroupCountable
{

   function 
MethodexistingClass $arg1 ) {

   }


Coming soon, PHP 7.. or later
__________________
Lasse mir ohne Anwendung von Gewalt Dinge schenken, Amazon weiß darüber bald mehr.
tr0y ist gerade online   Mit Zitat antworten
Antwort


Themen-Optionen
Thema bewerten
Thema bewerten:

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are an
Gehe zu

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
classenbezeichnung php, php public function in abstract class not found, function filter list() php code

Alle Zeitangaben in WEZ +2. Es ist jetzt 01:07 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum