<?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>Doctrine ORM | Nerdpress.org</title>
	<atom:link href="https://nerdpress.org/category/php/doctrine-orm/feed/" rel="self" type="application/rss+xml" />
	<link>https://nerdpress.org</link>
	<description>...dev, tech problems and solutions.</description>
	<lastBuildDate>Fri, 17 Jan 2025 16:34:32 +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>Doctrine: WHERE IN with array of integers</title>
		<link>https://nerdpress.org/2025/01/17/doctrine-where-in-with-array-of-integers/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Fri, 17 Jan 2025 16:34:32 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Sql]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3381</guid>

					<description><![CDATA[<p>Since I stumbled across this the other day, here&#8217;s how you build an SQL query with a WHERE IN condition for an array of integers. This is surprisingly not intuitive, as you cannot simply pass an array of integers to a prepared statement. Instead, you need to add special binding types to inform Doctrine that &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2025/01/17/doctrine-where-in-with-array-of-integers/" class="more-link">Continue reading<span class="screen-reader-text"> "Doctrine: WHERE IN with array of integers"</span></a></p>
The post <a href="https://nerdpress.org/2025/01/17/doctrine-where-in-with-array-of-integers/">Doctrine: WHERE IN with array of integers</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Since I stumbled across this the other day, here&#8217;s how you build an SQL query with a <code>WHERE IN</code> condition for an array of integers.</p>



<p>This is surprisingly not intuitive, as you cannot simply pass an array of integers to a prepared statement. Instead, you need to add special binding types to inform Doctrine that this is indeed an array of integers.</p>



<p>It&#8217;s very well explained in the documentation under the Parameters Conversion section:<br /><a href="https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion">https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion</a><br />But it is rather hard to find and it took me a while.</p>



<p>The trick is to add the array binding types to the the types parameters to the query method. In the case of integers, it is<code> \Doctrine\DBAL\ArrayParameterType::INTEGER</code>. <br />Now Doctrine knows how to handle the types in the array while binding the values.</p>



<span id="more-3381"></span>



<p>Example:</p>


<pre class="wp-block-code"><span><code class="hljs language-php">$sql = <span class="hljs-string">'SELECT * FROM items WHERE id IN (?)'</span>; 
$numbersAsStrings = <span class="hljs-string">"1,2,3"</span>;
$numbers = array_map(<span class="hljs-string">'intval'</span>, explode(<span class="hljs-string">','</span>, $numbersAsStrings));
$users = $con-&gt;fetchAllAssociative(
  $sql, 
  &#91;$numbers], 
  &#91;ArrayParameterType::INTEGER]
);</code></span></pre>


<p>If you omit the types, Doctrine will simply try to bind the array as string, which will fail and you get this error:<br /><em>Array to string conversion</em></p>



<p>If you try to pass it as a comma-separated string yourself and omit the types like <kbd><code>$numbers = implode(',',array_map('intval', explode(',', $numbersAsStrings)));</code></kbd> You will get an error because Doctrine expects an array of values for the <kbd>IN</kbd> clause and not a string.<br />Error: <br /><em>count(): Argument #1 ($value) must be of type Countable|array, string given</em></p>



<p>I hope this helps someone finding out how to make <kbd>WHERE IN</kbd> SQL queries with Doctrine more quickly than me next time.</p>



<p></p>The post <a href="https://nerdpress.org/2025/01/17/doctrine-where-in-with-array-of-integers/">Doctrine: WHERE IN with array of integers</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Doctrine migrations and Postgis</title>
		<link>https://nerdpress.org/2022/10/31/doctrine-migrations-and-postgis/</link>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Mon, 31 Oct 2022 09:12:46 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Postgis]]></category>
		<category><![CDATA[Postgres]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=3184</guid>

					<description><![CDATA[<p>Using Postgres with the Postgis extension to integrate GeoData / GIS functionality in your project is not natively supported by Doctrine and Doctrine migrations. First you have to add the extension to Postgres, even if you use the Postgis docker image like postgis/postgis:14-3.3-alpine. So add this SQL statement to the up method of your first &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2022/10/31/doctrine-migrations-and-postgis/" class="more-link">Continue reading<span class="screen-reader-text"> "Doctrine migrations and Postgis"</span></a></p>
The post <a href="https://nerdpress.org/2022/10/31/doctrine-migrations-and-postgis/">Doctrine migrations and Postgis</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Using Postgres with the Postgis extension to integrate GeoData / GIS functionality in your project is not natively supported by Doctrine and Doctrine migrations.</p>



<p>First you have to add the extension to Postgres, even if you use the Postgis docker image like <code>postgis/postgis:14-3.3-alpine</code>.</p>



<p>So add this SQL statement to the up method of your first migration:<br /><code>$this->addSql('CREATE EXTENSION IF NOT EXISTS postgis;');</code><br /></p>



<p>and the DROP statement for the extension to the down method:<br /><code>$this->addSql('DROP EXTENSION postgis;');</code></p>



<p>Now, when using Doctrine with Postgres and Postgis extension, migrations still behave a bit odd and try to remove Sequences created by Postgis, because Doctrine migrations does not take Postgis extension&#8217; s built-in Sequences into account.</p>



<span id="more-3184"></span>



<p>So you will find this statements in your first migration, which is basically wrong because &#8211;<em>of course</em>&#8211; we want to keep the topology and tiger Sequences.</p>


<pre class="wp-block-code"><span><code class="hljs language-php">	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span><span class="hljs-params">(Schema $schema)</span>: <span class="hljs-title">void</span>
	</span>{
		<span class="hljs-comment">// this up() migration is auto-generated, please modify it to your needs</span>
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE topology.topology_id_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.county_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.state_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.place_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.cousub_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.edges_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.addrfeat_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.faces_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.featnames_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.addr_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.zcta5_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.tract_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.tabblock_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.bg_gid_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.pagc_gaz_id_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.pagc_lex_id_seq CASCADE'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'DROP SEQUENCE tiger.pagc_rules_id_seq CASCADE'</span>);
	}

	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">down</span><span class="hljs-params">(Schema $schema)</span>: <span class="hljs-title">void</span>
	</span>{
		<span class="hljs-comment">// this down() migration is auto-generated, please modify it to your needs</span>
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SCHEMA topology'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SCHEMA tiger'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SCHEMA tiger_data'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE topology.topology_id_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.county_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.state_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.place_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.cousub_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.edges_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.addrfeat_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.faces_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.featnames_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.addr_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.zcta5_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.tract_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.tabblock_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.bg_gid_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.pagc_gaz_id_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.pagc_lex_id_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
		<span class="hljs-keyword">$this</span>-&gt;addSql(<span class="hljs-string">'CREATE SEQUENCE tiger.pagc_rules_id_seq INCREMENT BY 1 MINVALUE 1 START 1'</span>);
	}</code></span></pre>


<p>So we have to teach Doctrine to respect these Postgis features.<br />Therefor extend the PostgreSqlPlatform class, add the Postgis features as exclude condition to the query:</p>



<p>src/DBAL/PostgisPostgreSqlPlatform.php:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">DBAL</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Doctrine</span>\<span class="hljs-title">DBAL</span>\<span class="hljs-title">Platforms</span>\<span class="hljs-title">PostgreSQLPlatform</span> <span class="hljs-title">as</span> <span class="hljs-title">PostgreSqlPlatformBase</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostgisPostgreSqlPlatform</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PostgreSqlPlatformBase</span>
</span>{
	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getListNamespacesSQL</span><span class="hljs-params">()</span>
	</span>{
		<span class="hljs-comment"># exclude postgis schemas</span>
		<span class="hljs-keyword">return</span> <span class="hljs-string">"SELECT schema_name AS nspname
				FROM   information_schema.schemata
				WHERE  schema_name NOT LIKE 'pg\_%'
				AND schema_name NOT LIKE 'topology'
				AND schema_name NOT LIKE 'tiger%'
				AND    schema_name != 'information_schema'"</span>;
	}

	<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getListSequencesSQL</span><span class="hljs-params">($database)</span>
	</span>{
		<span class="hljs-keyword">return</span> <span class="hljs-string">'SELECT sequence_name AS relname,
					   sequence_schema AS schemaname,
					   minimum_value AS min_value, 
					   increment AS increment_by
				FROM   information_schema.sequences
				WHERE  sequence_catalog = '</span> . <span class="hljs-keyword">$this</span>-&gt;quoteStringLiteral($database) . <span class="hljs-string">"
				AND    sequence_schema NOT LIKE 'pg\_%' 
				AND sequence_schema NOT LIKE 'topology%'
				AND sequence_schema NOT LIKE 'tiger%'
				AND    sequence_schema != 'information_schema'"</span>;
	}
}</code></span></pre>


<p>As Gist: <a href="https://gist.github.com/ivoba/74a143d8074110ef47f93a581bb0c3f6" target="_blank" rel="noreferrer noopener">https://gist.github.com/ivoba/74a143d8074110ef47f93a581bb0c3f6</a></p>



<p>Now tell doctrine to use this PostgreSqlPlatform class instead.<br />In symfony you can add this to config/packages/doctrine.yaml:</p>


<pre class="wp-block-code"><span><code class="hljs language-yaml"><span class="hljs-attr">doctrine:</span>
	<span class="hljs-attr">dbal:</span>
		<span class="hljs-attr">url:</span> <span class="hljs-string">'%env(resolve:DATABASE_URL)%'</span>
		<span class="hljs-attr">types:</span>
			<span class="hljs-attr">geometry:</span> <span class="hljs-string">LongitudeOne\Spatial\DBAL\Types\GeometryType</span>
			<span class="hljs-attr">point:</span> <span class="hljs-string">LongitudeOne\Spatial\DBAL\Types\Geometry\PointType</span>
			<span class="hljs-attr">polygon:</span> <span class="hljs-string">LongitudeOne\Spatial\DBAL\Types\Geometry\PolygonType</span>
			<span class="hljs-attr">linestring:</span> <span class="hljs-string">LongitudeOne\Spatial\DBAL\Types\Geometry\LineStringType</span>
		<span class="hljs-attr">platform_service:</span> <span class="hljs-string">App\DBAL\PostgisPostgreSqlPlatform</span></code></span></pre>


<p>This is inspired by this Gist, which does the same for other Postgres extensions: <a href="https://gist.github.com/dextervip/a2f384050748d6ee3ed7d573425e9d58" target="_blank" rel="noreferrer noopener">https://gist.github.com/dextervip/a2f384050748d6ee3ed7d573425e9d58</a></p>



<p>Now you can run your migrations diff <code>bin/console do:mi:di</code> and the Postgis sequences will be respected by the Doctrine.</p>The post <a href="https://nerdpress.org/2022/10/31/doctrine-migrations-and-postgis/">Doctrine migrations and Postgis</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>[Symfony 2] composer.json for a assumed-stable symfony 2 distribution</title>
		<link>https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/</link>
					<comments>https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sun, 01 Apr 2012 12:18:54 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Project Setup]]></category>
		<category><![CDATA[Silex]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Twig]]></category>
		<category><![CDATA[composer.phar]]></category>
		<category><![CDATA[dependency management]]></category>
		<category><![CDATA[packagist]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=2118</guid>

					<description><![CDATA[<p>This small composer.json file is used in a project i am working on atm, feel free to use it at own risk. I will provide non-periodical updates and hopefully soon a full upgrade to symfony 2.1.x including doctrine orm 2.2.x. I still did not get the point regarding dependency resolution, so i simply &#8220;composed&#8221; the &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/" class="more-link">Continue reading<span class="screen-reader-text"> "[Symfony 2] composer.json for a assumed-stable symfony 2 distribution"</span></a></p>
The post <a href="https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/">[Symfony 2] composer.json for a assumed-stable symfony 2 distribution</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>This small composer.json file is used in a project i am working on atm, feel free to use it at own risk. I will provide non-periodical updates and hopefully soon a full upgrade to symfony 2.1.x including doctrine orm 2.2.x.</p>
<p>I still did not get the point regarding dependency resolution, so i simply &#8220;composed&#8221; the composer file by writing down my own requirements (&#8220;i want only the hottest, newest stuff!!&#8221;, then tracked down the error messages, removing them by explicetly writing down the missing dependencies by using the latest &#8220;dev-*&#8221; versions. After that i tried to run the project, which actually did not work, but selective downgrade of some of the bundles (framework, security-extra blahblah) finally did the job.<span id="more-2118"></span></p>
<p>Feel free to use it in your own projects:</p>
<pre class="brush: jscript; title: ; notranslate">
{
	&quot;require&quot; : {
              &quot;symfony/symfony&quot; : &quot;v2.0.12&quot;,
              &quot;doctrine/common&quot; : &quot;2.1.4&quot;,
              &quot;doctrine/orm&quot; : &quot;2.1.6&quot;,
              &quot;symfony/finder&quot; : &quot;v2.0.12&quot;,

              &quot;symfony/assetic-bundle&quot; : &quot;2.0-dev&quot;,
              &quot;twig/extensions&quot; : &quot;dev-master&quot;,
              &quot;jms/security-extra-bundle&quot; : &quot;1.1.0&quot;,
              &quot;sensio/framework-extra-bundle&quot; : &quot;2.0-dev&quot;,
              &quot;sensio/distribution-bundle&quot; : &quot;2.0-dev&quot;,
              &quot;sensio/generator-bundle&quot; : &quot;2.0-dev&quot;

 	},
        &quot;autoload&quot; : {
            &quot;psr-0&quot; : {
                &quot;Acme&quot; : &quot;src/&quot;,
            }
        }
}

</pre>
<p>Create a file named &#8220;composer.json&#8221; in your project&#8217;s root directory, then paste the above code into it and save it.</p>
<p>Now run</p>
<pre class="brush: bash; title: ; notranslate">
$ curl -s http://getcomposer.org/installer | php
</pre>
<p>After that, download all dependencies by typing</p>
<pre class="brush: bash; title: ; notranslate">
$ php composer.phar install
</pre>
<p>The easiest way to create a full project including AcmeDemoBundle, AppKernel and the whole stuff is to download the symfony 2 standard distribution without vendors and calling the script from there. The only thing to do is to modify the path to autoload.php, which should point to vendor/.composer/autoload.php.</p>
<p>Now you are able to upgrade your project&#8217;s dependencies to the newest versions by simply modifying the composer.json file. Have fun!.</p>The post <a href="https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/">[Symfony 2] composer.json for a assumed-stable symfony 2 distribution</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2012/04/01/symfony-2-composer-json-for-a-assumed-stable-symfony-2-distribution/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Silex and MongoDB simply</title>
		<link>https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/</link>
					<comments>https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/#comments</comments>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Mon, 30 Jan 2012 14:27:34 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Silex]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[silex]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=2033</guid>

					<description><![CDATA[<p>Using MongoDB in your Silex Project is quite easy. I will show this with my Superleansilexplate and will integrate it there as an example. Since i dont want to integrate MongoDB in Superleansilexplate it will just become an additional gist. Given you have some smaller amount of data like a counter that needs to be &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/" class="more-link">Continue reading<span class="screen-reader-text"> "Silex and MongoDB simply"</span></a></p>
The post <a href="https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/">Silex and MongoDB simply</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Using MongoDB in your Silex Project is quite easy.</p>
<p>I will show this with my <a href="https://github.com/ivoba/superleansilexplate">Superleansilexplate</a> and will integrate it there as an example.<br />
Since i dont want to integrate MongoDB in Superleansilexplate it will just become an additional <a href="https://gist.github.com/1704512">gist</a>.</p>
<p>Given you have some smaller amount of data like a counter that needs to be stored or other loose coupled datasets, we simply speak to MongoDB &#8220;directly&#8221; and store the data via <a href="https://github.com/doctrine/mongodb">Doctrine MongoDB Abstraction Layer</a>.<br />
Since i presume the Data / Document Structure isnt that complex we dont use <a href="https://github.com/doctrine/mongodb-odm">Doctrine MongoDB ODM</a> (the Object Document Mapper).<br />
If you want to use it instead, try this <a href="https://github.com/docteurklein/SilexExtensions">Silex Extensions</a>.</p>
<p><span id="more-2033"></span></p>
<p>So we use this <a href="https://github.com/fate/Silex-Extensions">SilexExtensions</a> collection and install it via git:</p>
<pre class="brush: bash; title: ; notranslate">
 cd mysilexproject
 git clone git@github.com:fate/Silex-Extensions.git vendor/silex-extension
</pre>
<p>Then we install the doctrine mongodb libary manually:</p>
<pre class="brush: bash; title: ; notranslate">
 git clone --recursive https://github.com/doctrine/mongodb vendor/mongodb
</pre>
<p>The extension collection has some more poviders but you can just ignore them and just focus on the MongoDbExtension.</p>
<p>&#8211;<em> i actually dont like extensions collections. i would prefer to clone each extensions individually. thou its not much code overhead, but when it comes to the vendor dependencies it can become quite messy IMHO</em> &#8211;</p>
<p>Alright now the code.<br />
Edit src/app.php and register the namespace for the extension:</p>
<pre class="brush: php; title: ; notranslate">
 $app&#x5B;'autoloader']-&gt;registerNamespace('SilexExtension', __DIR__ . '/../vendor/silex-extension/src');
</pre>
<p>Then register the MongoDbExtension;</p>
<pre class="brush: php; title: ; notranslate">
 $app-&gt;register(new SilexExtension\MongoDbExtension(), array(
 'mongodb.class_path' =&gt; __DIR__ . '/../vendor/mongodb/lib',
 'mongodb.connection' =&gt; array(
 'server' =&gt; 'mongodb://mysecretuser:mysecretpassw@localhost',
 'options' =&gt; array(),
 'eventmanager' =&gt; function($eventmanager) {
 }
 )
 ));
</pre>
<p>and finally query your MongoDB collection of choice and display the resultset as json:</p>
<pre class="brush: php; title: ; notranslate">
$app-&gt;get('/data-from-mongodb', function() use($app) {

$coll = $app&#x5B;'mongodb']-&gt;selectDatabase('mydb')-&gt;selectCollection('mycoll');
 $query = array(
 'query' =&gt; 'value'
 );
 $sort = array(
 'count' =&gt; -1,
 );
 $r = $coll-&gt;find($query)-&gt;sort($sort)-&gt;toArray();
 $response = new Response();
 $response-&gt;headers-&gt;set('Content-type', 'application/json');
 $response-&gt;setContent(json_encode($r));
 return $response;
 });
</pre>
<p>Easy</p>The post <a href="https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/">Silex and MongoDB simply</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2012/01/30/silex-and-mongodb-simply/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Symfony 2 wird super. Oder &#8230;?</title>
		<link>https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/</link>
					<comments>https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Tue, 10 May 2011 22:09:30 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software engineering]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Design Pattern]]></category>
		<category><![CDATA[DIC]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[Software Architecture]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1462</guid>

					<description><![CDATA[<p>Natürlich wird Symfony 2 super. Die Dokumentation ist wie gewohnt zum jetzigen, frühen Zeitpunkt genial, die Architektur durchdacht, die Entwickler-Community steckt sowieso alles in die Tasche, man sieht einfach: Da steckt eine Menge Arbeit, Hirnschmalz und Erfahrung hinter. Aber genug geschleimt ;) Mein Lieblingsthema ist ja zur Zeit der Dependency Injection Container. Und irgendwie stinkt &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/" class="more-link">Continue reading<span class="screen-reader-text"> "Symfony 2 wird super. Oder &#8230;?"</span></a></p>
The post <a href="https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/">Symfony 2 wird super. Oder …?</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Natürlich wird Symfony 2 super. Die Dokumentation ist wie gewohnt zum jetzigen, frühen Zeitpunkt genial, die Architektur durchdacht, die Entwickler-Community steckt sowieso alles in die Tasche, man sieht einfach: Da steckt eine Menge Arbeit, Hirnschmalz und Erfahrung hinter. Aber genug geschleimt ;) </p>
<p>Mein Lieblingsthema ist ja zur Zeit der Dependency Injection Container. Und irgendwie stinkt mir die ganze Container-Konfiguration noch gewaltig. Meine <a href="https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/">kläglichen Versuche</a>, selbst mal so was ähnliches wie eine brauchbare Autowiring-Implementierung herunterzubrechen, waren natürlich auch bzw. erst recht nicht der große Wurf &#8211; was vor allem daran lag, dass ich den Service Container und damit den ganzen Sinn und Zweck des Ganzen einfach mal wegrationalisiert hatte &#8211; Loose Coupling sieht natürlich anders aus, das sei den Kritikern zugestanden. Ich verteidige mich mal dadurch, dass ich eigentlich nur mal mit Mixins rumspielen wollte &#8211; da hab&#8217; ich wohl die eine oder andere Begrifflichkeit durcheinander geworfen. </p>
<p>Aber um mal zu des Pudels Kern zu kommen: Ist es wirklich so geil, mit kilometerlangen XML-Dateien, &#8216;ner Menge Initialisierungscode und ohne mit der heißgeliebten Code-Completion in der IDE meiner Wahl ein Paradigma zu kaufen, das im speziellen Anwendungskontext &#8211; nicht im Framework-Kontext &#8211; eher selten Anwendung findet? </p>
<p><span id="more-1462"></span></p>
<p>Es ist doch so: PHP bietet zwar mittlerweile eine vernünftige Reflection API, aber wenig (keine) Möglichkeiten, Code zur Compile- oder Runtime effizient zu injizieren (vorbei bspw. an der Sichtbarkeit, was für Property Injection aus meiner Sicht erforderlich wäre). Mit Handständen geht das mittels der Reflection API, noch fieser mit bspw. Runkit. </p>
<p>Somit ist &#8211; (natürlich nur aus meiner Sicht, was im Übrigen für den gesamten &#8220;Complaint&#8221; gilt &#8211; dabei wäre ich wirklich froh, berichtigt zu werden) jeder Versuch, die Konfiguration eines wie auch immer gearteten, auf PHP sitzenden, DIC mit Syntactic Sugar anzureichern, vergeblich. Und Syntactic Sugar ist dringend vonnöten, um das Zeug in der Praxis RAD-tauglich zu machen. Nehme ich PHP den RAD-Faktor, was bleibt denn dann noch übrig?</p>
<p>Symfony 2 behilft sich damit, einen DI-Container zu definieren und ihn als PHP-Code wegzucachen. Dieser hat dann Accessoren für alle definierten Services, Constructor-Injection ist durch Referenzierung in den Konfigurationsdateien möglich. Die Doku spricht zusätzlich von Setter- und Property-Injection, dazu konnte ich aber irgendwie keine dokumentierten Beispiele finden. Es gibt aber immerhin die Möglichkeit, Methoden in der Service-Klasse als Pre- oder Post-Initialization Interceptoren auszuführen.</p>
<p>Letztlich tut der Container, was er soll: Abhängigkeiten in beliebige Instanzen zu injizieren. Bei Bedarf auch gegen ein Interface, aber das ist letztlich aufgrund des Sprachentwurfs nur optional (Was impliziert, das man auf Kosten riesiger Flexibilität &#8211; die man nicht braucht &#8211; schnell mal riskiert, durch einen falsch konfigurierten DI-Container seine Anwendung kaputt zu machen).</p>
<p>Aber der Aufwand steht meiner Meinung nach noch in keinem Verhältnis zum Nutzen. Am Beispiel einer Controller Extension, die als Service definiert wird, möchte ich das mal demonstrieren. Die offizielle Symfony 2-Dokumentation sagt, dass</p>
<blockquote><p>To keep things simple, Symfony2 by defaults does not require that controllers be defined as services. Furthermore Symfony2 injects the entire service container into your controller.
</p></blockquote>
<p>Das ist immerhin schon einmal eine Information. Das Standardverhalten ist also, dass ich automagisch eine Controllerklasse habe, die den Container kennt (Wie? Magisch? Ich dachte, Symfony 2 hat die Magie zugunsten transparentem Code und ständiger Kontrolle über jeden Aspekt des Core-Frameworks aufgegeben?). Dadurch, dass er ein ContainerAware Interface implementiert, kennt er auch einen Shortcut auf </p>
<pre class="brush: php; title: ; notranslate">$this-&gt;container-&gt;get('serviceid')</pre>
<p>, nämlich </p>
<pre class="brush: php; title: ; notranslate">$this-&gt;get('serviceid');</pre>
<p>. Um Bspw. ein Doctrine-Entity zu persistieren, reichen &#8220;ein paar codezeilen&#8221;:</p>
<pre class="brush: php; title: ; notranslate">
     $em = $this-&gt;get('doctrine.orm.entity_manager');
     $em-&gt;???($myEntity);
</pre>
<p>Wie hieß die Methode da am Entity Manager jetzt nochmal? Das ist das erste Problem: Dadurch, dass alle Services anonym im Service Container herumdümpeln bzw. auf ihre Instanziierung warten, habe ich in meiner IDE keinerlei Code-Completion mehr. Um das wieder zu erreichen, muss ich entweder<br />
&#8211; einen Accessor schreiben (getEntityManager()) und diesen mittels PHP-Doc type-hinten (annotieren) oder<br />
&#8211; mindestens einen magischen Docblock davorsetzen, der genau *meiner* IDE die Möglichkeit gibt, den Variablentyp zu erraten (aber ggf. proprietär ist, d.h. in anderen IDEs nicht unbedingt funktionieren muss). Für die Netbeans IDE gibt es dafür bspw. das &#8220;<a href="http://blogs.oracle.com/netbeansphp/entry/defining_a_variable_type_in">vdoc</a>&#8220;-Feature.</p>
<p>Das ganze setzt natürlich voraus, dass ich *weiß*, welches Interface der Service doctrine.orm.entity_manager implementiert bzw wie die konkrete Klasse (samt Namespace) desselben heißt. Und vorher muss ich auch noch wissen, wie überhaupt der *Servicename* des Entity Managers lautet. </p>
<p>Bin ich also komplett Ahnungslos, rufe ich erstmal ein Terminal auf, tippe sowas wie</p>
<pre class="brush: jscript; title: ; notranslate">$ app/console container:debug --show-private</pre>
<p> ein und suche mir anschließend in der kilometerlangen Liste genau die Services zusammen, die ich brauche.</p>
<p>Dafür brauche ich als Framework-Newbie schonmal richtig tiefgehende Kenntnisse darüber, was ein DIC überhaupt ist, tut und zur Konfiguration erfordert.</p>
<p>Um also das, was &#8220;früher&#8221; ein </p>
<pre class="brush: php; title: ; notranslate">new Cart($color, $maxSpeed)-&gt;save()</pre>
<p> war, zu erreichen, muss ich nun erstmal ganz schön viel Sport treiben (dieses Beispiel nur exemplarisch, es steht außer Frage, dass die Doctrine 2-Architektur wirklich klasse ist. Das Manko aus meiner Sicht ist die Integration in Sf2, nicht der ORM-Layer an sich.)  </p>
<p>Möchte ich den Accessor der ContainerAware-Implementierung am Controller vermeiden und die Services &#8220;direkt&#8221; injizieren, muss ich ihn selbst als Service am DIC registrieren. Wie das funktioniert, würde den Rahmen sprengen, nur so viel: Der Aufwand steht aus meiner Sicht wieder in keinem Verhältnis zum Ergebnis. Allerdings habe ich damit den Vorteil, dass ich bspw. keine abstrakte Controllerklasse mehr zu erweitern habe &#8211; der Controller kann ein simples Popo sein. Dass es aber nicht zu simpel sein darf, zeigt bspw., das ich trotz alledem mindestens einen Constructor definieren muss, der eben alle benötigten Services aufnimmt und an Instanzvariablen bindet. Und das können einige sein &#8211; fängt an beim Templating, geht übers Formframework, ggf. den Entity-Manager, einen Mailer und was einem sonst noch so einfällt. Dabei wollten wir doch ab jetzt nur noch leichtgewichtige Controller haben?</p>
<p>Meiner Meinung nach liegt die Lösung der Malaise in zwei Alternativen: Man baut so lange Abstracts, die den ganzen Kram als Shortcuts bereitstellen (dann hätten wir bspw. wieder eine komplexe, abstrakte Kontrollerklasse, die mindestens alles kennt, was in Symfony 1 noch dem ApplicationContext gehörte) &#8211; womit wir unser Loose Coupling Pardigma wieder in den Schrank zu den übrigen Ideen stellen können, die im Nachgang irgendwie doch nicht funktionierten. Oder legt Autowiring drüber. </p>
<p>Flow 3 baut bspw. an einem DIC + Autowiring, der alle verwalteten Services durch eine Kombination der Analyse von Annotationen (also PHP-Doccomments) und Signaturen (Typehints) direkt an die erzeugten Instanzen bindet. Die Konfiguration scheint damit sehr viel leichtgewichtiger. </p>
<p>Grails (was so weit ich weiß auf der Spring IOC-Komponente sitzt) geht noch einen Schritt weiter und mappt Instanzvariablen durch reine Naming-Conventions: Wenn also eine Instanzvariable auf &#8220;Service&#8221; endet und es zur Eigenschaft &#8220;mailerService&#8221; einen passenden Service &#8220;mailer&#8221; gibt, wird dieser automagisch injiziert. Kein zusätzlicher Code noch Annotations vonnöten.</p>
<p>Ich wüsste aber nicht, wie man solche Features wirklich performanceneutral, effizient und stabil auf einer Plattform wie PHP aufsetzen könnte &#8211; dafür ist die Sprache einfach (noch) nicht weit genug. </p>
<p>Abschließend bleibt ein übler Nachgeschmack &#8211; und der Eindruck, dass man sich hier fatal an den XML-&#8220;Konfigurationswahnsinn&#8221; der entsprechenden Java-&#8220;Vorbilder&#8221; annähern möchte. Wo doch gerade in diesem Lager  intensiv daran gearbeitet wird, genau davon abzurücken und Konfigurationen eben durch Konventionen zu ersetzen.  </p>
<p>Was denkt ihr? Kann das ganze doch durch Routine punkten, sodass es durch ein wenig konkrete Projekterfahrung doch ganz leicht von der Hand geht? Wird der DIC im Tagesgeschäft schon intensiv benutzt, oder werden nur die Standardfunktionen des Frameworks verwendet und das Zeug &#8220;unter der Haube&#8221; doch lieber den Framework- und Bundle-Entwicklern überlassen? Ich bin wieder sehr gespannt auf Meinungen und Kritik&#8230;</p>The post <a href="https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/">Symfony 2 wird super. Oder …?</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2011/05/11/symfony-2-wird-super-oder/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Distinct in Doctrine</title>
		<link>https://nerdpress.org/2011/04/16/distinct-in-doctrine/</link>
					<comments>https://nerdpress.org/2011/04/16/distinct-in-doctrine/#comments</comments>
		
		<dc:creator><![CDATA[Ivo Bathke]]></dc:creator>
		<pubDate>Sat, 16 Apr 2011 13:51:33 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Sql]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1454</guid>

					<description><![CDATA[<p>Wenn man DISTINCT in einem Query und Doctrine nutzen will muss man mit Aliasen arbeiten! Sonst baut Doctrine einem da immer die id mit in den Query und das DISTINCT wird damit ausgehebelt. So gehts nicht: Doctrine::getTable('propose') -&#62;createQuery('propose') -&#62;select('propose.cat') -&#62;distinct() -&#62;fetchArray(); Denn das wird dazu: SELECT DISTINCT p.id AS p__id, p.cat AS p__cat FROM propose &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2011/04/16/distinct-in-doctrine/" class="more-link">Continue reading<span class="screen-reader-text"> "Distinct in Doctrine"</span></a></p>
The post <a href="https://nerdpress.org/2011/04/16/distinct-in-doctrine/">Distinct in Doctrine</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Wenn man <strong>DISTINCT</strong> in einem Query und Doctrine nutzen will <em>muss</em> man mit Aliasen arbeiten!<br />
Sonst baut Doctrine einem da immer die <strong>id</strong> mit in den Query und das <strong>DISTINCT</strong> wird damit ausgehebelt.</p>
<p><span id="more-1454"></span></p>
<p>So gehts nicht:</p>
<pre class="brush: php; title: ; notranslate">
Doctrine::getTable('propose')
-&gt;createQuery('propose')
-&gt;select('propose.cat')
-&gt;distinct()
-&gt;fetchArray();
</pre>
<p>Denn das wird dazu:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT DISTINCT p.id AS p__id, p.cat AS p__cat FROM propose p
</pre>
<p>so gehts:</p>
<pre class="brush: php; title: ; notranslate">
Doctrine::getTable('propose')
-&gt;createQuery('propose')
-&gt;select('propose.cat as cat')
-&gt;distinct()
-&gt;fetchArray();
</pre>
<p>Denn das wird dazu:</p>
<pre class="brush: sql; title: ; notranslate">
SELECT DISTINCT p.cat AS p__0 FROM propose p
</pre>The post <a href="https://nerdpress.org/2011/04/16/distinct-in-doctrine/">Distinct in Doctrine</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2011/04/16/distinct-in-doctrine/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Symfony 2 Standard Edition released</title>
		<link>https://nerdpress.org/2011/03/07/symfony-2-standard-edition-released/</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Mon, 07 Mar 2011 17:20:38 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software engineering]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Doctrine 2]]></category>
		<category><![CDATA[Standard Edition]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1401</guid>

					<description><![CDATA[<p>Ab heute, dem 7. 3. 2011, steht auf http://symfony.com die &#8220;Standard-Edition&#8221; der neuesten Version 2 des populären RAD-Frameworks zum Download bereit. Bereits am vergangenen Wochenende ging die neue Website des Projekts online. Symfony 2 wird als Sammlung loser gekoppelter Komponenten &#8211; sog. &#8220;Bundles&#8221; &#8211; in mehreren Ausgaben erhältlich sein. Zum jetzigen Zeitpunkt existiert bereits eine &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2011/03/07/symfony-2-standard-edition-released/" class="more-link">Continue reading<span class="screen-reader-text"> "Symfony 2 Standard Edition released"</span></a></p>
The post <a href="https://nerdpress.org/2011/03/07/symfony-2-standard-edition-released/">Symfony 2 Standard Edition released</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Ab heute, dem 7. 3. 2011, steht auf http://symfony.com die &#8220;Standard-Edition&#8221; der neuesten Version 2 des populären RAD-Frameworks zum Download bereit. Bereits am vergangenen Wochenende ging die neue Website des Projekts online.<br />
<span id="more-1401"></span><br />
Symfony 2 wird als Sammlung loser gekoppelter Komponenten &#8211; sog. &#8220;Bundles&#8221; &#8211; in mehreren Ausgaben erhältlich sein. Zum jetzigen Zeitpunkt existiert bereits eine Sandbox und eine davon abgeleitete &#8220;Standard-Edition&#8221;, die wie gewohnt ein festes Code-Verzeichnislayout vorgeben.</p>
<p>Als zukünftige Ausgaben denkbar sind ein Symfony2-basierendes CMF (Content Management Framework) oder eine auf die speziellen Befürfnisse von Online-Shops zugeschnittene Bundle-Sammlung.</p>
<p>Der Code ist noch nicht als stabil deklariert. Die bereits vorhandene und wie immer intensiv gepflegte Referenz-Dokumentation lädt bereits jetzt zum Reinschnuppern und Ausprobieren ein.  </p>The post <a href="https://nerdpress.org/2011/03/07/symfony-2-standard-edition-released/">Symfony 2 Standard Edition released</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Symfony 2 PR3: doctrine:schema:create liefert &#8220;No Metadata Classes to process.&#8221;</title>
		<link>https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/</link>
					<comments>https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sun, 17 Oct 2010 16:33:42 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[active entity]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[Doctrine 2]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[symfony 2]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1131</guid>

					<description><![CDATA[<p>Die Doku stellt in Aussicht, dass man den &#8220;normalen&#8221; Doctrine-Namespace-Shortcut benutzen kann, also bspw. @Entity anstelle von @DoctrineOrmMappingEntity. Funktioniert aber nicht, weil in irgend einer Service-Configuration dieser Namespace auf einen Alias gemapped wird, der da lautet &#8220;orm&#8221;. Die Syntax lautet aber nun auch nicht @ormEntity, sondern @orm:Entity. Schreibt man sein Model also bspw. so: &#60;?php &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/" class="more-link">Continue reading<span class="screen-reader-text"> "Symfony 2 PR3: doctrine:schema:create liefert &#8220;No Metadata Classes to process.&#8221;"</span></a></p>
The post <a href="https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/">Symfony 2 PR3: doctrine:schema:create liefert “No Metadata Classes to process.”</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Die <a href="http://docs.symfony-reloaded.org/guides/doctrine/orm/overview.html">Doku</a> stellt in Aussicht, dass man den &#8220;normalen&#8221; Doctrine-Namespace-Shortcut benutzen kann, also bspw. @Entity anstelle von @DoctrineOrmMappingEntity. Funktioniert aber nicht, weil in irgend einer Service-Configuration dieser Namespace auf einen Alias gemapped wird, der da lautet &#8220;orm&#8221;. Die Syntax lautet aber nun auch nicht @ormEntity, sondern @orm:Entity. Schreibt man sein Model also bspw. so:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

namespace ApplicationHelloBundleEntity;

/**
 * ApplicationHelloBundleEntityUser
 *
 * @orm:Table(name=&quot;users&quot;)
 * @orm:Entity
 */
class User
{
  /**
   * @var integer $id
   *
   * @orm:Column(name=&quot;id&quot;, type=&quot;integer&quot;)
   * @orm:Id
   * @orm:GeneratedValue(strategy=&quot;AUTO&quot;)
   */
  protected $id;
</pre>
<p>sollten alle CLI-Tasks auch wunderbar funktionieren. Es bleibt zu hoffen, dass die DI-Services eine reichhaltige Parameter-Dokumentation spendiert kriegen und das ganze Bundle-System eine transparente, dokumentierte API erhalten (wo zum Teufel liegt in der Sandbox bitte der versprochene Doctrine-Controller?) </p>
<p>Die Einstellung findet sich übrigens in der Service-Configuration unter src/vendor/symfony/src/Symfony/Bundle/DoctrineBundle/Resources/config/orm.xml:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;service id=&quot;doctrine.orm.metadata_driver.annotation.reader&quot; class=&quot;%doctrine.orm.metadata.annotation_reader_class%&quot;&gt;
            &lt;call method=&quot;setAnnotationNamespaceAlias&quot;&gt;
              &lt;argument&gt;DoctrineORMMapping&lt;/argument&gt;
              &lt;argument&gt;orm&lt;/argument&gt;
            &lt;/call&gt;
        &lt;/service&gt;
</pre>
<p>Ist leicht zu finden, wenn man weiß, wonach man suchen muss. Ich denke, es ist am einfachsten, die Service-Definition des DI-Containers an entsprechender Stelle an seine eigenen Bedürfnisse anzupassen. Wie das zuverlässig und projektübergreifend funktioniert, erkläre ich vielleicht mal, wenn ich&#8217;s selbst gerafft hab.</p>
<p>Achso, <a href="http://groups.google.com/group/symfony-devs/browse_thread/thread/a2912efa4b64002a/4606d5407258dd2d?show_docid=4606d5407258dd2d">hier</a> noch der Nebensatz (etwas herunter scrollen), in dem gesagt wird, das Jonathan irgendwann mal das &#8220;orm:&#8221; Präfix einführt. Symfony 2 ist definitiv noch nicht ready for production (was aber auch niemand behauptet).</p>The post <a href="https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/">Symfony 2 PR3: doctrine:schema:create liefert “No Metadata Classes to process.”</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2010/10/17/symfony-2-pr3-doctrineschemacreate-liefert-no-metadata-classes-to-process/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Dependency Injection mit PHP 5.3, Runkit-Erweiterung und Doctrine 2-Annotationen</title>
		<link>https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/</link>
					<comments>https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/#comments</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Sun, 26 Sep 2010 15:33:33 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software engineering]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Annotations]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Doctrine 2]]></category>
		<category><![CDATA[IoC]]></category>
		<category><![CDATA[PHP 5.3]]></category>
		<category><![CDATA[Runkit]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=1085</guid>

					<description><![CDATA[<p>Unter Dependency Injection versteht man heute nicht nur ein einfaches Entwurfsmuster, sondern vor allem Framework-gestützte Mechanismen, die den konkreten Implementierungsaufwand verringern (Entwicklungszeitoptimierung), dem Entwickler bessere Übersicht über Abhängigkeiten zu schaffen (Applicationdesignoptimierung) und die Anzahl der Instanzen gleichen Prototyps zu minimieren (Performanceoptimierung). Heute möchte ich einen alternativen, vielleicht pragmatischeren Ansatz als der andererer populärer Implementierungenn herbeispinnen, &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/" class="more-link">Continue reading<span class="screen-reader-text"> "Dependency Injection mit PHP 5.3, Runkit-Erweiterung und Doctrine 2-Annotationen"</span></a></p>
The post <a href="https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/">Dependency Injection mit PHP 5.3, Runkit-Erweiterung und Doctrine 2-Annotationen</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>Unter <a href="http://de.wikipedia.org/wiki/Dependency_Injection">Dependency Injection</a> versteht man heute nicht nur ein einfaches Entwurfsmuster, sondern vor allem Framework-gestützte Mechanismen, die den konkreten Implementierungsaufwand verringern (Entwicklungszeitoptimierung), dem Entwickler bessere Übersicht über Abhängigkeiten zu schaffen (Applicationdesignoptimierung) und die Anzahl der Instanzen gleichen Prototyps zu minimieren (Performanceoptimierung).</p>
<p>Heute möchte ich einen alternativen, vielleicht pragmatischeren Ansatz als der andererer populärer Implementierungenn herbeispinnen, um Dependency Injection (DI) in PHP 5.3 zu realisieren.<br />
<span id="more-1085"></span><br />
Für diverse Programmiersprachen gibt es &#8211; auf den jeweiligen Anwendungsbereich mehr oder weniger spezialisierte &#8211; sogenannte Dependency-Injection (DI)-Container. Der DI-Container als solcher dient im Grunde als Manager oder Konfigurator, der das Zusammenspiel unserer Abhängigkeiten definiert &#8211; meist auf Grundlage einer Konfigurationsdatei, die bspw. in XML vorliegt:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&quot;&gt;

  &lt;bean id=&quot;...&quot; class=&quot;...&quot;&gt;
    &lt;!-- collaborators and configuration for this bean go here --&gt;
  &lt;/bean&gt;

  &lt;bean id=&quot;...&quot; class=&quot;...&quot;&gt;
    &lt;!-- collaborators and configuration for this bean go here --&gt;
  &lt;/bean&gt;

  &lt;!-- more bean definitions go here... --&gt;

&lt;/beans&gt;
</pre>
<p>(Quelle: <a href="http://static.springsource.org/spring/docs/2.0.x/reference/beans.html">Springsource</a>)</p>
<p>Eine weitere Möglichkeit Abhängigkeiten zu definieren, bietet das <a href="http://en.wikipedia.org/wiki/Convention_over_configuration">Convention Over Configuration-Paradigma</a>: Heißt bspw. eine Member-Variable &#8220;Mailservice&#8221;, so kann der zugrundeliegende DI-Container entsprechend konfiguriert werden, sodass bei Instanziierung automatisch eine Klasse gleichen Namens (Mailservice) instanziiert und an das Objekt gebunden wird (so macht&#8217;s bspw. Grails in seinen MVC-Controller-Instanzen, wobei hier natürlich wieder das <a href="http://static.springsource.org/spring/docs/2.0.x/reference/beans.html">Spring IoC</a> (Das hat nichts mit dem internationalen olympischen Komitee zu tun, sondern ist die Abkürzung für &#8220;Inversion of Control&#8221; und steht gleichbedeutend für &#8220;Dependency Injection&#8221;). Diese Implementierung erfordert natürlich ausgereifte Introspektionsmechanismen der zugrundeliegenden Programmiersprache (Stichwort &#8220;<a href="http://de.wikipedia.org/wiki/Reflexion_(Programmierung)">Reflection</a>&#8220;), außerdem muss man dem DI bzw. IOC-Container vorher beigebracht haben, <em>welche</em> Klassen oder Verzeichnisstrukturen überhaupt durchsucht und unter &#8220;DI-Kontrolle&#8221; gestellt werden müssen &#8211; ein zusätzlicher Programmieraufwand ist also immer noch gegeben. Unvorhersehbarkeiten im Code und eine erhöhte WTF&#8217;s/min-Rate kommen dabei frei Haus.</p>
<p>PHP bieted zu dem ganzen Thema ab Werk erstmal &#8211; nix. Die <a href="http://php.net/manual/en/book.reflection.php">Reflection-API</a> ist aber schonmal ein ausgereiftes Werkzeug, um definierte Abhängigkeiten auszuwerten. Das allerdings ausschließlich mittels lesendem Zugriff auf Metadaten von bspw. Klassen, Methoden oder auch System- bzw. benutzerdefinierten Funktionen. Schreibende Operationen sind im Sprachkern erst einmal nicht vorgesehen. Es ist also prinzipiell möglich, zur Laufzeit Abhängigkeiten durch Konvention zu definieren, die Auflösung selbiger ist aber &#8220;mit Boardmitteln&#8221; nicht zu realisieren. </p>
<p>Ein eigenes Sprachkonstrukt wie <a href="http://de.wikipedia.org/wiki/Mixin">Mixins</a> ist auch (noch) nicht implementiert, und anonyme (&#8220;<a href="http://de.wikipedia.org/wiki/Lambda-Funktion">Lambda</a>&#8220;)-Funktionen lassen sich nicht wie in Javascript oder auch Groovy direkt an den Objekt-Prototypen hängen oder auch an einzelne Instanzen, sondern müssen mühsam &#8220;by reference&#8221; gezogen und dann erst ausgewertet werden.</p>
<p>Javascript:</p>
<pre class="brush: jscript; title: ; notranslate">
  var foo = function() { }
  foo.prototype.bar = function() { return &quot;bar&quot;; }
  foo.baz = foo.prototype.bar;

  var foobar = new foo;
  foo.bar(); // -&gt; &quot;bar&quot;
  foo.baz(); // -&gt; &quot;bar&quot;
</pre>
<p>PHP:</p>
<pre class="brush: php; title: ; notranslate">
  $foo = new stdClass();
  $foo-&gt;bar = function() 
  {
    return &quot;bar&quot;;
  }
  $foo-&gt;bar(); // method not found
   
  $bar = $foo-&gt;bar;
  $bar(); // -&gt; &quot;bar&quot;
</pre>
<p>Zugegeben: Gäbe es bereits Mixins oder Prototypen im PHP-Kontext, wäre die Implementierung eines DI-Containers wohl eher unspannend, mindestens aber überflüssig. Dennoch fehlt eine zuverlässige Möglichkeit, PHP-Instanzen zur Laufzeit mit neuen Methoden anreichern zu können. Daher gehen die meisten PHP-DI-Frameworks immer den Weg über einen recht aufgeblähten DI-Container. Dieser macht aber im Grunde nichts anderes, als Referenzen zu verwalten. Der Container selbst wird dann an die anzureichernde Instanz gebunden, im Idealfall eventuell aber noch via magischer Methode __call() verborgen. Dann aber muss die zu aufnehmende Instanz wiederum mindestens ein Interface &#8220;Injectable&#8221;  o.Ä. implementieren. Letzlich aber passiert am Ende immer folgendes:</p>
<pre class="brush: php; title: ; notranslate">
class myController extends Controller
{
  public function indexAction(HttpRequest $request)
  {
    $db = $this-&gt;getService('Database');
  }
}
</pre>
<p>Der Service-Container übernimmt also die klassische Aufgabe des &#8220;ApplicationContext&#8221;: Er managed Referenzen, rückt diese aber erst &#8220;on demand&#8221; heraus. Meiner Meinung hat man dabei nicht allzu viel gewonnen, vor allem, wenn das obige Codeschnippsel noch eine Menge Konfiguration, Code zum Bootstrappen des DI-Containers und/oder Caching voraussetzt.</p>
<p>Ich persönlich würde mir dann doch eher &#8220;ganz oldschool&#8221; ein paar getter/setter zusätzlich schreiben und mich einfach darauf verlassen, dass der gute, alte ApplicationContext sowieso (fast) alles enthält, was ich brauch&#8217;, mit der Konsequenz, dass dieser eben nicht gerade leichtgewichtig ist.</p>
<p>Wozu also das ganze?</p>
<h2>Ein alternativer DI-Container mit Doctrine 2 Annotations und Runkit</h2>
<p>Die Annotations-Implementierung von Doctrine 2 ist einfach und mächtig genug, um eine beliebigen Klasse mit Metainformationen auszustatten, die die zu injizierenden Abhängigkeiten definieren. Runkit ermöglicht es, auf Basis dieser Metadaten Abhänigkeiten an das ensprechende Objekt zu binden &#8211; zur Laufzeit und ohne zusätzliche Implementierung von Schnittstellen o.Ä. Vom Prinzip her sollte es also möglich sein, eine Klasse zu schreiben, diese zu annotieren und dann bei Instanziierung automatisch alle gewünschten Abhängigkeiten zur Verfügung stehen zu haben. Ein Codebeispiel:</p>
<p>index.php:</p>
<pre class="brush: php; title: ; notranslate">
  require __DIR__ . '/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php';

  use DoctrineCommonClassLoader;
  
  $classLoader = new ClassLoader('DoctrineCommon', __DIR__ . '/lib/vendor/doctrine-common/lib');
  $classLoader-&gt;register();

  $classLoader = new ClassLoader('deifschleife', __DIR__ . '/lib');
  $classLoader-&gt;register();

  // INITIALISIERUNG DES DI-CONTAINERS
  $di_container = new deifschleifediContainer;
  
  $di_container-&gt;setClassnames(array(
    'deifschleifeDITest'
  ));
  
  // &quot;AUFNEHMENDE&quot; KLASSE
  $test = new deifschleifeDITest();

  // GEHÖRT deifschleifeADependency
  echo $test-&gt;foo();
  
  // GEHÖRT deifschleifeAnotherDependency
  echo $test-&gt;bar();

  // GEHÖRT deifschleifeYetAnotherDependency
  echo $test-&gt;baz();
  
  // GIBT's NICHT, ÜBER __call() ABGEFANGEN
  echo $test-&gt;methodThatDoesNotExist();
</pre>
<p>Kurz erklärt:</p>
<pre class="brush: php; title: ; notranslate">
$di_container = new deifschleifediContainer;
$di_container-&gt;setClassnames(array(
    'deifschleifeDITest'
  ));
</pre>
<p>Instanziiert den DI-Container und stellt eine Klasse (deifschleifeDITest) unter seine &#8220;Kontrolle&#8221;.</p>
<pre class="brush: php; title: ; notranslate">
$test = new deifschleifeDITest();

  // GEHÖRT deifschleifeADependency
  echo $test-&gt;foo();
  
  // GEHÖRT deifschleifeAnotherDependency
  echo $test-&gt;bar();

  // GEHÖRT deifschleifeYetAnotherDependency
  echo $test-&gt;baz();
  
  // GIBT's NICHT, ÜBER __call() ABGEFANGEN
  echo $test-&gt;methodThatDoesNotExist();
</pre>
<p>Instanziiert die überwachte Klasse deifschleifeDITest und ruft einige Methoden auf, die sämtlich aus anderen Klassen nach DITest injiziert wurden. Die letze Methode ist nirgends existent. deifschleifeDITest implementiert ausschließlich __call(), ansonsten ist die Klasse (fast) leer:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
namespace deifschleife;

/**
 * @Services({
 *   @Service(
 *    class=&quot;deifschleifeADependency&quot;,
 *    constructorArgs={
 *      &quot;pong&quot;
 *    }
 *  ),
 *  @Service(
 *    class=&quot;deifschleifeAnotherDependency&quot;,
 *    constructor={&quot;deifschleifeAnotherDependency&quot;, &quot;getAnotherDependency&quot;}
 *  ),
 *  @Service(
 *    class=&quot;deifschleifeYetAnotherDependency&quot;,
 *    constructor=&quot;makeYetAnotherDependency&quot;
 *  )
 * })
 */
class DITest
{
  public function __call($method, $args)
  {
    return sprintf(&quot;Called __call, Method: %s, Args: %s&quot;, $method . '()', implode(', ', $args));
  }

  public function makeYetAnotherDependency()
  {
    return new YetAnotherDependency();
  }
}
</pre>
<p>Interessant sind die Klassen-Annotationen ganz oben: @Services teilt dem Doctrine 2 Annotation Parser mit, dass hier eine Reihe von PHP-Klassen, die zu injizierende Methoden enthalten, zusammenzusuchen sind. Jeder einzelne @Service in der Liste kann noch grob konfiguriert werden, so kann bspw. eine eigene Factory-Methode für jede Dependency angegeben werden.</p>
<p>Die einzelnen Dependencies sind &#8220;ganz normale&#8221; PHP-Klassen. Intern passiert folgendes: Die Runkit-Erweiterung dient dazu, über runkit_method_add() &#8220;on the fly&#8221; eine magische Methode __call() an die mit zusätzlcihen Methoden anzureichernde Klasse deifschleifeDITest zu binden. Existiert bereits eine entsprechende Methode __call(), wird diese intern via runkit_method_rename() umbenannt und am Ende von __call() (neu) aufgerufen. Das bedingt natürlich eine gewisse Rücksichtname bei zusätzlicher Verwendung von __call(). </p>
<p>Die Idee unterscheidet sch also nur unwesentlich von bereits vorhandenen Konzepten, spart aber einige Schritte ein:</p>
<p>1.) Man benötigt keine Abstrakte Klasse und/oder Interface, die dass die getService()-Logik bereitstellt.<br />
2.) Man benötigt kaum zusätzliche Konfigurationsaufwand &#8211; eine einfache Annotation im PHPDOc-Comment-Format reicht aus (es spricht allerdings nichts dagegen, je nach Gschmäckle einen Config-Adapter dazwischen zu schieben, der das Mapping via XML oder bspw. Yaml erlaubt)<br />
3.) Man kann auf Proxy-Instanzen verzichten, die __call() transparent bereitstellen.</p>
<p>Fazit: Es ist prinzipiell möglich, Dependency Injection &#8211; passender noch &#8220;Mixins&#8221; &#8211; mit PHP zu realisieren, ohne nennenswert viel Codeoverhead zu produzieren. </p>
<p>Allerdings muss man berücksichtigen, dass Runkit eine experimentelle Erweiterung ist, deren Zuverlässigkeit in komplexen Projekten nicht vorauszusehen ist. Außerdem wird es sehr wahrscheinlich in Bälde ein mächtiges, neues Sprachkonstrukt geben, das Mixins ermöglicht (siehe <a href="http://wiki.php.net/rfc/traits">RFC zu Traits</a>). Und natürlich kann ich mir auch totalen Murks zusammen gereimt haben, denn sicherlich sind die existierenden Implementierungen von fähigeren Architekten entworfen worden und haben bestimmt ihre Daseinsberechtigungen in einem Kontext, den ich vielleicht einfach noch nicht erfasst haben. Comments dazu wären wir sehr willkommen!</p>
<h2>Ausblick</h2>
<p>Die Lösung zentral über __call() ist die Schnelle, aber nicht optimale. Vorstellbar ist eine injizierung sämtlicher öffentlicher Methoden wie runkit_method_add, und ein globaler Accessor, der die Objektinstanz der Abhängigkeit liefert. Das ganze könnte man (optional) konfigurierbar gestalten (über Doctrine 2 Annotationen), um eventuellen Namenskonflikten auszuweichen.</p>
<h2>Test-Sourcen</h2>
<p>Die PHP-Quelltexte zu den obigen Beispielen kann man hier herunterladen:<br />
<a href="http://ifschleife.de/dependency_injection.tar.gz">http://ifschleife.de/dependency_injection.tar.gz</a></p>
<p>Ich habe die DoctrineCommon-Package bereits beigelegt, das Beispiel sollte also unter PHP5.3 funktionieren (bitte di.php aufrufen, der Rest ist noch durchsetzt mit Doctrine 2 Testklamotten).</p>
<p>Eine Anleitung, wie man Runkit unter php5.3 zum laufen kriegt, gibt es <a href="http://d.hatena.ne.jp/shimooka/20100729/1280379407">hier</a> (Japanisch, aber der Quelltext ist auf PHP ;))</p>
<p>Die Test-Sourcen liegen, wie in den obigen Codebeispielen beschrieben, unter lib/de/ifschleife. Ich möchte betonen, dass das nur eine Art Fallstudie ist, ich wäre aber über jeden Kommentar erfreut, der mir widerlegt oder bestätigt, ob man den programmatischen Ansatz vielleicht weiterverfolgen sollte. </p>
<p>Vielen Dank für die Aufmerksamkeit! :)</p>The post <a href="https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/">Dependency Injection mit PHP 5.3, Runkit-Erweiterung und Doctrine 2-Annotationen</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2010/09/26/dependency-injection-mit-php-5-3-runkit-erweiterung-und-doctrine-2-annotationen/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>The only valid measurement of code quality: WTFs/minute</title>
		<link>https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/</link>
					<comments>https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/#comments</comments>
		
		<dc:creator><![CDATA[Max Girkens]]></dc:creator>
		<pubDate>Wed, 17 Feb 2010 09:25:43 +0000</pubDate>
				<category><![CDATA[Doctrine ORM]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[EntityManager]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[writeBehind]]></category>
		<category><![CDATA[WTFs]]></category>
		<guid isPermaLink="false">https://nerdpress.org/?p=810</guid>

					<description><![CDATA[<p>oder: Doctrine 2 wird wohl ziemlich gut. Hier gibt es ein paar Notizen von Jonathan Wage&#8217;s Präsentation dazu! Sehr cool klingt unter anderem auch die writeBehind Geschichte und dass Objekte nicht mehr von Doctrine Klassen abgeleitet werden müssen, sondern mit dem &#8220;Entity Managers&#8221; zB. gespeichert werden. Also keine ->save() methoden mehr. :) “Everything is an &#8230; </p>
<p class="link-more"><a href="https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/" class="more-link">Continue reading<span class="screen-reader-text"> "The only valid measurement of code quality: WTFs/minute"</span></a></p>
The post <a href="https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/">The only valid measurement of code quality: WTFs/minute</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></description>
										<content:encoded><![CDATA[<p>oder: <a href="http://www.doctrine-project.org/">Doctrine</a> 2 wird wohl ziemlich gut.</p>
<p><a href="http://window.punkave.com/2010/02/16/doctrine-2-jonathan-wage-at-sflive2010/">Hier</a> gibt es ein paar Notizen von Jonathan Wage&#8217;s Präsentation dazu!</p>
<p><span id="more-810"></span><br />
Sehr cool klingt unter anderem auch die writeBehind Geschichte und dass Objekte nicht mehr von Doctrine Klassen abgeleitet werden müssen, sondern mit dem &#8220;Entity Managers&#8221; zB. gespeichert werden.<br />
Also keine ->save() methoden mehr. :)</p>
<blockquote><p>
“Everything is an entity.” A lightweight persistent domain object, a regular PHP class. You don’t extend a base doctrine class. No final methods.</p>
<p>namespace Entities;<br />
class User<br />
{<br />
  private $id;<br />
  private $name;<br />
  private $address;<br />
}</p>
<p>Note use of <a href="http://de.php.net/manual/de/language.namespaces.php">namespaces</a>.</p>
<p>EntityManager is central access point to ORM. Used to query for persistent objects. Employs transactional write behind strategy that delays execution of SQL to execute it in the most efficient way.
</p></blockquote>The post <a href="https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/">The only valid measurement of code quality: WTFs/minute</a> first appeared on <a href="https://nerdpress.org">Nerdpress.org</a>.]]></content:encoded>
					
					<wfw:commentRss>https://nerdpress.org/2010/02/17/the-only-valid-measurement-of-code-quality-wtfs-minute/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
