<?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>Service | Nerdpress.org</title>
	<atom:link href="https://nerdpress.org/tag/service/feed/" rel="self" type="application/rss+xml" />
	<link>https://nerdpress.org</link>
	<description>...dev, tech problems and solutions.</description>
	<lastBuildDate>Fri, 01 Apr 2011 08:51:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Image Placeholder Services</title>
		<link>https://nerdpress.org/2011/04/01/image-placeholder-services/</link>
		
		<dc:creator><![CDATA[Max Girkens]]></dc:creator>
		<pubDate>Fri, 01 Apr 2011 08:51:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Gfx]]></category>
		<category><![CDATA[Service]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1439</guid>

					<description><![CDATA[<p>cooler Service, wenn man mal neutrale Platzhalter Bilder braucht: http://placehold.it/ und was ähnliches mit Flickr Fotos: http://flickholdr.com/</p>
The post <a href="https://nerdpress.org/2011/04/01/image-placeholder-services/">Image Placeholder Services</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>cooler Service, wenn man mal neutrale Platzhalter Bilder braucht:<br />
<a href="http://placehold.it/">http://placehold.it/</a></p>
<p>und was ähnliches mit Flickr Fotos:<br />
<a href="http://flickholdr.com/">http://flickholdr.com/</a></p>The post <a href="https://nerdpress.org/2011/04/01/image-placeholder-services/">Image Placeholder Services</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Dependency Injection mit Symfony 1.x</title>
		<link>https://nerdpress.org/2010/05/27/dependency-injection-mit-symfony-1-x/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Thu, 27 May 2010 16:58:23 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software engineering]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Inversion of Control]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Service]]></category>
		<category><![CDATA[sfDependencyInjectionContainerPlugin]]></category>
		<category><![CDATA[Symfony Components]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=987</guid>

					<description><![CDATA[<p>Beschreibung IoC Pattern anhand Grails Services und Kurze Einführung in die Symfony-Komponente "Dependency Injection".</p>
The post <a href="https://nerdpress.org/2010/05/27/dependency-injection-mit-symfony-1-x/">Dependency Injection mit Symfony 1.x</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Durch meine ersten Gehversuche mit <a href="http://www.grails.org/">Grails</a> sowie einen interessanten Vortrag über JSF2 bin ich kürzlich über das Kürzel &#8220;<a href="http://de.wikipedia.org/wiki/Inversion_of_Control">IoC</a>&#8221; gestoßen. Das ganze ist vom Prinzip her recht einfach und in Grails, das im Grunde ein stinknormales MVC-Pattern implementiert, konkret gelöst, indem man durch eine Namenskonvention am Controller automatisch sogenannte Services instanziiert. </p>
<p><span id="more-987"></span></p>
<p>Also anstatt zu schreiben:</p>
<pre class="brush: groovy; title: ; notranslate">
class DefaultController {
  
  def mySuperService
  
  def index = {
   mySuperService = new MySuperService(params);
   mySuperService.getData()
  }
}
</pre>
<p>schreibe ich einfach</p>
<pre class="brush: groovy; title: ; notranslate">
class DefaultController {
 
  def mySuperService
 
  def index = {
   mySuperService.getData()
  }
}
</pre>
<p>Gut, sieht jetzt nicht besonders spektakulär aus, doch wenn man weiß, dass mySuperService im Hintergrund (Stichwort &#8220;Spring Managed Bean&#8221;) automatisch instanziiert sowie an meinen Controller gebunden wurde und dass da prinzipiell noch viel mehr <a href="http://www.grails.org/Services">geht</a>, ist das bereits ein ganz brauchbares Feature.</p>
<p>Natürlich ist die Injizierung per Naming-convention eine Grails-eigene Lösung (alles, was auf Service endet, ist ein Service und wird injiziert), um Konfigurationsarbeit zu sparen. Für gewöhnlich wird das Verhalten sogenanner &#8220;<a href="http://java.sun.com/javaee/6/docs/api/javax/annotation/ManagedBean.html">managed Beans</a>&#8221; natürlich konfiguriert, entweder Java-typisch via XML-Konfigurationsdatei oder durch <a href="http://de.wikipedia.org/wiki/Annotation#Informatik">Annotationen</a>.</p>
<p>Dabei kann wiederum java-typisch auch der &#8220;Scope&#8221; einer Bean bestimmt werden; hier bringt vor allem der &#8220;Singleton&#8221; bzw. Application Scope einen Vorteil gegenüber einer statuslosen PHP-Anwendung. Doch bereits die Fähigkeit, den Scope überhaupt fein granulieren zu können, setzt das ganze wieder von PHP-Gemurkse ala $_SESSION, $_REQUEST etc. ab. </p>
<p>Also egal wo und in welchem Kontext man Managed Beans, Enterprise Java Beans, Spring Beans (Die Unterschiede interessieren hier mal nicht die Bohne &#8211; ich könnte sie auch gar nicht qualifiziert erläutern) einsetzt &#8211; das IoC-Muster spart Code, vereinfacht Abhängigkeiten und sorgt für schlankere Konstruktoren &#8211; ist insgesamt also eine sehr mächtige Sache.</p>
<p>Was aber nicht heißt, dass so etwas generell nicht auch in meiner PHP-Anwendung funktionieren kann.</p>
<h3><strong>sfDependencyInjectionContainerPlugin</strong></h3>
<p>Dieses Plugin (<a href="http://www.symfony-project.org/plugins/sfDependencyInjectionContainerPlugin">http://www.symfony-project.org/plugins/sfDependencyInjectionContainerPlugin</a>) leistet genau das: Es verwaltet entweder über eine in PHP formulierte <a href="http://de.wikipedia.org/wiki/Dom%C3%A4nenspezifische_Sprache">DSL</a>(hust), über XML oder eine symfony-typische .yml-Datei konfigurierte Abhängigkeiten. Das Plugin ist selbst nur ein Adapter, das die <a href="http://components.symfony-project.org/">Symfony-Komponente</a> <a href="http://components.symfony-project.org/dependency-injection/">DependencyInjection</a> in ein Symfony 1.2 (und höher) Projekt integriert &#8211; in Symfony 2.0 wird DependencyInjection voraussichtlich Bestandteil des Systemkerns sein.</p>
<p>Zur Installation und Konfiguration des Plugins verweise ich auf die <a href="http://www.symfony-project.org/plugins/sfDependencyInjectionContainerPlugin">README</a>-Datei. Trotzdem vielleicht der Hinweis, dass die Bibliotheken mit einem eigenen Autoloader daherkommen, daher empfehle ich, folgende Programm-Zeilen in eure ProjectConfiguration.class.php hinzuzufügen:</p>
<p>config/projectConfiguration.class.php</p>
<pre class="brush: php; title: ; notranslate">
  require_once dirname(__FILE__) . '/../pfad/zur/DependencyInjection/Komponente/sfServiceContainerAutoloader.php';
  sfServiceContainerAutoloader::register();
</pre>
<p>Anders habe ich es nicht hinbekommen, zwar lässt sich durch eine config/autoload.yml die Laufzeit von Class Not Found-Fehlern befreien, aber das Symfony Command Line Interface geht dann trotzdem hops. Für einen Tipp, wie man&#8217;s eleganter hinkriegt, wäre ich dankbar.</p>
<p>Beispielsweise möchte ich den Nerdpress-RSS-Feed in meine Seite einbinden. Dazu baue ich einen Proxy, um bequem via AJAX auf das entfernte RSS-XML zugreifen zu können.<br />
Diesen Proxy definiere ich als Service und injiziere ihn meine Symfony-Module:</p>
<p>config/services.yml:</p>
<pre class="brush: jscript; title: ; notranslate">
services:
  NerdpressRssProxy:
    class: NerdpressRssProxy
</pre>
<p>Diese drei Zeilen reichen bereits aus, um meine Abhängigkeit zu definieren.</p>
<p>Nun implementiere ich die Service-Klasse:</p>
<p>lib/NerdpressRssProxy.php</p>
<pre class="brush: php; title: ; notranslate">
class NerdpressRssProxy
{
  /**
   * @var sfFileCache
   */
  protected $cache;

  /**
   * @return sfFileCache
   */
  public function getCache()
  {
    if (null === $this-&gt;cache)
    {
      $this-&gt;cache = new sfFileCache(array('cache_dir' =&gt; sfConfig::get('sf_cache_dir')));
    }
    return $this-&gt;cache;
  }

  /**
   * @return string
   * @throws Exception
   */
  public function getEntries()
  {
    $cache = $this-&gt;getCache();

    sfContext::getInstance()-&gt;getConfiguration()-&gt;loadHelpers(array('Helper', 'Tag', 'Url', 'Text'));

    if(!($rss = $cache-&gt;get('nerdpress_rss')))
    {
      if(($rss = @file_get_contents('https://nerdpress.org/feed')))
      {
        $rss = auto_link_text($rss, 'all', array('class' =&gt; 'external'));

        $cache-&gt;set('nerdpress_rss', $rss, 3600);
      }
      else
      {
        throw new Exception('Rss feed could not be opened');
      }
    }
    return $rss;
  }
}
</pre>
<p>Die Methode getEntries() rufe ich nun in meinem Nerdpress-RSS-Modul auf, um die WebResponse zu befüllen:</p>
<p>apps/frontend/modules/rssProxy/actions/actions.class.php</p>
<pre class="brush: php; title: ; notranslate">
class rssProxyActions extends sfActions
{
  public function preExecute()
  {
    $this-&gt;getResponse()-&gt;setContentType('application/rss+xml');
  }
  
  public function executeNerdpress(sfWebRequest $request)
  {
    try
    {
      // SERVICE HOLEN UND getEntries() AUFRUFEN
      $rss = $this-&gt;getService('NerdpressRssProxy')-&gt;getEntries();

      $this-&gt;getResponse()-&gt;setHttpHeader('Content-Length', mb_strlen($rss));
      $this-&gt;getResponse()-&gt;setContent($rss);
    }
    catch(Exception $e)
    {
      $this-&gt;forward404($e-&gt;getMessage());
    }
    return sfView::NONE;
  }
}
</pre>
<p>Das wars. Einfach, oder? Ingesamt 3 Zeilen yml-Konfiguration reichen, um Dependency Injection &#8220;the PHP way&#8221; zu realisieren, Symfony sei Dank. Natürlich ist nicht *ganz* so hübsch wie in der J2EE-Welt und sicherlich funktional noch weit davon entfernt. Aber ein Anfang ist gemacht, und wenn man seine Services erst einmal auf diese Art und Weise unter Kontrolle bringt, ist man vom Nutzen der Sache schnell überzeugt: Mit ein bisschen Disziplin gehören &#8220;Controller-Spaghettiwürste&#8221; nämlich der Vergangenheit an.</p>
<p>Bitte entschuldigt eventuell fehlerhafte oder unsaubere Beschreibungen der Begriffe &#8220;Bean&#8221;, &#8220;IoC&#8221;, JSF2 etc. Ich bitte explizit um Korrektur in Form von Kommentaren :)</p>The post <a href="https://nerdpress.org/2010/05/27/dependency-injection-mit-symfony-1-x/">Dependency Injection mit Symfony 1.x</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
