<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ebene7 &#187; Callback</title>
	<atom:link href="http://blog.ebene7.com/schlagwort/callback/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ebene7.com</link>
	<description></description>
	<lastBuildDate>Tue, 04 Jun 2013 18:57:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Sortieren mit PHP5 Closures und dem Java Comparator Pattern</title>
		<link>http://blog.ebene7.com/2012/08/31/sortieren-mit-php5-closures-und-dem-java-comparator-pattern/</link>
		<comments>http://blog.ebene7.com/2012/08/31/sortieren-mit-php5-closures-und-dem-java-comparator-pattern/#comments</comments>
		<pubDate>Fri, 31 Aug 2012 04:00:13 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Callback]]></category>
		<category><![CDATA[Closure]]></category>
		<category><![CDATA[Comparator]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Sortierung]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3421</guid>
		<description><![CDATA[Was mich schon oft bei PHP ein wenig störte ist, dass es zum Sortieren nicht so schöne Comparatoren wie in Java gibt. Nun habe ich in der Vergangenheit ja schon das eine oder andere über Closures in PHP und Java &#8230; <a href="http://blog.ebene7.com/2012/08/31/sortieren-mit-php5-closures-und-dem-java-comparator-pattern/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Was mich schon oft bei PHP ein wenig störte ist, dass es zum Sortieren nicht so schöne Comparatoren wie in Java gibt.</p>
<p>Nun habe ich in der Vergangenheit ja schon das eine oder andere über <a href="http://blog.ebene7.com/2012/01/30/closures-in-php/">Closures in PHP</a> und <a href="http://blog.ebene7.com/2010/09/06/besser-sortieren-mit-php-dank-java-interfaces/">Java Comparatoren für PHP</a> geschrieben und wollte das nun mal zusammenbringen.</p>
<p><span id="more-3421"></span>Einige PHP-Sortierfunktionen erlauben Callbacks, um die Reihenfolge zu bestimmen. Da ich das Ganze aber gerne in gut testbaren OOP-Einheiten hätte, müssen wir einen kleinen Umweg gehen.</p>
<p>Zunächst das obligatorische Interface.</p>
<pre>namespace E7;

interface Comparator {
  public function compare($a, $b);
}</pre>
<p>Diese Schnittstelle implementieren wir mit einer abstrakten Klasse.</p>
<pre>namespace E7;

class BaseComparator implements Comparator {
  public function compare($a, $b) {
    if ($a == $b) { return 0; }
    return $a &lt; $b ? -1 : 1;
  }

  public function __invoke() {
    return call_user_func_array(array($this, 'compare'), func_get_args());
  }
}</pre>
<p>Und schon haben wir einen einfachen, und zugegebenermaßen nicht typsicheren, Comparator.</p>
<p>Durch die magische Methode __invoke() kann ein Objekt nun wie eine Callbackfunktion verwendet werden.</p>
<p>Für die Sortierung von Objekten kann das dann einfach erweitert werden.</p>
<pre>class PersonComparator extends BaseComparator {
  public function compare($a, $b) {
    // hier Prüfung auf Typ etc.
    return parent::compare($a-&gt;getId(), $b-&gt;getId());
  }    
}</pre>
<p>Um die Sortierreihenfolge negieren zu können, können wir einen einfachen Wrapper nutzen.</p>
<pre>class ReverseOrder implements Comparator {
  private $_comparator;

  public function __construct(Comparator $comparator) {
    $this-&gt;_comparator = $comparator;
  }

  public function compare($a, $b) {
    return $this-&gt;_comparator-&gt;compare($a, $b) * -1;
  }
}</pre>
<p>Beispiel&#8230;</p>
<pre>//--
$people = array();
for ($i = 0; $i &lt; 10; $i ++) {
  $people[] = new Person();
}

echo 'BEFORE&lt;br/&gt;';
foreach($people as $person) {
  echo "$person&lt;br/&gt;";
}

$comparator = new ReverseOrder( new PersonComparator() );

uasort($people, function($a, $b) use ($comparator) {
    return $comparator-&gt;compare($a, $b);
});

// oder

uasort($people, $comparator);

echo 'AFTER&lt;br/&gt;';
foreach($people as $person) {
  echo "$person&lt;br/&gt;";
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ebene7.com/2012/08/31/sortieren-mit-php5-closures-und-dem-java-comparator-pattern/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Closures in PHP</title>
		<link>http://blog.ebene7.com/2012/01/30/closures-in-php/</link>
		<comments>http://blog.ebene7.com/2012/01/30/closures-in-php/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 05:00:58 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Callback]]></category>
		<category><![CDATA[Closure]]></category>
		<category><![CDATA[Interface]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3364</guid>
		<description><![CDATA[Ab der Version 5.3 bietet auch PHP, wie auch schon viele andere Sprachen, die Möglichkeit mit anonymen Funktionen zu arbeiten. Dadurch können z.B. Callback-Funktionen zur Filterung o.Ä. implementiert werden, ohne dass man sich dafür tolle Namen ausdenken muss. Aber was &#8230; <a href="http://blog.ebene7.com/2012/01/30/closures-in-php/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ab der Version 5.3 bietet auch PHP, wie auch schon viele andere Sprachen, die Möglichkeit mit <a href="http://www.php.net/manual/de/functions.anonymous.php" target="_blank">anonymen Funktionen</a> zu arbeiten. Dadurch können z.B. Callback-Funktionen zur Filterung o.Ä. implementiert werden, ohne dass man sich dafür tolle Namen ausdenken muss. Aber was kann man damit noch machen?</p>
<p><span id="more-3364"></span>Bislang musste man Callback-Funktionen gewöhnlich definieren, bevor man sie verwenden konnte.</p>
<pre>&lt;?php
function myCallback($output) {
  return '##' . $output . '##';
}

echo call_user_func('myCallback', 'Hallo Welt');

// Ausgabe:
##Hallo Welt##</pre>
<p>Als Closure geschrieben sähe das dann so aus:</p>
<pre>&lt;?php
echo call_user_func(
  function($output) { return '##' . $output . '##'; },
  'Hallo Welt');

// Ausgabe:
##Hallo Welt##</pre>
<p>Zugegeben, dieses Beispiel hätte man durch einfache Stringverkettung wesentlich einfacher schreiben können und eigentlich war das mit <a href="http://de2.php.net/manual/de/function.create-function.php" target="_blank">create_function()</a> auch schon unter PHP4 möglich.</p>
<p>Wir können die Funktion natürlich wie früher auch schon in einer Variablen speichern und dann weiter verwenden.</p>
<pre>&lt;?php
$myFunction = function($output) {
  return '##' . $output . '##';
};

echo call_user_func($myFunction, 'Hallo Welt') . '&lt;br/&gt;';
echo $myFunction('Hallo Welt') . '&lt;br/&gt;';

//Ausgabe:
##Hallo Welt##
##Hallo Welt##</pre>
<p>Und auch das ist ja noch nichts Neues. Mit Closures haben wir nun aber auch die Möglichkeit, teile unserer &#8220;Umgebung&#8221; zum Zeitpunkt der Funktionsdefinition zu konservieren.</p>
<p>Dazu müssen wir nur die Definition etwas erweitern.</p>
<pre>&lt;?php
$before = '&gt;';
$after = '&lt;';

$myFunction = function($output) use ($before, $after) {
    return $before . $output . $after;
};

echo $myFunction('Hallo Welt') . '&lt;br/&gt;';

//Ausgabe:
&gt;Hallo Welt&lt;</pre>
<p>An dieser Stelle frieren wir mit &#8220;use&#8221; sozusagen die Werte für $before und $after innerhalb unserer Funktion ein. Spätere Änderungen der beiden Variablen haben keine Auswirkungen auf die Funktion.</p>
<pre>$before = 'foo';
$after = 'bar';
echo $myFunction('Hallo Welt') . '&lt;br/&gt;';

//Ausgabe:
&gt;Hallo Welt&lt;</pre>
<p>In PHP wir mittlerweile sehr viel mit Standardinterfaces und -klassen (SPL) abgedeckt und so ist es auch in diesem Fall. In der Variablen $myFunction ist ein Objekt vom Typ &#8220;<a href="http://de2.php.net/manual/en/class.closure.php" target="_blank">Closure</a>&#8221; gespeichert.</p>
<pre>&lt;?php
echo '&lt;pre&gt;' . print_r($myFunction, true) . '&lt;/pre&gt;';

//Ausgabe:
Closure Object
(
  [static] =&gt; Array
    (
      [before] =&gt; &gt;
      [after] =&gt; &lt;
    )
  [parameter] =&gt; Array
    (
      [$output] =&gt;
    )
)</pre>
<p>Will man eigene Objekte wie Funktionen aufrufen, dann geht das mit der magischen Methode <a href="http://de2.php.net/manual/de/language.oop5.magic.php#language.oop5.magic.invoke" target="_blank">__invoke()</a>, die auch hier verwendet wird.</p>
<p>Anfangs erwähnte ich, dass Closure-Callbacks zur Filterung, aber auch zur Manipulation von Array verwendet werden können.</p>
<p>Wenn nur der Inhalt interessant ist, dann kommen wir mit array_map() und einem Parameter aus.</p>
<pre>&lt;?php
$values = array(
  array(
    'a' =&gt; array(
      'b' =&gt; 'foo'
    )
  ),
  array(
    'a' =&gt; array(
      'b' =&gt; 'bar'
    )
  ),
);

$filtered = array_map(
  function ($item) { return $item['a']['b']; },
  $values
);
echo '&lt;pre&gt;' . print_r($filtered, true) . '&lt;/pre&gt;';

// Ausgabe:
Array
(
  [0] =&gt; foo
  [1] =&gt; bar
)</pre>
<p>Wollen wir aber Werte im Array in Abhängigkeit zum Key/Index verändern, dann geht das mit array_walk und einem zweiten Parameter im Callback. Bei beiden kann natürlich auch &#8220;use&#8221; verwendet werden. Der Parameter $value wird dabei als Referenz übernommen.</p>
<pre>$values = array(
  'a' =&gt; 100,
  'b' =&gt; 200,
  'c' =&gt; 300,
);

array_walk(
  $values,
  function (&amp;$value, $key) {
    if ('b' == $key) {
      $value = 42;
    }
  }
);

echo '&lt;pre&gt;' . print_r($values, true) . '&lt;/pre&gt;';

// Ausgabe:
Array
(
  [a] =&gt; 100
  [b] =&gt; 42
  [c] =&gt; 300
)</pre>
<p>Ich hoffe, dass ich ein wenig Licht ins Dunkel bringen konnte und &#8220;Closure&#8221; nun kein geheimnisvolles Zauberwort mehr ist.</p>
<p>Wenn ihr noch gute Ergänzungen oder Anwendungbeispiele habt, dann immer her damit und bitte fleissig kommentieren. <img src='http://blog.ebene7.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ebene7.com/2012/01/30/closures-in-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Eigene Werte aus PHP in die Apache Logs schreiben</title>
		<link>http://blog.ebene7.com/2011/12/01/eigene-werte-aus-php-in-die-apache-logs-schreiben/</link>
		<comments>http://blog.ebene7.com/2011/12/01/eigene-werte-aus-php-in-die-apache-logs-schreiben/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 05:00:50 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Server und Technik]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Callback]]></category>
		<category><![CDATA[Logging]]></category>
		<category><![CDATA[Webserver]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=3193</guid>
		<description><![CDATA[Heute, na inzwischen eigentlich schon gestern, habe ich bei der Suche nach einer Apache-Konfiguration durch Zufall etwas interessantes gefunden. Eine PHP-Funktion namens &#8220;apache_note()&#8220;, mit der man Werte aus PHP an die Apache-Logs weitergeben kann. Der eine oder andere kennt die &#8230; <a href="http://blog.ebene7.com/2011/12/01/eigene-werte-aus-php-in-die-apache-logs-schreiben/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Heute, na inzwischen eigentlich schon gestern, habe ich bei der Suche nach einer Apache-Konfiguration durch Zufall etwas interessantes gefunden. Eine PHP-Funktion namens &#8220;<a href="http://php.net/manual/de/function.apache-note.php" target="_blank">apache_note()</a>&#8220;, mit der man Werte aus PHP an die Apache-Logs weitergeben kann.<span id="more-3193"></span></p>
<p>Der eine oder andere kennt die Funktion vielleicht schon, aber für mich ist sie neu. Daher habe ich damit einfach mal etwas rumprobiert und einen kleinen Codeschipsel dazu gebastelt. Die Apache-Logs können für vielfältige Auswertungen verwendet werden.</p>
<p>Zum Beispiel welche Seiten besucht oder nicht gefunden werden können, zum Tracken von Werbemitteln oder in dem Fall auch zum Protokollieren weiterer PHP-Werte.</p>
<p>In einem früheren Projekt haben wir mal die Zeit und den Speicherverbrauch gemessen die ein PHP-Script braucht, um die Seite auszuliefern. Dazu hatten wir eine einfache Klasse, ähnlich der folgenden (im dem Beispiel wird nur die Zeit gemessen):</p>
<pre>class PageBenchmark
{
  private $_startTime;
  private static $_instance;

  protected function __construct()
  {
    register_shutdown_function(array(self::$_instance, 'stop'));
    $this-&gt;start();
  }

  protected function __clone() {}

  public function getInstance()
  {
    if (null === self::$_instance) {
      self::$_instance = new self();
    }
    return self::$_instance;
  }

  public function start()
  {
    $this-&gt;_startTime = microtime(true);
  }

  public function stop()
  {
    $time = microtime() - $this-&gt;_startTime;
    apache_note('worktime', $time);
  }
}

PageBenchmark::getInstance();</pre>
<p>Die Klasse ist bewusst einfach gehalten und sollte möglichst ohne weitere Abhängigkeiten funktionieren. Die Verwendung ist dabei recht einfach. Das Script an einer zentralen Stelle möglichst früh einbinden. Durch den Aufruf von getInstance() wird ein Objekt instanziiert und die Methode stop() als Callback registriert.</p>
<p>Wird das Script nun abgearbeitet, wird diese Methode zum Ende aufgerufen und die verbrauchte Zeit wird errechnet und an Apache übergeben.</p>
<p>Damit das ganze dann einen Sinn bekommt, muss die Konfiguration des Webservers noch etwas angepasst werden. Für unser Beispiel schreiben wir die Zeit an das Ende jeder Zeile.</p>
<pre>LogFormat "%h %l %u %t \"%r\" %&gt;s %b \"%{Referer}i\" [%{worktime}n]" mylogformat
CustomLog /var/www/sandkasten/logs/access.log mylogformat</pre>
<p>Danach natürlich den Webserver neu starten, bzw. ein Reload machen. Ab jetzt sollte zu jedem Logeintrag die verbrauchte Zeit mitgeschrieben werden. Die verwendeten Kürzel werden in der <a href="http://httpd.apache.org/docs/current/mod/mod_log_config.html" target="_blank">Doku zu mod_log_config</a> erklärt.</p>
<p>Viel Spaß beim Probieren!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ebene7.com/2011/12/01/eigene-werte-aus-php-in-die-apache-logs-schreiben/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Array als Parameterliste an den Konstruktor übergeben</title>
		<link>http://blog.ebene7.com/2011/03/21/array-als-parameterliste-an-den-konstruktor-uebergeben/</link>
		<comments>http://blog.ebene7.com/2011/03/21/array-als-parameterliste-an-den-konstruktor-uebergeben/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 05:00:51 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tipps und Tricks]]></category>
		<category><![CDATA[Callback]]></category>
		<category><![CDATA[Factory]]></category>
		<category><![CDATA[Parameter]]></category>
		<category><![CDATA[Reflection]]></category>

		<guid isPermaLink="false">http://blog.ebene7.com/?p=2797</guid>
		<description><![CDATA[In verschiedenen Fällen kann/muss man, z.B. Callback-Funktionen/Methoden mit einer variablen Parameterliste aufrufen. Was aber, wenn wir ein Objekt durch eine Factory erstellen wollen und der Konstruktor Parameter erwartet? Die Funktionen call_user_func() oder call_user_func_array() fallen leider aus, da wir noch kein &#8230; <a href="http://blog.ebene7.com/2011/03/21/array-als-parameterliste-an-den-konstruktor-uebergeben/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In verschiedenen Fällen kann/muss man, z.B. Callback-Funktionen/Methoden mit einer variablen Parameterliste aufrufen. Was aber, wenn wir ein Objekt durch eine Factory erstellen wollen und der Konstruktor Parameter erwartet?</p>
<p>Die Funktionen <a href="http://de2.php.net/manual/de/function.call-user-func.php" target="_blank">call_user_func()</a> oder <a href="http://de2.php.net/manual/de/function.call-user-func-array.php" target="_blank">call_user_func_array()</a> fallen leider aus, da wir noch kein Callback-Objekt haben. Es gibt aber einen sehr einfachen Weg mit Reflections.<span id="more-2797"></span></p>
<p>Zuerst ein paar einfache Klassen zum Testen. Von der Klasse Foo soll ein Objekt erstellt werden und diese erwartet je ein Objekt vom Typ Bar und Baz als Parameter im Konstruktor.</p>
<pre>&lt;?php
class Bar {}
class Baz {}

class Foo
{
  public function __construct(Bar $bar, Baz $baz)
  {
    echo '&lt;pre&gt;' . print_r(func_get_args(), true) . '&lt;/pre&gt;';
  }
}</pre>
<p>Nun wird das Objekt über eine sehr einfache Factory-Methode erzeugt und dabei wird die Parameterliste von create() an den Konstruktor weitergegeben.</p>
<pre>&lt;?php
class Factory
{
  public static function create($type)
  {
    $args = func_get_args();
    array_shift($args);
    $class = new ReflectionClass($type);
    return $class-&gt;newInstanceArgs($args);
  }
}

$foo = Factory::create('Foo', new Bar(), new Baz());</pre>
<p>So einfach ist es. Über die Reflection-Klasse wird ein neues Objekt erzeugt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ebene7.com/2011/03/21/array-als-parameterliste-an-den-konstruktor-uebergeben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
