tag:forum.selfhtml.org,2005:/self
Lese ich das richtig? PHP-Objekte ähnlich flexibel wie in JS? – SELFHTML-Forum
2009-07-01T21:06:08Z
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376592#m1376592
Felix Riesterer
Felix.Riesterer@gmx.net
http://www.felix-riesterer.de/
2009-06-30T21:13:29Z
2009-06-30T21:13:29Z
Lese ich das richtig? PHP-Objekte ähnlich flexibel wie in JS?
<p>Liebe Fachleute,</p>
<p>heute las ich auf <a href="http://www.heise.de/newsticker/PHP-5-3-mit-vielen-neuen-Funktionen--/meldung/141269" rel="nofollow noopener noreferrer">heise.de über PHP5.3</a> und die darin enthaltenen neuen Features, darunter z.B. Closures und anonyme Funktionen usw. Bedeutet das, dass man in PHP5.3 ähnlich wie in JavaScript Objekte zur Laufzeit erweitern und verändern kann? Im von mir bisher begriffenen Klassen-basierten System (ich stehe in etwa auf dem Stand von PHP4.4 was OO in PHP angeht) war das so nicht möglich, jedenfalls nicht so dynamisch...</p>
<p>Liebe Grüße,</p>
<p>Felix Riesterer.</p>
<div class="signature">-- <br>
ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
</div>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376594#m1376594
Christian Seiler
self@christian-seiler.de
http://www.christian-seiler.de/projekte/xslt-json/
2009-06-30T21:46:36Z
2009-06-30T21:46:36Z
Lese ich das richtig? PHP-Objekte ähnlich flexibel wie in JS?
<p>Hallo Felix,</p>
<blockquote>
<p>heute las ich auf <a href="http://www.heise.de/newsticker/PHP-5-3-mit-vielen-neuen-Funktionen--/meldung/141269" rel="nofollow noopener noreferrer">heise.de über PHP5.3</a> und die darin enthaltenen neuen Features, darunter z.B. Closures und anonyme Funktionen usw. Bedeutet das, dass man in PHP5.3 ähnlich wie in JavaScript Objekte zur Laufzeit erweitern und verändern kann?</p>
</blockquote>
<p>Jain. Um mal etwas aus der internen Perspektive zu erzählen (ich war an der Implementierung von Closures in PHP beteiligt): Es gab ziemlich viele Diskussionen auf der PHP-Mailingliste, wie man Closures dazu verwenden kann, um Objekte zu erweitern. Es wurde aber festgestellt, dass dies zu vielen Problemen führt, wenn man das mit anderen PHP-OOP-Semantiken verbindet (Visibility wie private/protected/public was es in JS so direkt nicht gibt sondern nur über Closures emuliert, andere Namensräume für Variablen und Methoden in Objekten, etc.). Die verschiedenen Ansätze, die es gab, hatte ich vor langer Zeit mal in <a href="http://wiki.php.net/rfc/closures/object-extension" rel="nofollow noopener noreferrer">http://wiki.php.net/rfc/closures/object-extension</a> zusammengefasst. Nachdem auf der PHP-Mailingliste aber kein Konsens entstehen konnte, welchen Weg man wählen will, wurde entschieden, dass Closures gar keinen Zugriff auf $this haben, damit man das zu einem späteren Zeitpunkt noch nachrüsten kann (<a href="http://wiki.php.net/rfc/closures/removal-of-this" rel="nofollow noopener noreferrer">http://wiki.php.net/rfc/closures/removal-of-this</a>).</p>
<p>Allerdings: Es gibt bestimmte Dinge, die Du bereits jetzt machen kannst:</p>
<p>Python-artige Variante mit $self als ersten Parameter:</p>
<pre><code class="block language-php"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MeineKlasse</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token variable">$begruessung</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Hallo'</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__call</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">array_unshift</span> <span class="token punctuation">(</span><span class="token variable">$args</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token function">call_user_func_array</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token variable">$objekt</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MeineKlasse</span><span class="token punctuation">;</span>
<span class="token variable">$objekt</span><span class="token operator">-></span><span class="token property">hallo</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$self</span><span class="token punctuation">,</span> <span class="token variable">$wer</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token variable">$self</span><span class="token operator">-></span><span class="token property">begruessung</span><span class="token operator">.</span><span class="token string double-quoted-string">" "</span><span class="token operator">.</span><span class="token variable">$wer</span><span class="token operator">.</span><span class="token string double-quoted-string">"!\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token variable">$objekt</span><span class="token operator">-></span><span class="token function">hallo</span> <span class="token punctuation">(</span><span class="token string single-quoted-string">'Welt'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>Objekt als Closure-Variable:</p>
<pre><code class="block language-php"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MeineKlasse</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token variable">$begruessung</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Hallo'</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__call</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">call_user_func_array</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token variable">$objekt</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MeineKlasse</span><span class="token punctuation">;</span>
<span class="token variable">$objekt</span><span class="token operator">-></span><span class="token property">hallo</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$wer</span><span class="token punctuation">)</span> <span class="token keyword">use</span> <span class="token punctuation">(</span><span class="token variable">$objekt</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token variable">$objekt</span><span class="token operator">-></span><span class="token property">begruessung</span><span class="token operator">.</span><span class="token string double-quoted-string">" "</span><span class="token operator">.</span><span class="token variable">$wer</span><span class="token operator">.</span><span class="token string double-quoted-string">"!\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token variable">$objekt</span><span class="token operator">-></span><span class="token function">hallo</span> <span class="token punctuation">(</span><span class="token string single-quoted-string">'Welt'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
<p>Allerdings: In den so erweiterten Methoden hast Du nur Zugriff auf die Variablen/Methoden des Objekts, die public sind. Auf private/protected kannst Du so nicht zugreifen. Aber Du kannst mit dieser Logik PHP-Objekte, deren Klasse es über __call zulässt selbst beliebig erweitern mit Closures - so ähnlich wie Javascript.</p>
<p>Viele Grüße,<br>
Christian</p>
<div class="signature">-- <br>
<a href="http://del.icio.us/chris_se/servertipps" rel="nofollow noopener noreferrer">Mein "Weblog"</a> [<a href="http://del.icio.us/rss/chris_se/servertipps" rel="nofollow noopener noreferrer">RSS</a>]<br>
<a href="http://www.christian-seiler.de/projekte/xslt-json/" rel="nofollow noopener noreferrer">Using XSLT to create JSON output</a> (Saxon-B 9.0 for Java)<br>
»I don't believe you can call yourself a web developer until you've built an app that uses hyperlinks for deletion and have all your data deleted by a search bot.«<br>
-- <a href="http://thedailywtf.com/Comments/WellIntentioned-Destruction.aspx#254549" rel="nofollow noopener noreferrer">Kommentar bei TDWTF</a>
</div>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376593#m1376593
Sven Rautenberg
http://www.rtbg.de
2009-06-30T21:51:25Z
2009-06-30T21:51:25Z
Lese ich das richtig? PHP-Objekte ähnlich flexibel wie in JS?
<p>Moin!</p>
<blockquote>
<p>heute las ich auf <a href="http://www.heise.de/newsticker/PHP-5-3-mit-vielen-neuen-Funktionen--/meldung/141269" rel="nofollow noopener noreferrer">heise.de über PHP5.3</a> und die darin enthaltenen neuen Features, darunter z.B. Closures und anonyme Funktionen usw. Bedeutet das, dass man in PHP5.3 ähnlich wie in JavaScript Objekte zur Laufzeit erweitern und verändern kann?</p>
</blockquote>
<p>Nein, bedeutet es nicht.</p>
<p>Das prototypische Objektmodell von Javascript hat mit dem Klassen- und Objektmodell von PHP nicht viel zu tun. Und abgesehen von der Tatsache, dass sich seit PHP 4 objektmäßig vom Prinzip her nicht viel verändert hat, könnte man sich natürlich schon immer Dynamik hinprogrammieren, wenn man sie wirklich braucht.</p>
<p>- Sven Rautenberg</p>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376595#m1376595
Christian Seiler
self@christian-seiler.de
http://www.christian-seiler.de/projekte/xslt-json/
2009-06-30T22:22:16Z
2009-06-30T22:22:16Z
Lese ich das richtig? PHP-Objekte ähnlich flexibel wie in JS?
<p>Hallo nochmal,</p>
<p>Ich hab übrigens mal was schnell zusammengehackt, was vielleicht das Leben erleichtert. Ich behaupte nicht, dass es perfekt ist, man kann da sicher noch einige Dinge tweaken, aber es ist vielleicht ganz nett:</p>
<pre><code class="block language-php"><span class="token comment">//////////////////////////////////////////////////////////////////// </span>
<span class="token comment">// BASISCODE, DER NICHT GEAENDERT WERDEN MUSS </span>
<span class="token comment">//////////////////////////////////////////////////////////////////// </span>
<span class="token keyword">class</span> <span class="token class-name-definition class-name">ExtensibleObject</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token variable">$prototypeMethods</span> <span class="token operator">=</span> <span class="token keyword">array</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__call</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$class</span> <span class="token operator">=</span> <span class="token function">get_class</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BadMethodCallException</span> <span class="token punctuation">(</span><span class="token string double-quoted-string">"Method <span class="token interpolation"><span class="token variable">$class</span></span>::<span class="token interpolation"><span class="token variable">$method</span></span> does not exist"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token variable">$method</span> <span class="token operator">=</span> <span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token variable">$method</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token variable">$method</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token variable">$p</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReflectionParameter</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$p</span><span class="token operator">-></span><span class="token function">getName</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token string single-quoted-string">'self'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Python-Style convention: First parameter is named $self </span>
<span class="token function">array_unshift</span> <span class="token punctuation">(</span><span class="token variable">$args</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ReflectionException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ignore (parameter count < 0) </span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">call_user_func_array</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">__callStatic</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$class</span> <span class="token operator">=</span> <span class="token function">get_called_class</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token operator">-></span><span class="token variable">$name</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BadMethodCallException</span> <span class="token punctuation">(</span><span class="token string double-quoted-string">"Method <span class="token interpolation"><span class="token variable">$class</span></span>::<span class="token interpolation"><span class="token variable">$name</span></span> does not exist"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token variable">$method</span> <span class="token operator">=</span> <span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token operator">-></span><span class="token variable">$name</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token variable">$p</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReflectionParameter</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$p</span><span class="token operator">-></span><span class="token function">getName</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token string single-quoted-string">'self'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Python-Style convention: First parameter is named $self </span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">BadMethodCallException</span> <span class="token punctuation">(</span><span class="token string double-quoted-string">"Non-static method <span class="token interpolation"><span class="token variable">$class</span></span>::<span class="token interpolation"><span class="token variable">$name</span></span> may not be called statically"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ReflectionException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ignore (parameter count < 0) </span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">call_user_func_array</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__get</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$name</span> <span class="token operator">==</span> <span class="token string single-quoted-string">'prototype'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword static-context">static</span><span class="token operator">::</span><span class="token function">prototype</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token variable">$class</span> <span class="token operator">=</span> <span class="token function">get_class</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">RuntimeException</span> <span class="token punctuation">(</span><span class="token string double-quoted-string">"Attribute <span class="token interpolation"><span class="token variable">$class</span></span>::<span class="token interpolation"><span class="token variable">$name</span></span> does not exist"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">prototype</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$class</span> <span class="token operator">=</span> <span class="token function">get_called_class</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">isset</span> <span class="token punctuation">(</span><span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">stdClass</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token keyword static-context">self</span><span class="token operator">::</span><span class="token variable">$prototypeMethods</span><span class="token punctuation">[</span><span class="token variable">$class</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">//////////////////////////////////////////////////////////////////// </span>
<span class="token comment">// ENDE </span>
<span class="token comment">//////////////////////////////////////////////////////////////////// </span>
<span class="token comment">// Abgeleitete Klasse </span>
<span class="token keyword">class</span> <span class="token class-name-definition class-name">MyObject</span> <span class="token keyword">extends</span> <span class="token class-name">ExtensibleObject</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token variable">$welt</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'Welt'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Etwas prototypisches Zeugs </span>
<span class="token variable">$obj1</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MyObject</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token property">prototype</span><span class="token operator">-></span><span class="token property">hallo</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Hallo "</span><span class="token operator">.</span><span class="token variable">$self</span><span class="token operator">-></span><span class="token property">welt</span><span class="token operator">.</span><span class="token string double-quoted-string">"\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token class-name static-context">MyObject</span><span class="token operator">::</span><span class="token function">prototype</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token property">ciao</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token variable">$self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Ciao "</span><span class="token operator">.</span><span class="token variable">$self</span><span class="token operator">-></span><span class="token property">welt</span><span class="token operator">.</span><span class="token string double-quoted-string">"\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token property">prototype</span><span class="token operator">-></span><span class="token property">tag</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Guten Tag!\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token property">nacht</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Gute Nacht!\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token variable">$obj2</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MyObject</span><span class="token punctuation">;</span>
<span class="token variable">$obj2</span><span class="token operator">-></span><span class="token property">welt</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'kleine Welt'</span><span class="token punctuation">;</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Hallo:\n===============\n"</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token function">hallo</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$obj2</span><span class="token operator">-></span><span class="token function">hallo</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"\nCiao:\n===============\n"</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token function">ciao</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$obj2</span><span class="token operator">-></span><span class="token function">ciao</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"\nTag:\n===============\n"</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token function">tag</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$obj2</span><span class="token operator">-></span><span class="token function">tag</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"\nNacht:\n===============\n"</span><span class="token punctuation">;</span>
<span class="token variable">$obj1</span><span class="token operator">-></span><span class="token function">nacht</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token variable">$obj2</span><span class="token operator">-></span><span class="token function">nacht</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Exception: "</span><span class="token operator">.</span> <span class="token variable">$e</span><span class="token operator">-></span><span class="token function">getMessage</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span><span class="token string double-quoted-string">"\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"\nTag (static):\n===============\n"</span><span class="token punctuation">;</span>
<span class="token class-name static-context">MyObject</span><span class="token operator">::</span><span class="token function">tag</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"\nHallo (static):\n===============\n"</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token class-name static-context">MyObject</span><span class="token operator">::</span><span class="token function">hallo</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Exception</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">echo</span> <span class="token string double-quoted-string">"Exception: "</span><span class="token operator">.</span> <span class="token variable">$e</span><span class="token operator">-></span><span class="token function">getMessage</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span><span class="token string double-quoted-string">"\n"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
<p>Die Ausgabe bei PHP 5.3 wäre folgende:</p>
<h3>Hallo:</h3><p>Hallo Welt<br>
Hallo kleine Welt</p>
<h3>Ciao:</h3><p>Ciao Welt<br>
Ciao kleine Welt</p>
<h3>Tag:</h3><p>Guten Tag!<br>
Guten Tag!</p>
<h3>Nacht:</h3><p>Gute Nacht!<br>
Exception: Method MyObject::nacht does not exist</p>
<h3>Tag (static):</h3><p>Guten Tag!</p>
<h3>Hallo (static):</h3><p>Exception: Non-static method MyObject::hallo may not be called statically</p>
<p>Das ganze kombiniert hier schön Late Static Bindings (get_called_class (), static::) mit Closures und __call/__callStatic-Logik und demonstriert damit einige der neuen Features von PHP 5.3. Ich hoffe, der Code erklärt sich selbst. Was es noch nicht kann, was man aber sicher leicht hinzufügen könnte, wäre $x->prototype = $y->prototype (bzw. für den statischen Fall Class2::setPrototype (Class1::prototype ())) mit spezieller Klasse ExtensibleObjektPrototype für Type-Hints. Vielleicht hacke ich das bei Gelegenheit auch noch zusammen.</p>
<p>Achja, falls man __get/__call in eigenen Klassen überschreibt, sollte das so aussehen:</p>
<pre><code class="block language-php"><span class="token keyword">class</span> <span class="token class-name-definition class-name">MySubclass</span> <span class="token keyword">extends</span> <span class="token class-name">ExtensibleObject</span> <span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__get</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword static-context">parent</span><span class="token operator">::</span><span class="token function">__get</span> <span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">RuntimeException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token comment">// eigentlicher Code fängt hier an, sobald die RuntimeException </span>
<span class="token comment">// ignoriert wurde </span>
<span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">foobar</span><span class="token punctuation">[</span><span class="token variable">$name</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// oder whatever </span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">__call</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword static-context">parent</span><span class="token operator">::</span><span class="token function">__call</span> <span class="token punctuation">(</span><span class="token variable">$method</span><span class="token punctuation">,</span> <span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">BadMethodCallException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token comment">// eigentlicher Code fängt hier an, sobald die BadMethodCallException </span>
<span class="token comment">// ignoriert wurde </span>
<span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">foobar</span><span class="token punctuation">[</span><span class="token variable">$method</span><span class="token punctuation">]</span> <span class="token punctuation">(</span><span class="token variable">$args</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// oder whatever </span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>Viele Grüße,<br>
Christian</p>
<div class="signature">-- <br>
<a href="http://del.icio.us/chris_se/servertipps" rel="nofollow noopener noreferrer">Mein "Weblog"</a> [<a href="http://del.icio.us/rss/chris_se/servertipps" rel="nofollow noopener noreferrer">RSS</a>]<br>
<a href="http://www.christian-seiler.de/projekte/xslt-json/" rel="nofollow noopener noreferrer">Using XSLT to create JSON output</a> (Saxon-B 9.0 for Java)<br>
»I don't believe you can call yourself a web developer until you've built an app that uses hyperlinks for deletion and have all your data deleted by a search bot.«<br>
-- <a href="http://thedailywtf.com/Comments/WellIntentioned-Destruction.aspx#254549" rel="nofollow noopener noreferrer">Kommentar bei TDWTF</a>
</div>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376596#m1376596
Edgar Ehritt
2009-07-01T20:18:07Z
2009-07-01T20:18:07Z
GC in 5.3
<p>Hallo Christian,</p>
<p>wegen zu guten Einblicken in die Materie, laste ich Dir das mal an, bin natürlich um Antworten von jedem dankbar:</p>
<p>Wie sieht es jetzt genau mit dem GC aus. Gibt dieser Speicher (endlich) auch an das OS wieder ab, während Scripte laufen und Variablen gelöscht werden? (Mein Interesse gilt da CLI-Anwendungen.)</p>
<p>Gruß aus Berlin!<br>
eddi</p>
<div class="signature">-- <br>
“Um etwas zu erschaffen mit gutem Erfolg, muß man aufhören das zu sein, was man ist; um ganz das zu werden, was man hervorbringen will.”
</div>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376597#m1376597
Christian Seiler
self@christian-seiler.de
http://www.christian-seiler.de/projekte/xslt-json/
2009-07-01T20:54:44Z
2009-07-01T20:54:44Z
GC in 5.3
<p>Hallo,</p>
<blockquote>
<p>Wie sieht es jetzt genau mit dem GC aus. Gibt dieser Speicher (endlich) auch an das OS wieder ab, während Scripte laufen und Variablen gelöscht werden? (Mein Interesse gilt da CLI-Anwendungen.)</p>
</blockquote>
<p>Den GC betrifft das nicht, bei dem geht's nur um zirkuläre Referenzen. PHP gibt ja auch bereits in 5.2 schon Speicher an das OS zurück, wenn bestimmte Bedingungen erfüllt sind - und an der Speicherverwaltung selbst hat sich nichts wesentliches geändert.</p>
<p>Um zu verstehen, warum PHP bereits in 5.2 den Speicher nicht wirklich freigibt, eine kurze Einführung, wie in PHP die Speicherverwaltung funktioniert:</p>
<p>Sobald Speicher benötigt wird, ruft der C-Code von PHP die Funktion emalloc() auf. Die Funktion fordert dann vom Betriebssystem einen Block Speicher an, der der Anwendung zur Verfügung stehen soll (deswegen steigt der Speicherverbrauch auch in Sprüngen an) - und fügt den Block zu der internen Liste mit zur Verfügung stehenden Blöcke hinzu. Aus diesem Block wird dann ein Teil reserviert und die Adresse davon zurückgegeben. Beispiel (Zahlen für die Blockgrößen aus den Fingern gesogen):</p>
<p>0. Zustand der Speicherverwaltung und des Speichers:</p>
<p>+------------+<br>
| Blockliste |<br>
+------------+<br>
| (leer) |<br>
+------------+</p>
<p>1. Aufruf von emalloc:</p>
<p>char *foo = emalloc (20);</p>
<p>1a. Anfordern eines größeren Blocks vom Betriebssystem</p>
<p>[Notation: XXX reserviert, sonst frei]</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->| |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+<br>
+------------+</p>
<p>1b. Reservieren des Speicherbereichs im Block und Zurückgeben des Zeigers.</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->|XXXXX |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+ ^<br>
+------------+ |<br>
|<br>
foo ---------------------------+</p>
<p>2. Weiterer Aufruf von emalloc:</p>
<p>char *bar = emalloc (28);</p>
<p>2a. Reservieren des Speicherbereichs im Block und Zurückgeben des Zeigers.</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->|XXXXXXXXXXXX |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+ ^ ^<br>
+------------+ | |<br>
| |<br>
foo ---------------------------+ |<br>
|<br>
bar --------------------------------+</p>
<p>3. Noch ein Aufruf von emalloc:</p>
<p>char *baz = emalloc (200);</p>
<p>3a. Feststellen, dass der bisherige Speicherbereich zu klein ist, also noch ein Block vom OS anfordern:</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->|XXXXXXXXXXXX |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+ ^ ^<br>
| Block 2 --|---+ | |<br>
+------------+ | | |<br>
| | |<br>
foo ---------------------------+ |<br>
| |<br>
bar --------------------------------+<br>
| +------------- ... ----------------------+<br>
+------------>| ... |<br>
+------------- ... ----------------------+</p>
<p>2a. Reservieren des Speicherbereichs im neuen Block und Zurückgeben des Zeigers.</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->|XXXXXXXXXXXX |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+ ^ ^<br>
| Block 2 --|---+ | |<br>
+------------+ | | |<br>
| | |<br>
foo ---------------------------+ |<br>
| |<br>
bar --------------------------------+<br>
| +------------- ... ----------------------+<br>
+------------>|XXXXXXXXXXXXX ... XXXXXXXX |<br>
+------------- ... ----------------------+<br>
^<br>
|<br>
baz ---------------------------+</p>
<p>Was passiert nun, wenn im Script eine Variable nicht mehr benötigt wird? Der Speicherbereich der Variable wird als frei gekennzeichnet. In unserem Beispiel:</p>
<p>efree (foo);<br>
foo = NULL;</p>
<p>+------------+ +----------------------------------------+<br>
| Blockliste | +---------->| XXXXXXX |<br>
+------------+ | +----------------------------------------+<br>
| Block 1 --|-----+ ^<br>
| Block 2 --|---+ |<br>
+------------+ | |<br>
| |<br>
foo | |<br>
| |<br>
bar --------------------------------+<br>
| +------------- ... ----------------------+<br>
+------------>|XXXXXXXXXXXXX ... XXXXXXXX |<br>
+------------- ... ----------------------+<br>
^<br>
|<br>
baz ---------------------------+</p>
<p>Das Problem ist nun: Der Speicher des ersten Blocks kann nicht von PHP wieder an das Betriebssystem zurückgegeben werden, da dort noch die Variable bar lebt. Und das war hier nur im einfachen Beispiel - in PHP gibt es z.B. pro globaler Variable etliche Allozierungsaufrufe. Man hat also am Ende lauter Blöcke, die PHP hat, die teilweise belegt sind -> der Speicherverbrauch sinkt nicht mehr. Er sinkt nur dann, wenn Blöcke am Stück zurückgegeben werden können was eigentlich nur dann passiert, wenn man z.B. PHP als Apache-Modul betreibt können am Ende des Requests alle Blöcke, die während des Requests alloziert wurden, wieder freigegeben werden.</p>
<p>Nun könntest Du fragen, warum PHP überhaupt Blöcke alloziert die größer sind als der angeforderte Bereich und nicht einfach die immer passend macht. Die Antwort darauf ist, dass es sehr langsam ist, vom Betriebssystem einen neuen Block anzufordern (fast unabhängig von der Größe des Blocks), es aber sehr schnell ist, intern Teile von Blöcken als belegt oder nicht belegt zu markieren. Außerdem müssen die Blöcke vom Betriebssystem "aligned" sein, d.h. können ihre Startadresse nur in Vielfachen der Page Size oder einer ähnlichen Größe haben - und bei 4 KB Page Size würdest Du um nur 100 Bytes zu allozieren ganze 3996 Bytes komplett verschwenden. Daher ist die gewählte Variante sicherlich besser als die vorige.</p>
<p>Allerdings: Der nichtverwendete Speicher in den Blöcken steht wieder für neue Variablen in PHP zur Verfügung, d.h. der Speicherverbrauch eines PHP-Scripts geht zwar in der Regel nicht mehr nach unten - aber wenn es gut geht steigt er auch nicht mehr weiter.</p>
<p>Viele Grüße,<br>
Christian</p>
<div class="signature">-- <br>
<a href="http://del.icio.us/chris_se/servertipps" rel="nofollow noopener noreferrer">Mein "Weblog"</a> [<a href="http://del.icio.us/rss/chris_se/servertipps" rel="nofollow noopener noreferrer">RSS</a>]<br>
<a href="http://www.christian-seiler.de/projekte/xslt-json/" rel="nofollow noopener noreferrer">Using XSLT to create JSON output</a> (Saxon-B 9.0 for Java)<br>
»I don't believe you can call yourself a web developer until you've built an app that uses hyperlinks for deletion and have all your data deleted by a search bot.«<br>
-- <a href="http://thedailywtf.com/Comments/WellIntentioned-Destruction.aspx#254549" rel="nofollow noopener noreferrer">Kommentar bei TDWTF</a>
</div>
https://forum.selfhtml.org/self/2009/jun/30/lese-ich-das-richtig-php-objekte-aehnlich-flexibel-wie-in-js/1376598#m1376598
Edgar Ehritt
2009-07-01T21:06:08Z
2009-07-01T21:06:08Z
GC in 5.3
<p>Re:</p>
<p>danke! :)</p>
<p>Gruß aus Berlin!<br>
eddi</p>
<div class="signature">-- <br>
“Um etwas zu erschaffen mit gutem Erfolg, muß man aufhören das zu sein, was man ist; um ganz das zu werden, was man hervorbringen will.”
</div>