Es muss nicht immer AngularJS sein, um ein einiger Massen automatisches Databinding zu haben. Auch mit jQuery kann sich schnell kleine Lösungen basteln. Hier wir eine Liste von Items aus gegeben (<ul><li>...), die <li>'s sind per Drag and Drop sortiertbar und werden später wieder eingelesen und die Items der Reihenfolge der <li>'s entsprechend sortiert. Das wird schon ganz klassisch über die DOM-Elemente gemacht. Aber ich hatte keine Lust darauf auch die Checkboxen dannausdem <li> über das DOM zusuchen und auszulesen.
Hier zeigen sich die Vorteile von Closures mal wieder. Wenn man eine CheckBox ändert wird sofort über das onChange-Event getriggert auch das Feld des Objekts im Array angepasst. Ohne das Array oder DOM-Elemente durchlaufen zu müssen. Alles ganz automatisch.
//bind checkbox to item.visible of the current item
var func=function(item){
return function(){
item.visible=!item.visible;
}
};
check.change(func(items[j]));
Ich kann immer noch nicht verstehen, wie manche JavaScript-Entwickler ohne Closures auskommen und einige.. wenige.. ok.. einer.. sogar mal meinte Closures bräuchte man überhaupt und man komme immer gut ohne aus.
Meine erste Reallife-Erfahrung mit dem ZF2 und Models war eine eher weniger positive. Das TableGateway braucht unbedingt den Service-Manager bzw den DB-Adapter daraus. Meine Vorgängerin hat sich dazu entschlossen eine Basis-Entität zu bauen, die wiederum von TableGateway ableitet und man so relativ einfach save() und
load()-Methoden in die Model-Klasse einbauen konnte. Der Service-Manager wurde dann durch den Constructor der Model-Klasse durch gereicht bis man den Constructor des TableGateways mit dem DB-Adapter aufrufen konnte. Auch zwischen durch wurde der Service-Manager immer mal benötigt. Weil.. man ohne ihn keine Instanz einer Model-Klasse bekommen konnte.
Um so eine Instanz zu bekommen wurde eine Factory verwendet:
'service_manager' => array(
'factories' => array(
/** Modelle laden */
'sModel' => function($sm) {
$model = new S\Model\S($sm);
return $model;
}
),
/**
* By default, the ServiceManager assumes all services are shared (= single instantiation),
* but you may specify a boolean false value here to indicate a new instance should be returned.
*/
'shared' => array(
'sModel' => false
)
)
Jedes mal aber die Factory zu bemühen eine neue Instanz zu erzeugen ist nicht gerade performant und mit den ganzen Ableitungen ist es auch sehr unübersichtlich. Ich wollte einfach schnell eine Instanz einer Model-Klasse haben und nicht ein riesiges Object bekommen. Also sowas wie in POPO .. eine POJO in PHP eben.
Ein Cosntructor ohne Argumente und eine Klasse nur mit Attributen ohne Logik. Also find ich an mir zu überlegen, ob diese ganzen Ableitungen überhaupt nötig sind oder man mit der Dependency-Injection nicht was viel besseres bauen könnte.
Ich bin dann schnell zu DAOs gwechselt. Die Factory injeziert einmal den Service-Manager und kann immer die selbe Instanz des DAOs liefern. Die DTO/Model-Klasse ist schön klein und beim Befüllen in Schleifen viel schneller als eine Intanz über die Factory anfordern zu müssen.
Meine Lösung ist momentan:
'service_manager' => array(
'factories' => array(
'sDAO' => function($sm) {
return new S\Model\DAO\SDAO($sm);
}
),
)
class SDAO extends TableGateway{
private $_tableName="s";
private $_sm=null;
public function __construct($serviceManager){
$this->_sm=$serviceManager;
parent::__construct(
$this->_tableName,
$serviceManager->get('dbAdapter')
);
}
.........
}
Man kann nun so damit Arbeiten:
echo "name: ".$this->getServiceLocator()->get('sDAO')->loadS($id)->getName();
Das ist eine der Stellen wo Konzepte aus de Java-Welt perfekt mit PHP und dem ZF2 zusammen arbeiten und einen großen Vorteil bringen.
Vor dem Upload ist es oft wünschenwerts ein Bild drehen/rotieren zu können.
Ich hatte mich damals doch sehr damit rumgeärgert, um den richtigen Mittelpunkt bei Rotationen heraus zu bekommen.
Hier ist meine Lösung für Rotationen um 90,180,270 Grad (select oder durch Auf- und Abrunden kann man das sicher stellen,
dass keine anderen Werte eingegeben werden).
var rotate=parseInt(this.rotate);
if(rotate>0){
if(rotate!=180){
ctx.canvas.width=height;
ctx.canvas.height=width;
}
else{
ctx.canvas.width=width;
ctx.canvas.height=height;
}
ctx.save();
ctx.translate(ctx.canvas.width/2,ctx.canvas.height/2);
ctx.rotate(((Math.PI / 180)*rotate));
ctx.drawImage(this.img.image,0-(width/2),0-(height/2),width,height);
ctx.restore();
}
else{
ctx.canvas.width=width;
ctx.canvas.height=height;
ctx.drawImage(this.img.image,0,0,width,height);
}
Gerade beim Laden großer Datenmengen wie Lagerstrukturen oder bei Exporten ganzer Datenbestände, kommt man schnell in Bereiche, wo das Laden und Aufbereiten mehr als ein paar Minuten dauern kann. Bei normalen Desktop-Programmen und Skripten ist das nicht ganz so relevant. Wenn man aber im Web-Bereich arbeitet, kann es schnell zu Problemen mit Timeouts kommen. 3 Minuten können hier schon ein extremes Problem sein. Asynchrone Client helfen hier, aber keiner Wartet gerne und Zeit ist Geld.
Es gibt dann einen Punkt, wo die Zeit pro zu ladenen Element sich nicht mehr weiter verringern lässt. Hier hilft dann nur noch die Verarbeitung der einzelnen Elemente zu parallelisieren. Bei Java gibt es den ExecutorService, in JavaScript die WebWorker und in PHP gibt es pthreads. Es ist nichts für Leute mit einem Shared-Hosted Webspace, weil man eine Extension nach installieren muss.
Installation:
http://php.net/manual/de/pthreads.installation.php
(es sollte die erste DLL reichen)
Hier ist ein kleines Beispiel wo eine Liste von MD5-Hashes erzeugt werden soll. Die Threaded-Variante lief bei mir meistens fast doppelt so schnell
wie die einfache Variante mit der Schleife.
<?php
$files=scandir("c:/xampp/htdocs/files");
$start=microtime();
$cnt=count($files);
$result=array();
for($i=0;$i<$cnt;$i++){
$file=$files[$i];
if($file!="." && $file!=".."){
$result[count($result)]=md5(file_get_contents("c:/xampp/htdocs/files/".$file));
}
}
echo "bench (loop): ".(microtime()-$start)."<br>";
class PWorker extends Collectable{
public $workload;
public function __construct($work){
$this->workload=$work;
}
public function run(){
$this->workload=md5(file_get_contents("c:/xampp/htdocs/files/".$this->workload));
$this->setGarbage();
}
}
$result=array();
$start=microtime();
$p = new Pool(4);
for($i=0;$i<$cnt;$i++){
$file=$files[$i];
if($file!="." && $file!=".."){
$p->submit(new PWorker($file));
}
}
$p->shutdown();
$p->collect(function($checkingTask){
global $result;
$result[count($result)]=$checkingTask->workload;
return $checkingTask->isGarbage();
});
echo "bench (4 threads): ".(microtime()-$start)."<br>";
?>
Man kann also auch in PHP moderne Anwendungen schrieben die Multi-Core CPUs auch wirklich ausnutzen können und muss sich hinter Java in den meisten Bereichen nicht mehr verstecken.