PHP Sammelthread: Zend Framework und alles was dazugehört

Hey Leute mal ne doofe Frage, gibt es eine Komponente im ZF mit der man einfach API Abfragen wie EF oder Werbenetzwerk Interfaces abfragen kann. Ich hab im Manual nix gefunden, allerdings habe ich evtl. in den falschen Komponenten gesucht.

Ich denke nicht, dass so etwas fest implementiert wurde/wird. Jede API arbeitet anders.
Höchstens die Methoden zum Webseiten auslesen kannst du benutzen und dir dann eine eigene Implementation für APIs ähnlich ExportForce oder der Werbenetzwerke schreiben.
 
Ok das habe ich mir schon gedacht, @sebmaster ist das in Deinen Augen wirklich sinnvoll? Sollte man so eine Api nicht abkapseln, und intern wie bissher schreiben? Ich meine wenn die Service Abstract mal geändert wird, muss man dann evtl. alle Schnittstellen anpassen.

Meine Überlegung bissher was es abzukapseln unter Api und dann aufzusplitten in Request_Socket, Request_Fopen sowie die Results in Result_String und Result_Array.
Was meinst Ihr dazu, so kann man alles schon erweitern wenn es notwendig wird und ziehmlich viel ist über ini config steuerbar.
Die einzelnen Schnitstellen erben von Api_Abstract.
 
Hey Leute mal ne doofe Frage, gibt es eine Komponente im ZF mit der man einfach API Abfragen wie EF oder Werbenetzwerk Interfaces abfragen kann. Ich hab im Manual nix gefunden, allerdings habe ich evtl. in den falschen Komponenten gesucht.
Hallo Strolch, ja das gibt es.
Mit Zend_Rest, Zend_Soap und Zend_XmlRpc sind fertige Komponenten drinne, mit denen man mühelos externe Webservices ansprechen kann und das mit nur einer handvoll Zeilen.
Da aber Klamm und die Werbenetzwerke eine Frickel-Hölle sind und keine offenen Standards für Schnitstellen nutzen, sondern lieber ihren dämlichen Frickel-Mist mit Trennzeichen machen :)roll:), musst du selbst Hand anlegen.
Du kannst ja eine Zend_Service_EF-Komponente bauen und auf github legen ;)

Ok das habe ich mir schon gedacht, @sebmaster ist das in Deinen Augen wirklich sinnvoll? Sollte man so eine Api nicht abkapseln, und intern wie bissher schreiben? Ich meine wenn die Service Abstract mal geändert wird, muss man dann evtl. alle Schnittstellen anpassen.
Wie oben gesagt eine eigene Service-Komponente schreiben.

Meine Überlegung bissher was es abzukapseln unter Api und dann aufzusplitten in Request_Socket, Request_Fopen sowie die Results in Result_String und Result_Array.
Was meinst Ihr dazu, so kann man alles schon erweitern wenn es notwendig wird und ziehmlich viel ist über ini config steuerbar.
Die einzelnen Schnitstellen erben von Api_Abstract.
Nicht notwendig ;)
Nimm einfach Zend_Http_Client zum Auslesen der Daten und stell es unter eine objektoriente Zend_Service-Schnittstelle.
Zend_Http hat einen Socket-Adapter der unter jedem PHP läuft.
Ich hatte sowas schonmal aus Spaß angefangen, da ich aber mit EFs nicht viel am Hut lage, auch nach nen paar Stunden wieder sein lassen.
 
Ich habe heute mal 2 ZF-Applikationen zum Schnuppern und Ideen holen ;)

Die Quellen des Dodo App (ToDo-Liste) wurden durch einen Nutzer des Zend Framework Forums recherchiert, womit man es nun wieder downloaden kann.
(ich habe nur kurz einen blick drauf geworfen, sieht nicht schlecht aus)

Aber noch viel besser:
Dasprid, seinerseits Zf-Core-Entwickler, hat eine neue Version seiner Seite veröffentlicht und wie schon das letzte Mal sind die gesammten Daten per SVN einsehbar.
(sieht wirklich gut aus)

Dann viel Spaß und holt euch neue Impressionen, wie man seinen Code verbessern könnte ;)
 
begrüße!

nach ner halben ewigkeit habe ich mein model jetzt mehr oder minder so umgesetzt..
bei meiner umsetzung habe ich mich an dem spindle projekt von matthew auf github orientiert.. habe auch noch einiges geändert und bin mittlerweile tatsächlich einigermaßen zufrieden ;)

ich habe momentan ein problem mit insert operationen über zend_db_table_abstract (bzw einer davon abgeleiteten klasse, versteht sich ;) )

der verständis halber hier ein kleines beispiel.. die tabelle "roles":

name | description | role_id

die insert operation sieht folgendermaßen aus:
PHP:
$data = array('name' => 'foo', 'description' => 'bar');
$insertId = $table->insert($data);

normalerweise funktioniert das wunderbar und ich bekomme als rückgabewert die id des eingefügten datensatzes.. mein problem sind jetzt wieder die sequenzen ;) wenn keine sequenz angegeben ist ($_sequence also wie standardmäßig true ist) dann gibt es keine probleme.. ich hatte aber testweise mal eine sequenz angegeben, weil auch andere dbms außer mysql unterstützt werden sollen..

wenn im $table objekt jetzt also bei $_sequence ein string mit dem sequenznamen steht, dann bekomme ich als rückgabewert in $insertId ein false..
wenn ich in dem $data array noch einen key 'role_id' => '' einfüge, dann bekomme ich als rückgabewert einen leeren string ( string(0) "" ), was ja auch irgendwie logisch ist..
in beiden fällen wird der insert dennoch ausgeführt und steht mit einer passenden auto_increment id in der datenbank..

ist das gewolltes verhalten? ich würde die sequenzen gerne jetzt schon angeben.. sonst muss ich später, wenn ich das script für nen anderes dbms anbieten möchte jede einzelne tabellen klasse nochmal bearbeiten und die sequenz reinschreiben..

ich brauche an der stelle im model den rückgabewert.. wenn ich als rückgabewert von der insert operation false bekomme, dann läuft das script an einer anderen stelle nicht so wie gewünscht (hier ins detail zu gehen ist denke ich überlfüssig..)

ich könnte als eine etwas unschöne lösung natürlich nen try-catch block um die insert operation machen.. und falls keine exception geworfen wird einfach true zurückgeben und nicht wie bisher dirket den rückgabewert von der insert operation.. aber das ist denke ich alles andere als eine ideale lösung.. zumal die id als rückgabewert schon recht hilfreich ist..
 
ist das gewolltes verhalten? ich würde die sequenzen gerne jetzt schon angeben.. sonst muss ich später, wenn ich das script für nen anderes dbms anbieten möchte jede einzelne tabellen klasse nochmal bearbeiten und die sequenz reinschreiben..

niemals jetzt schon etwas implementieren, was man vllt u.U. irgendwann einmal brauchen könnte ;)

Laut Manual kannst du deine Tabelle für IBM DB2 und PostgreSQL deine Datenbank auch so bauen, dass es mit $_sequence = true geht, für die anderen musst du aber scheinbar die Definition anpassen.

Edit: ich habe eben nochmal in den Source geschaut, es gibt keine Möglichkeit beides zugleich zu unterstützen.
 
Zuletzt bearbeitet:
hmm.. finde ich etwas umständlich.. eigentlich müsste ja anhand von dem db adapter unterschieden werden können, ob von dem dbms sequenzen oder eben auto_increment unterstützt werden..

ich glaube ich schreibe die sequenzen jeweils in die tabellen klassen und kommentiere diese dann aus..

danke auf jeden fall für die schnelle antwort ;)

edit: und direkt noch ein anliegen!

wie implementiert ihr weiterleitungsseiten? es wird also ein formular abgeschickt, validiert und dann wird der datensatz geschrieben.. danach soll dann eine meldung kommen: "datensatz erfolgreich geschrieben. sie werden weitergeleitet"

mein erster gedanke war es die variablen $redirectTo, $head und $msg an den view zu übergeben und danach dann einen view rendern, der eben daraus so ne statusseite mit den übergebenen variablen macht.. aber mit der methode müsste ich so eine redirect methode dann für jeden controller implementieren.. das wäre aber wohl zum umständlich..
mit $this->_forward() habe ich das problem mit dem übergeben der parameter..

edit2:
oh.. grade erst gesehen, dass man bei $this->_forward() auch parameter übergeben kann.. dann werde ich es wohl so lösen, dass ich im index controller des default moduls eine redirectAction() mache, welche sich um die weiterleitungen kümmert..

falls jemand alternative vorschläge hat sind die natürlich immer willkommen ;)
 
Zuletzt bearbeitet:
begrüße!

ich mal wieder ;)

wie gesagt habe ich mein model fast fertig umgesetzt.. es gibt value objekte, die jeweils genau einen datensatz repräsentieren (ist das dann ein mapper? das habe ich anscheinend nie so richtig verstanden). dabei gibt es für jede tabelle eine eigene klasse.. damit die value objekte dann auch direkt in die datenbank geschrieben, editiert oder gelöscht werden können sind sie natürlich auch mit einem von Zend_Db_Table_Abstract abgeleiteten objekt verknüpft.. (ich beschränke mich momentan nur auf datenbanken, die infrastruktur für die implementierung anderer backends ist allerdings vorhanden..)

in den jeweiligen value objekten gibt es einen array $allowed, in dem alle erlaubten felder spezifiziert werden. und es gibt noch einen array $protected, in dem felder stehen, die bei update und insert operationen nicht geändert werden dürfen (der klassiker ist das primary feld)..

gibt es irgendwas, das dagegen spricht, den $allowed array von dem Zend_Db_Table objekt zu holen, falls er nicht angegeben wurde? mit $db->describeTable('tabelle'); bekommt man ja im prinzip genau die informationen, die in $allowed stehen sollen.. und den namen der tabelle bekommt man über $table->info('name');
ich erkenne daran keine nachteile, sondern nur den vorteil, dass änderungen an der db direkt ohne refactoring im script übernommen werden und man generell weniger tipparbeit hat.. zumal durch die erweiterung mit dem $protected array auch einschränkungen vorgenommen werden können..

ich frage nach, weil die lösung so offensichtlich ist und mir so gut vorkommt, dass ich mich wundere, warum ich es in keiner umsetzung eines models bisher so gesehen habe und denke mir deswegen, dass ich nen dicken fetten nachteil übersehen haben muss :-? das einzige was mir einfällt ist, dass unter umständen bei nem anderen backend die allowed arrays jeweils neu geschrieben werden müssen.. das ist aber denke ich verkraftbar..
 
auch auf die gefahr hin, dass das hier immer mehr zu nem monolog meinerseits wird.. ich hab mal wieder ein problem ;)
ich bastle grade an einer Tree komponente, die Zend_Db_Table_Abstract um einige funktionen erweitert, um ein nested set damit abbilden und verwalten zu können.. (strolch hatte mal einen blog verlinkt, der ansatz war mir aber nicht flexibel genug.. falls interesse besteht kann ich meinen ansatz (basiert alles auf Zend_Db_Select und es ist möglich für jede art von select extra spalten, where klauseln etc anzugeben) gerne posten..)

ich bastle also einen select: (es geht darum alle childs zu einem knoten auszulesen)
PHP:
$select->from(array('node' => 'process'), array('process_id', 'name', 'lft', 'rgt'))
               ->joinCross(array('parent' => 'process'), array())
               ->where('node.lft BETWEE parent.lft AND parent.rgt')
               ->where($db->quoteInto('parent.process_id = ?', $id, Zend_Db::INT_TYPE))
               ->order('node.lft')
               ;

als query bekomme ich:
Code:
SELECT `node`.`process_id`, `node`.`lft`, `node`.`rgt`, `parent`.*
FROM `process` AS `node`
CROSS JOIN `process` AS `parent` 
WHERE (node.lft BETWEEN parent.lft AND parent.rgt) 
  AND (parent.process_id = 1) 
ORDER BY `node`.`lft` ASC

was mich stört ist das `parent`.* .. damit werden die ergebnisse nämlich versaut.. im result steht nämlich damit immer die process_id des parent knotens.. was dem ganzen irgendwie den sinn raubt..

wie bekomme ich das raus? wenn ich die doku richtig verstanden habe, dann müsste das eigentlich funktionieren, indem ich beim joinCross() als zweiten parameter einen leeren array übergebe.. in der doku steht folgendes:

If you give an empty array as the columns argument, no columns from the respective table are included in the result set. See a code example under the section on the join() method.

aber irgendwas mach ich anscheinend trotzdem falsch.. hat jemand ne ahnung, wie ich diese unschöne wildcard losbekomme?

edit: ich könnte natürlich einfach nen alias für die process_id machen.. also
PHP:
from(array('node' => 'process'), array('node_id' => 'process_id', 'name', 'lft', 'rgt'))
aber das is denke ich nich das wahre..

danke im vorraus,
mfg,
whizzler
 
Zuletzt bearbeitet:
Laut Code jagen die die Cols inner for foreach Schleife nochmal durch nen array_filter wobei vorher auf nen Array geprüft wird, Daher mein Vorschlag einfach NULL übergeben das sollte funktionieren. array_filter entfernt NULL Werte somit sollte die for foreach Schleife nicht durchlaufen werden.

*edit hier nochmal der Durchlauf vom Code:
Code:
Zend_Db_Select Zeile 406
   Zend_Db_Select Zeile 831
      Zend_Db_Select Zeile 901(array Prüfung) 
      Zend_Db_Select Zeile 920 (foreach Schleife)
*Code Tag verwendet für die Einrückung
Btw. Sorry is ne foreach Schleife und keine for, oben ausgebessert.
 
Zuletzt bearbeitet:
och nee.. ich vollidiot.. hab den fehler gefunden.. war nen einfacher syntax fehler.. ich hatte ne klammer falsch gesetzt.. in dem code, den ich hier gepostet habe stimmts.. ich hatte das nochmal neu getippt, weil es bei mir im code wegen variablen, konstanten und co nicht wirklich übersichtlich ist..

danke an strolch für die mühe auf jeden fall! ein leerer array und null führen jeweils zum gleichen ergebnis.. (vorausgesetzt man setzt die klammern richtig ;) )
 
Ich hab grad nen ganz schönen Hals über Zend_Form. Wieso können die da nichtmal was einheitlich lösen? :roll:

Also ich hab meine Decorators so angepasst, dass die Element von nem Div umgeben werden.

PHP:
array(
            'Label',
            'ViewHelper',
            array('HtmlTag', array('tag' => 'div'))
);

Bei Text-Elementen ist das Label in dem Div. Bei Checkboxen oder Select-Boxen steht der Label aber außerhalb. Wieso?! :evil:
PHP:
<div>
<label for="description" class="optional">Beschreibung</label><textarea name="description" id="description" class="inputText" rows="10" cols="80">test</textarea></div>
vs.
PHP:
<label for="title" class="required">Anrede *</label>
<div class="row-start">
<select name="title" id="title">
<option value="Herr" label="Herr">Herr</option>
<option value="Frau" label="Frau">Frau</option>
</select>
</div>

Seh ich grad den Sinn dahinter nicht, oder wieso machen die das nicht einheitlich? :-?
 
Neija es gibt ja nen HTML-Tag für den ganzen Block und einen HTML-Tag für die Gruppierung der einzelnen Werte.
Solange du nicht sagst auf welches Objekt du diese Decorator-Regeln angewendet hast, können wir dir da auch nicht helfen.

Edit: Das Label-Placement wird wahrscheinlich der Auslöser sein ;)
 
Solange du nicht sagst auf welches Objekt du diese Decorator-Regeln angewendet hast, können wir dir da auch nicht helfen.
Auf beide, die ich genannt habe. Und dennoch ist es ein unterschiedliches Verhalten 8O

Edit: Das Label-Placement wird wahrscheinlich der Auslöser sein ;)
Da gibt es doch nur prepend und append oder? Wieso ist es dann im div? Ich hab da nichts gesetzt.

EDIT: *benutze Kopf mit Wand* ich hab addDecorator statt setDecorator genutzt -.-
Jetzt passt es.
 
Ich will dann auch mal ein wenig hier rumfragen..
Folgendes Problem: Ich versuche ein Translationsystem mit dem ZendFramework umzusetzen. Allerdings scheitere ich daran, dass die aktuelle Sprache erst viel zu spät bekannt wird im Script.
Also einmal möchte ich ganz normal per Standardrouter eine Standardsprache haben, dazu dann noch die Möglichkeit über einen "Ordner" nach dem Namen der Sprache, dass diese ausgewählt wird. Also z.B. /de/foo/bar soll foo als Controller nehmen, bar als Action und dazu dann alles in Deutsch darstellen.

Bei mir sehe ich nun aber erst die Texte in der jeweiligen Sprache, wenn diese in der Templatedatei über den Viewhelper ausgegeben werden.
Also ein Problem bei folgendem: Ich habe für die Breadcrumbs mehrere Instanzen der Zend_Navigation_Page_Mvc Klasse und lasse über die Option params die Sprache übergeben, damit diese richtig beim Link genutzt wird.

Wüsste da jemand Abhilfe?
Ich hatte schon überlegt die aktuelle Sprache in einen Cookie zu speichern, dieser ist ja schon direkt beim Laden der Resources verfügbar.. Aber die Methode hört sich sehr "dreckig" an (zumal Cookies nicht immer verfügbar sind). Mit dem Request-Objekt kann ich in den Resources ja noch nicht so viel machen.. Oder ich lese eigenständig noch mal über Standard-PHP Funktionen aus in welchen Sprachordner ich bin!? Hmm..
Danke!
 
Die Sprache sucht sich Zend_Translate doch selber du musst dir nur eine _init in der Bootstrap schreiben oder eben ein Plugin mit routeShutdown und Zend_Translate die Param geben. Den Rest macht Zend_Translate meines Wissens selbst.
 
Die Sprache sucht sich Zend_Translate doch selber du musst dir nur eine _init in der Bootstrap schreiben oder eben ein Plugin mit routeShutdown und Zend_Translate die Param geben. Den Rest macht Zend_Translate meines Wissens selbst.

Zend_Translate kann sich durch Zend_Locale die Sprache selber suchen, ja. Aber ich möchte entweder (alles über Config regelbar) eine Standardsprache wenn kein "Sprachordner" benutzt wird, eine automatisch erkannte Sprache (also über Zend_Locale dann eigentl.) oder nun mal die Sprache vom aktuellen "Sprachordner".
Und da Zend_Translate das alles nicht automatisch macht (besonders die Geschichte mit dem Ordner, eigentlich ist genau das, dass was die Probleme bereitet) verusch ich mich hier selber dran. ;)
 
Also das habe ich nun alles soweit hinbekommen. Wichtig war ein Zend_Controller_Router_Route::setDefaultTranslator($this->_translate); ;)

Aber nächste Problem.. Bzw. kann ich mir vorstellen, dass das ZendFramework da etwas falsch macht. Ich habe die Version 1.10.2 und wenn ich im ActionController auf den Router zugreife und mir mittels getParams() die Parameter ausgebe, sehe ich nur meinen eigenständig gesetzten language-Parameter. module, controller und action-Parameter gibt es einfach nicht... Aufgerufen habe ich das Rootverzeichnis / über den Browser. Sollte ich /index/index oder so aufrufen, gibt es controller und action-Parameter :/

Könnte es am ZendFramework selber liegen? Oder hat es eventuell etwas mit meinen Routen zu tun?

PHP:
$routeLanguage = new Zend_Controller_Router_Route(
    ':language',
    array(
        'language' => false
    ),
    array(
        'language' => '(de|en)'
    )
);
$routeModule = new Zend_Controller_Router_Route_Module(
    array(),
    Zend_Controller_Front::getInstance()->getDispatcher(),
    Zend_Controller_Front::getInstance()->getRequest()
);

Zend_Controller_Front::getInstance()->getRouter()->addRoute('module', $routeModule);
Zend_Controller_Front::getInstance()->getRouter()->addRoute('language', $routeLanguage);
Zend_Controller_Front::getInstance()->getRouter()->addRoute('default', $routeLanguage->chain($routeModule));

Danke euch! :)
 
Dass die Route dir dann keine Params zurückgibt kann ich mir durchaus vorstellen, schließlich wurden sie ja auch nicht übergeben.

Hast du schon $this->getRequest()->getParams() probiert?

Bin mir jetzt nicht sicher, ob das das richtige ist.