<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Blog entries tagged doctrine :: mwop.net</title>
  <updated>2025-03-10T08:24:34-05:00</updated>
  <generator uri="https://getlaminas.org" version="2">Laminas_Feed_Writer</generator>
  <link rel="alternate" type="text/html" href="https://mwop.net/blog/tag/doctrine"/>
  <link rel="self" type="application/atom+xml" href="https://mwop.net/blog/tag/doctrine/atom.xml"/>
  <id>https://mwop.net/blog/tag/doctrine</id>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[SQL Nested Queries or Sub Queries with Doctrine DBAL]]></title>
    <published>2025-03-06T10:35:34-06:00</published>
    <updated>2025-03-10T08:24:34-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2025-03-06-dbal-sub-query.html"/>
    <id>https://mwop.net/blog/2025-03-06-dbal-sub-query.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I recently ran into a problem with my website for which the
solution was a nested query (sometimes termed a subquery). However,
I use <xhtml:a href="https://www.doctrine-project.org/projects/doctrine-dbal/en/4.2/index.html">
Doctrine DBAL</xhtml:a> for creating my dynamic queries, and there's no
documentation on how to do them.</xhtml:p>
<xhtml:h3>The problem</xhtml:h3>
<xhtml:p>For my art gallery, the raw SQL looks something like the
following:</xhtml:p>
<xhtml:pre><xhtml:code class="language-sql hljs sql" data-lang="sql"><xhtml:span class="hljs-keyword">SELECT</xhtml:span>
    p.filename,
    p.description,
    p.created,
    array_agg(<xhtml:span class="hljs-keyword">DISTINCT</xhtml:span> t.tag) <xhtml:span class="hljs-keyword">as</xhtml:span> tags
<xhtml:span class="hljs-keyword">FROM</xhtml:span>
    photos p
<xhtml:span class="hljs-keyword">LEFT</xhtml:span> <xhtml:span class="hljs-keyword">JOIN</xhtml:span> tags t <xhtml:span class="hljs-keyword">ON</xhtml:span> p.filename = t.content_id
<xhtml:span class="hljs-keyword">WHERE</xhtml:span>
    p.filename = :filename
    <xhtml:span class="hljs-keyword">AND</xhtml:span> t.content_type = :content_type
<xhtml:span class="hljs-keyword">GROUP</xhtml:span> <xhtml:span class="hljs-keyword">BY</xhtml:span>
    p.filename
</xhtml:code></xhtml:pre>
<xhtml:p>I started noticing an odd issue where, post insertion of an
image into my gallery, I'd get no error, but the form would not
appear to have processed. On further inspection, using <xhtml:a href="https://www.zend.com/products/zendphp-enterprise/zendhq#tab-panel-16522">
Z-Ray from ZendHQ</xhtml:a>, I realized that the insertion was
successful, but that the redirect to view the inserted image was
returning a 404. I grabbed the executed SQL from Z-Ray for
retrieving the image, and it returned no rows.</xhtml:p>
<xhtml:p>I started thinking about why this image wasn't posting, when
others were, and realized there was one trivial difference: I
wasn't including any hashtags in my description, which meant no
tags.</xhtml:p>
<xhtml:p>Hopefully you can see where this is leading.</xhtml:p>
<xhtml:p>A <xhtml:code>LEFT JOIN</xhtml:code> normally will not cause the entire
query to fail if it finds no matching rows on the joined table;
that's the behavior of <xhtml:code>INNER JOIN</xhtml:code>. However, if you put
a condition that is based on a joined table outside the join
itself, it essentially acts like an <xhtml:code>INNER JOIN</xhtml:code>, as
this is now a condition of the <xhtml:code>SELECT</xhtml:code> query.</xhtml:p>
<xhtml:p>Sure enough, when I removed the <xhtml:code>LEFT JOIN</xhtml:code> and the
<xhtml:code>array_agg</xhtml:code> column, I got a hit.</xhtml:p>
<xhtml:h3>"Obvious" solution: move the condition</xhtml:h3>
<xhtml:p>As a commenter on this post noted, the immediate solution is to
move the <xhtml:code>AND t.content_type = :content_type</xhtml:code> clause to
the <xhtml:code>JOIN</xhtml:code>:</xhtml:p>
<xhtml:pre><xhtml:code class="language-sql hljs sql" data-lang="sql"><xhtml:span class="hljs-keyword">SELECT</xhtml:span>
    p.filename,
    p.description,
    p.created,
    array_agg(<xhtml:span class="hljs-keyword">DISTINCT</xhtml:span> t.tag) <xhtml:span class="hljs-keyword">as</xhtml:span> tags
<xhtml:span class="hljs-keyword">FROM</xhtml:span>
    photos p
<xhtml:span class="hljs-keyword">LEFT</xhtml:span> <xhtml:span class="hljs-keyword">JOIN</xhtml:span> tags t <xhtml:span class="hljs-keyword">ON</xhtml:span> p.filename = t.content_id <xhtml:span class="hljs-keyword">AND</xhtml:span> t.content_type = :content_type
<xhtml:span class="hljs-keyword">WHERE</xhtml:span>
    p.filename = :filename
<xhtml:span class="hljs-keyword">GROUP</xhtml:span> <xhtml:span class="hljs-keyword">BY</xhtml:span>
    p.filename
</xhtml:code></xhtml:pre>
<xhtml:p>This does work, and requires no huge changes to the DBAL query
builder; I just move the condition into the
<xhtml:code>joinLeft()</xhtml:code>, and carry on.</xhtml:p>
<xhtml:h3>Preferred solution: nested query</xhtml:h3>
<xhtml:p>The solution I chose was to do a nested query, and to aggregate
those results as an array. This makes it more clear when reading
the query as to the intent: I want to select all distinct tags for
this image and assign them as an array to a column. I'm using
PostgreSQL, so the query looks like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-sql hljs sql" data-lang="sql"><xhtml:span class="hljs-keyword">SELECT</xhtml:span>
    p.filename,
    p.description,
    p.created,
    (<xhtml:span class="hljs-keyword">SELECT</xhtml:span> <xhtml:span class="hljs-built_in">ARRAY</xhtml:span>(
        <xhtml:span class="hljs-keyword">SELECT</xhtml:span> <xhtml:span class="hljs-keyword">DISTINCT</xhtml:span> tag <xhtml:span class="hljs-keyword">FROM</xhtml:span> tags <xhtml:span class="hljs-keyword">WHERE</xhtml:span> p.filename = content_id <xhtml:span class="hljs-keyword">AND</xhtml:span> content_type = :content_type
        )) <xhtml:span class="hljs-keyword">as</xhtml:span> tags
<xhtml:span class="hljs-keyword">FROM</xhtml:span>
    photos p
<xhtml:span class="hljs-keyword">WHERE</xhtml:span>
    p.filename = :filename
<xhtml:span class="hljs-keyword">GROUP</xhtml:span> <xhtml:span class="hljs-keyword">BY</xhtml:span>
    p.filename
</xhtml:code></xhtml:pre>
<xhtml:p>With this approach, if no rows are returned from the
<xhtml:code>tags</xhtml:code> table, an empty array is created; otherwise an
array of the tag values that match is returned.</xhtml:p>
<xhtml:p>However, I didn't know how to create this query using the
Doctrine DBAL query builder.</xhtml:p>
<xhtml:h3>DBAL solution</xhtml:h3>
<xhtml:p>When creating a <xhtml:code>SELECT</xhtml:code> using the DBAL query
builder, you do something like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$select = $dbal-&gt;createQueryBuilder();
$select
    -&gt;select(
        <xhtml:span class="hljs-comment">// one argument per column to select</xhtml:span>
    )
    -&gt;from(<xhtml:span class="hljs-string">'table_name'</xhtml:span>, <xhtml:span class="hljs-string">'t'</xhtml:span>) <xhtml:span class="hljs-comment">// alias the table</xhtml:span>
</xhtml:code></xhtml:pre>
<xhtml:p>The arguments to <xhtml:code>select()</xhtml:code> are expected to be
strings, and any given string can be an arbitrary SQL
expression.</xhtml:p>
<xhtml:p>Creating the subselect is easy; you do it like any other
query:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$tags = $dbal-&gt;createQueryBuilder();
$tags
    -&gt;select(<xhtml:span class="hljs-string">'tag'</xhtml:span>)
    -&gt;distinct()
    -&gt;from(<xhtml:span class="hljs-string">'tags'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'content_id = p.filename'</xhtml:span>)
    -&gt;andWhere(<xhtml:span class="hljs-string">'content_type = :content_type'</xhtml:span>);
</xhtml:code></xhtml:pre>
<xhtml:p>Now, how do I get that into a column string for a select?</xhtml:p>
<xhtml:p>The <xhtml:code>getSQL()</xhtml:code> method of a query builder will spit
out the SQL sent. Moreover, it <xhtml:strong>does not</xhtml:strong> replace
placeholders, so even if you set a bound parameter, it won't be
injected into the generated SQL.</xhtml:p>
<xhtml:p>Knowing all this, I did the following:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$tags = $dbal-&gt;createQueryBuilder();
$tags
    -&gt;select(<xhtml:span class="hljs-string">'tag'</xhtml:span>)
    -&gt;distinct()
    -&gt;from(<xhtml:span class="hljs-string">'tags'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'content_id = p.filename'</xhtml:span>)
    -&gt;andWhere(<xhtml:span class="hljs-string">'content_type = :content_type'</xhtml:span>);

$select = $dbal-&gt;createQueryBuilder();
$select
    -&gt;select(
        <xhtml:span class="hljs-string">'p.filename'</xhtml:span>,
        <xhtml:span class="hljs-string">'p.description'</xhtml:span>,
        <xhtml:span class="hljs-string">'p.created'</xhtml:span>,
        sprintf(<xhtml:span class="hljs-string">'(SELECT ARRAY(%s)) as tags'</xhtml:span>, $tags-&gt;getSQL()),
    )
    -&gt;from(<xhtml:span class="hljs-string">'photos'</xhtml:span>, <xhtml:span class="hljs-string">'p'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'p.filename = :filename'</xhtml:span>)
    -&gt;groupBy(<xhtml:span class="hljs-string">'p.filename'</xhtml:span>)
    -&gt;setParameter(<xhtml:span class="hljs-string">'filename'</xhtml:span>, $filename, ParameterType::STRING)
    -&gt;setParameter(<xhtml:span class="hljs-string">'content_type'</xhtml:span>, <xhtml:span class="hljs-string">'photo'</xhtml:span>, ParameterType::STRING);
</xhtml:code></xhtml:pre>
<xhtml:p>(Where <xhtml:code>ParameterType</xhtml:code> is imported from the namespace
<xhtml:code>Doctrine\DBAL</xhtml:code>.)</xhtml:p>
<xhtml:p>This approach worked immediately, and generated exactly the same
result as the raw SQL I had tested.</xhtml:p>
<xhtml:h3>Changelog</xhtml:h3>
<xhtml:ul>
<xhtml:li>2025-03-07: clarified that the solution was targeting the DBAL
query builder. DBAL can consume raw SQL as well, and does not
require usage of the query builder.</xhtml:li>
<xhtml:li>2025-03-10: noted that a <xhtml:code>LEFT JOIN</xhtml:code> will still
work, as long as the <xhtml:code>t.content_type = :content_type</xhtml:code>
condition is moved from the <xhtml:code>SELECT</xhtml:code> to the <xhtml:code>LEFT
JOIN</xhtml:code>.</xhtml:li>
</xhtml:ul>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2025-03-06-dbal-sub-query.html">SQL Nested
Queries or Sub Queries with Doctrine DBAL</xhtml:a> was originally
published <xhtml:time class="dt-published" datetime="2025-03-06T10:35:34-06:00">6 March 2025</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by <xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew Weier
O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[Advent 2023: Doctrine DBAL]]></title>
    <published>2023-12-10T11:00:00-06:00</published>
    <updated>2023-12-11T09:21:00-06:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2023-12-10-advent-dbal.html"/>
    <id>https://mwop.net/blog/2023-12-10-advent-dbal.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I've mostly taken database abstraction for granted since I
started at Zend. We had a decent abstraction layer in ZF1, and
improved it for ZF2. There were a lot quirks to it — you really had
to dive in and look at the various SQL abstraction classes to
understand how to do more complex stuff — but it worked, and was
always right there and available in the projects I worked on.</xhtml:p>
<xhtml:p>In the last couple of years, though, we came to the realization
in the Laminas Project that we didn't really have anybody with the
expertise or time to maintain it. We've marked it security-only
twice now, and while we've managed to keep it updated to each new
PHP version, it's becoming harder and harder, and whenever there's
a CI issue, it's anybody's guess as to whether or not we'll be able
to get it resolved.</xhtml:p>
<xhtml:p>My alternatives have been straight PDO, or Doctrine DBAL, with
the latter being my preference.</xhtml:p>
<xhtml:h3>Doctrine <xhtml:em>what</xhtml:em>?</xhtml:h3>
<xhtml:p>When most folks who use PHP hear "Doctrine", they immediately
think "<xhtml:a href="https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping">ORM</xhtml:a>";
it's how most folks use it, and what it's best known for.</xhtml:p>
<xhtml:p>Underlying the ORM is its database abstraction layer (hence
"DBAL"). This library exposes an API that will work across any
database it supports; this is essentially what zend-db, and later
laminas-db, were doing as well. What most folks don't realize is
that you can use the DBAL <xhtml:em>by itself</xhtml:em>, without the ORM.</xhtml:p>
<xhtml:h3>Why no ORM?</xhtml:h3>
<xhtml:p>ORMs are fine. Really. But they add an additional layer of
complexity to understanding what you are actually doing.
Additionally, if you want to do something that doesn't quite fit
how the ORM works, you'll need to drop down to the DBAL anyways. So
my take has always been: why not just use the DBAL from the
beginning?</xhtml:p>
<xhtml:p>So, how does <xhtml:em>Matthew</xhtml:em> write code that interacts with the
database?</xhtml:p>
<xhtml:p>I start by writing value objects that represent discrete aspects
of the application. Most of my work will be in consuming or
creating these. From there, I write a <xhtml:em><xhtml:a href="https://martinfowler.com/eaaCatalog/repository.html">repository</xhtml:a></xhtml:em>
class that I use for purposes of persisting and retrieving them. I
can usually extract an interface from this, which aids in my
testing, or if I decide I need a different approach to persistence
later.</xhtml:p>
<xhtml:p>I push the work of mapping the data from the database to these
objects, and vice versa, either in the repository, or in the value
objects themselves (often via a <xhtml:a href="https://verraes.net/2014/06/named-constructors-in-php/">named
constructor</xhtml:a>). Using these approaches creates lean code that can
be easily tested, and for which there's no real need to understand
the underlying system; it's all right there in what I've written
for the application.</xhtml:p>
<xhtml:h3>Some gripes about the documentation, and some tips</xhtml:h3>
<xhtml:p>The <xhtml:a href="https://www.doctrine-project.org/projects/doctrine-dbal/en/current/index.html">
Doctrine DBAL docs</xhtml:a> are a bit sparse, particularly when it comes
to its <xhtml:a href="https://www.doctrine-project.org/projects/doctrine-dbal/en/current/reference/query-builder.html">
SQL abstraction</xhtml:a>. And there's no "getting started" or "basic
usage" guide. In fact, it's not until the third page within the
docs that you get any code examples; thankfully, at that point they
give you information on how to get a database connection:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-keyword">use</xhtml:span> <xhtml:span class="hljs-title">Doctrine</xhtml:span>\<xhtml:span class="hljs-title">DBAL</xhtml:span>\<xhtml:span class="hljs-title">DriverManager</xhtml:span>;

$connectionParams = [
    <xhtml:span class="hljs-string">'dbname'</xhtml:span>   =&gt; <xhtml:span class="hljs-string">'mydb'</xhtml:span>,
    <xhtml:span class="hljs-string">'user'</xhtml:span>     =&gt; <xhtml:span class="hljs-string">'user'</xhtml:span>,
    <xhtml:span class="hljs-string">'password'</xhtml:span> =&gt; <xhtml:span class="hljs-string">'secret'</xhtml:span>,
    <xhtml:span class="hljs-string">'host'</xhtml:span>     =&gt; <xhtml:span class="hljs-string">'localhost'</xhtml:span>,
    <xhtml:span class="hljs-string">'driver'</xhtml:span>   =&gt; <xhtml:span class="hljs-string">'pdo_mysql'</xhtml:span>,
];
$conn = DriverManager::getConnection($connectionParams);
</xhtml:code></xhtml:pre>
<xhtml:p>They also provide a number of other approaches, including using
a DSN (an acronym they never explain, but based on using PDO,
likely means "data source name").</xhtml:p>
<xhtml:p>Once you have a connection, what do you do? Well the DBAL
connection allows you to prepare and execute queries, including via
the use of prepared statements. It provides a variety of methods
for fetching individual or multiple rows, with a variety of options
for how the data is returned (indexed arrays, associative arrays,
individual columns, individual values, etc.). These retrieval
methods are mirrored in the result instances returned when
executing prepared statements as well.</xhtml:p>
<xhtml:p>And that brings me to the SQL abstraction.</xhtml:p>
<xhtml:p>First, it's really, really good. It's minimal, but it covers
just about anything you need to do. If you need to write something
complex, you probably can; the beauty is that if you can't, you can
always fall back to a SQL query, and using the connection's API for
binding values.</xhtml:p>
<xhtml:p>But the documentation could be better.</xhtml:p>
<xhtml:p>It felt like it was written by a database admin who has
forgotten more than most people ever learn about databases, and
never considered that others might not know as much as them. The
fact that it starts with architecture and not usage feels hugely
antagonistic for somebody coming in just wanting to know how to
connect to the database, build a query, and fetch some results.
(The irony is not lost on me that this is almost exactly how
Laminas and Mezzio docs are written, and, yes, I recognize we could
all do better!)</xhtml:p>
<xhtml:blockquote>
<xhtml:p>Before folks start grousing, yes, I have on my TODO list an item
for contributing to the DBAL docs. I'm trying to work up an outline
of what I would have found useful, what acronyms need explanation,
and some examples of common patterns before I make any suggestions,
however.</xhtml:p>
</xhtml:blockquote>
<xhtml:p>First, they have a whole documentation page related to the SQL
query builder, and a lot of examples. But not a single one details
<xhtml:em>how to actually execute the query</xhtml:em>! So, for those
wondering:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$sql = $conn-&gt;createQueryBuilder();

<xhtml:span class="hljs-comment">// ... build your query ...</xhtml:span>

<xhtml:span class="hljs-comment">// Execute a query that will retrieve results (generally SELECT queries):</xhtml:span>
$result = $sql-&gt;executeQuery();

<xhtml:span class="hljs-comment">// Execute a query that produces changes (INSERT, UPDATE, DELETE, etc.):</xhtml:span>
$count = $sql-&gt;executeStatement();
</xhtml:code></xhtml:pre>
<xhtml:p>Query results have a variety of <xhtml:code>fetch*()</xhtml:code> operations
on them, while executing a statement returns an integer indicating
the number of rows affected (assuming the database supports
this).</xhtml:p>
<xhtml:p>Second, when I started doing joins, the argument names were
confusing, and made it harder to understand what was needed. I
eventually figured it out, but it was really easy to flip the
arguments for the different tables being joined. The usage below
illustrates names that would better describe how to use it:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$sql-&gt;innerJoin(
    $primaryTableOrItsAliasIfYouSpecifiedOne, <xhtml:span class="hljs-comment">// e.g. "user" or "u"</xhtml:span>
    $newTableToJoin,                          <xhtml:span class="hljs-comment">// e.g. "address"</xhtml:span>
    $aliasForNewTableToJoin,                  <xhtml:span class="hljs-comment">// e.g. "a"</xhtml:span>
    $conditionToJoinOn                        <xhtml:span class="hljs-comment">// e.g. "u.id = a.uid"</xhtml:span>
);
</xhtml:code></xhtml:pre>
<xhtml:p>Third, there's some odd differences in the API between INSERT
and UPDATE operations., When setting a value, one takes
<xhtml:code>setValue()</xhtml:code>, while the other takes <xhtml:code>set()</xhtml:code>,
and only one of these is valid for a given operation (it's
<xhtml:code>setValue()</xhtml:code> for INSERT operations, and
<xhtml:code>set()</xhtml:code> for UPDATE operations, in case you were
wondering). This is especially confusing when using bound
parameters, because <xhtml:em>both</xhtml:em> can use the
<xhtml:code>setParameter()</xhtml:code> method for binding positional
placeholder values.</xhtml:p>
<xhtml:p>Speaking of plaeholders, the docs don't do a great job of
detailing how to handle <xhtml:em>placeholders</xhtml:em> gracefully.</xhtml:p>
<xhtml:p>The documentation suggests patterns like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$queryBuilder
    -&gt;select(<xhtml:span class="hljs-string">'id'</xhtml:span>, <xhtml:span class="hljs-string">'name'</xhtml:span>)
    -&gt;from(<xhtml:span class="hljs-string">'users'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'email = ?'</xhtml:span>)
    -&gt;setParameter(<xhtml:span class="hljs-number">0</xhtml:span>, $userInputEmail);
</xhtml:code></xhtml:pre>
<xhtml:p>Which is fine when there's only one parameterized value, but
what if you have several, or if you're dynamically building the
query (e.g., looping through user-supplied sorting or criteria,
etc.), and you don't know their exact position in the final query?
And what if you want to use named parameters instead of positional
parameters, but you're not sure if your database supports them?</xhtml:p>
<xhtml:p>The answer is in the docs, but the various <xhtml:em>examples</xhtml:em>
don't use the pattern (other than in the discussion of the
methods), which is infuriating. The above can also be written as
follows:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php">$queryBuilder
    -&gt;select(<xhtml:span class="hljs-string">'id'</xhtml:span>, <xhtml:span class="hljs-string">'name'</xhtml:span>)
    -&gt;from(<xhtml:span class="hljs-string">'users'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'email = '</xhtml:span> . $queryBuilder-&gt;createNamedParameter($userInputEmail));
</xhtml:code></xhtml:pre>
<xhtml:p>There's also a <xhtml:code>createPositionalParameter()</xhtml:code> method.
Both accept an optional second argument, where you can specify the
value <xhtml:em>type</xhtml:em>, which can help ensure that values are quoted
correctly for the SQL type they will map to. This also allows you
to do <xhtml:code>IN()</xhtml:code> operations, and each value will be quoted
correctly, with the appropriate list separator for the
database.</xhtml:p>
<xhtml:p>Once you know this approach, it's easy to remember and use, but
it took me a few times through the docs before I stumbled across
it.</xhtml:p>
<xhtml:p>The SQL it generates, though, is great, and when I've used tools
like ZendHQ's Z-Ray to introspect queries, I'm always impressed by
what was actually sent over the wire.</xhtml:p>
<xhtml:blockquote>
<xhtml:h4>2023-12-11 Update</xhtml:h4>
<xhtml:p><xhtml:a href="https://mastodon.social/@nesl247">Alexander Kim</xhtml:a>
pointed out to me that you can use named parameters within the
query builder, along with the <xhtml:code>setParameter()</xhtml:code> method.
That usage looks like this:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-keyword">use</xhtml:span> <xhtml:span class="hljs-title">Doctrine</xhtml:span>\<xhtml:span class="hljs-title">DBAL</xhtml:span>\<xhtml:span class="hljs-title">ParameterType</xhtml:span>;

$queryBuilder
    -&gt;select(<xhtml:span class="hljs-string">'id'</xhtml:span>, <xhtml:span class="hljs-string">'name'</xhtml:span>)
    -&gt;from(<xhtml:span class="hljs-string">'users'</xhtml:span>)
    -&gt;where(<xhtml:span class="hljs-string">'email = :email'</xhtml:span>)
    -&gt;setParameter(<xhtml:span class="hljs-string">'email'</xhtml:span>, $userInputEmail, ParameterType::STRING);
</xhtml:code></xhtml:pre>
<xhtml:p>You can also specify named parameters when using
<xhtml:code>set()</xhtml:code> and <xhtml:code>setValue()</xhtml:code>, though I'd argue
that using <xhtml:code>createNamedParameter()</xhtml:code> is easier in those
contexts.</xhtml:p>
</xhtml:blockquote>
<xhtml:p>But for all these issues, the fact is that the docs generally
give you <xhtml:em>enough</xhtml:em>, and the API is so clean and reasonably
documented that you can generally figure out how things work just
from your IDE hints and autocompletion. Yes, I have gripes, but the
library is <xhtml:em>very</xhtml:em> solid, <xhtml:em>very</xhtml:em> well written, and
absolutely something I can depend on.</xhtml:p>
<xhtml:h3>Final Thoughts</xhtml:h3>
<xhtml:p>I've often used straight PDO for projects, and it works fine.
However, having a tool available like Doctrine DBAL has been a huge
boon in ensuring I can switch from SQLite while prototyping to
MySQL for production, and know that things will "just work".</xhtml:p>
<xhtml:p>I also find the way it juggles <xhtml:em>types</xhtml:em> to be really
useful. I know that if a value is typed in the database as a NULL
or as text or as a float or integer, I'll actually get those types
back when I query; the same is true for when I send data to the
database. There's no magic involved, and I don't have to remember
to do type conversions to and from the database. That's
<xhtml:em>exactly</xhtml:em> the type of functionality I want from a DBAL.</xhtml:p>
<xhtml:p>Yes, writing database-centric code is cumbersome, and there's a
reason folks use ORMs, ActiveRecord, and the like. However, it
generally only needs to be written once, with occasional updates.
Having a good DBAL available helps keep complexity of your
application down and gives you the tools to communicate securely
with your database.</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2023-12-10-advent-dbal.html">Advent 2023:
Doctrine DBAL</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2023-12-10T11:00:00-06:00">10 December
2023</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
  <entry xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <title type="html"><![CDATA[On Visibility in OOP]]></title>
    <published>2012-06-28T21:20:00-05:00</published>
    <updated>2012-06-30T10:00:00-05:00</updated>
    <link rel="alternate" type="text/html" href="https://mwop.net/blog/2012-06-28-oop-visibility.html"/>
    <id>https://mwop.net/blog/2012-06-28-oop-visibility.html</id>
    <author>
      <name>Matthew Weier O'Phinney</name>
      <email>contact@mwop.net</email>
      <uri>https://mwop.net</uri>
    </author>
    <content xmlns:xhtml="http://www.w3.org/1999/xhtml" type="xhtml">
      <xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml"><xhtml:p>I'm a big proponent of object oriented programming. OOP done
right helps ease code maintenance and enables code re-use.</xhtml:p>
<xhtml:p>Starting in PHP, OOP enthusiasts got a whole bunch of new tools,
and new tools keep coming into the language for us with each minor
release. One feature that has had a huge impact on frameworks and
libraries has been available since the earliest PHP 5 versions:
visibility.</xhtml:p>
<xhtml:h2>Theory</xhtml:h2>
<xhtml:p>The visibility keywords include <xhtml:em>private</xhtml:em>,
<xhtml:em>protected</xhtml:em>, and <xhtml:em>public</xhtml:em>, often referred to as
<xhtml:strong>PPP</xhtml:strong>. There's an additional keyword I often lump in
with them, <xhtml:em>final</xhtml:em>.</xhtml:p>
<xhtml:p>Public visibility is the default, and equivalent to the only
visibility available to PHP prior to version 5: any member declared
public is accessible from any scope. This means the following:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// I can access within my own scope</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">doThat</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span>
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// I have access to members in my parent</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar . <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;baz();
    }
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> Foo();

<xhtml:span class="hljs-comment">// I can access public members from an instance</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;bar . $foo-&gt;baz();
</xhtml:code></xhtml:pre>
<xhtml:p>Basically, public visibility means that I can access the member
from within the object, within an extending class, or from simply
an instance.</xhtml:p>
<xhtml:p>Protected visibility starts to tighten things down a little.
With protected visibility, only the class itself, or an extending
class, can access the member:</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">protected</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;

    <xhtml:span class="hljs-keyword">protected</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// I can access within my own scope</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">doThat</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span>
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// I can access protected members in my parent</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar . <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;baz();
    }
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> FooBar();

<xhtml:span class="hljs-comment">// This works, as I'm calling a public member of an extending class:</xhtml:span>
$foo-&gt;doThat();

<xhtml:span class="hljs-comment">// But these are both illegal:</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;bar . $foo-&gt;baz();
</xhtml:code></xhtml:pre>
<xhtml:p>Protected visibility is nice for hiding things from those
consuming your class. It can be used to hide implementation
details, and to prevent direct modification of public properties —
something important to consider, if a property may be the product
of calculation, or if a particular type is required.</xhtml:p>
<xhtml:p>Private visibility locks things down further. With private
visibility, the object member is only directly modifiable or
callable within the declaring class.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">private</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;

    <xhtml:span class="hljs-keyword">private</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// I can access within my own scope</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">doThat</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span>
    </xhtml:span>{
        <xhtml:span class="hljs-comment">// These are both illegal</xhtml:span>
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar . <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;baz();
    }
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> FooBar();

<xhtml:span class="hljs-comment">// These are also both illegal:</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;bar . $foo-&gt;baz();
</xhtml:code></xhtml:pre>
<xhtml:p>Private visibility is generally of interest for locking down
algorithms. For instance, if you know that a particular value or
operation must not change, even in extending classes, declaring the
member private ensures that extending classes cannot directly call
it.</xhtml:p>
<xhtml:p>At any point, you can redeclare a property in an extending class
using equal or more public visibility. The effect of doing so
depends on what the visibility of the member was in the parent
class.</xhtml:p>
<xhtml:ul>
<xhtml:li>
<xhtml:p>In the case of a <xhtml:em>public</xhtml:em> property, if an extending class
re-declares with public visibility, any access to the member within
the extending class or an instance of the extending class will see
only the new declaration.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> $bar = <xhtml:span class="hljs-string">'foobar'</xhtml:span>;
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> FooBar();
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;bar;   <xhtml:span class="hljs-comment">// "foobar"</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;baz(); <xhtml:span class="hljs-comment">// "foobar"</xhtml:span>
</xhtml:code></xhtml:pre></xhtml:li>
<xhtml:li>
<xhtml:p>In the instance of a <xhtml:em>protected</xhtml:em> property, if the
extending class re-declares with either public or protected
visibility, you get the same behavior as public -&gt; public.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">protected</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">public</xhtml:span> $bar = <xhtml:span class="hljs-string">'foobar'</xhtml:span>;
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> FooBar();
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;bar;   <xhtml:span class="hljs-comment">// "foobar"</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;baz(); <xhtml:span class="hljs-comment">// "foobar"</xhtml:span>
</xhtml:code></xhtml:pre></xhtml:li>
<xhtml:li>
<xhtml:p>In the instance of a <xhtml:em>private</xhtml:em> property, things get
interesting. The private value or method will be used for any
access made within code declared in the parent class, but not
overridden in the child. However, if the child class overrides any
code, the value of the re-declared instance will be used. This is
far easier to understand via an example.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">private</xhtml:span> $bar = <xhtml:span class="hljs-string">'bar'</xhtml:span>;
    <xhtml:span class="hljs-keyword">private</xhtml:span> $baz = <xhtml:span class="hljs-string">'baz'</xhtml:span>;

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">baz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">FooBar</xhtml:span> <xhtml:span class="hljs-keyword">extends</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">protected</xhtml:span> $bar = <xhtml:span class="hljs-string">'foobar'</xhtml:span>;
    <xhtml:span class="hljs-keyword">private</xhtml:span> $baz = <xhtml:span class="hljs-string">'foobaz'</xhtml:span>;

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">myBaz</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span> 
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar;
    }

    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">myBaz2</xhtml:span><xhtml:span class="hljs-params">()</xhtml:span>
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">return</xhtml:span> <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;baz;
    }
}

$foo = <xhtml:span class="hljs-keyword">new</xhtml:span> FooBar();
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;baz();    <xhtml:span class="hljs-comment">// "bar"</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;myBaz();  <xhtml:span class="hljs-comment">// "foobar"</xhtml:span>
<xhtml:span class="hljs-keyword">echo</xhtml:span> $foo-&gt;myBaz2(); <xhtml:span class="hljs-comment">// "foobaz"</xhtml:span>
</xhtml:code></xhtml:pre></xhtml:li>
</xhtml:ul>
<xhtml:p>My personal takeaway from this is:</xhtml:p>
<xhtml:ul>
<xhtml:li>Use <xhtml:em>public</xhtml:em> for members that are safe for anything to
call.</xhtml:li>
<xhtml:li>Use <xhtml:em>protected</xhtml:em> for anything you don't want called from
instance methods, not important to the public API (implementation
details), and anything you feel is safe for extending classes to
muck about with.</xhtml:li>
<xhtml:li>Use <xhtml:em>private</xhtml:em> for any important implementation details
that could adversely affect execution if overridden by an extending
class.</xhtml:li>
</xhtml:ul>
<xhtml:p>Those paying attention will note that I skipped <xhtml:em>final</xhtml:em>.
Actually, I saved that for last. Marking a class or method
<xhtml:em>final</xhtml:em> tells PHP that the class or method may not be
extended or re-declared/overridden. At all. I lump this with
visibility, because it's another way of locking down access to an
API; marking something <xhtml:em>final</xhtml:em> is saying, "you cannot extend
this", similar to using <xhtml:em>private</xhtml:em>, but without even the
possibility of redeclaring.</xhtml:p>
<xhtml:h2>Applied</xhtml:h2>
<xhtml:p>What got me to thinking about all this was a turn of events with
Zend Framework 2. We've had an annotation parser since last summer.
<xhtml:a href="http://ralphschindler.com/">Ralph Schindler</xhtml:a> developed
it in order to facilitate automatic discovery of injection points
for our Dependency Injection container. Classes could mark a method
with the <xhtml:code>@Inject</xhtml:code> annotation, and the various DI
compilers would know that that method needed to be injected.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-keyword">use</xhtml:span> <xhtml:span class="hljs-title">Zend</xhtml:span>\<xhtml:span class="hljs-title">Di</xhtml:span>\<xhtml:span class="hljs-title">Definition</xhtml:span>\<xhtml:span class="hljs-title">Annotation</xhtml:span>\<xhtml:span class="hljs-title">Inject</xhtml:span>;

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-keyword">protected</xhtml:span> $bar;

    <xhtml:span class="hljs-comment">/**
     * <xhtml:span class="hljs-doctag">@Inject</xhtml:span>()
     * <xhtml:span class="hljs-doctag">@param</xhtml:span>  Bar $bar
     * <xhtml:span class="hljs-doctag">@return</xhtml:span> void
     */</xhtml:span>
    <xhtml:span class="hljs-keyword">public</xhtml:span> <xhtml:span class="hljs-function"><xhtml:span class="hljs-keyword">function</xhtml:span> <xhtml:span class="hljs-title">setBar</xhtml:span><xhtml:span class="hljs-params">(Bar $bar)</xhtml:span>
    </xhtml:span>{
        <xhtml:span class="hljs-keyword">$this</xhtml:span>-&gt;bar = $bar;
    }
}

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Bar</xhtml:span> </xhtml:span>{}
</xhtml:code></xhtml:pre>
<xhtml:p>Recently, part of our Forms RFC included a feature to allow
creating forms and their related input filters by using
annotations. Basically, this allows developers to hint on their
domain entities how specific properties should be filtered,
validated, and potentially represented at the form level.</xhtml:p>
<xhtml:pre><xhtml:code class="language-php hljs php" data-lang="php"><xhtml:span class="hljs-keyword">use</xhtml:span> <xhtml:span class="hljs-title">Zend</xhtml:span>\<xhtml:span class="hljs-title">Form</xhtml:span>\<xhtml:span class="hljs-title">Annotation</xhtml:span>;

<xhtml:span class="hljs-class"><xhtml:span class="hljs-keyword">class</xhtml:span> <xhtml:span class="hljs-title">Foo</xhtml:span>
</xhtml:span>{
    <xhtml:span class="hljs-comment">/**
     * <xhtml:span class="hljs-doctag">@Annotation</xhtml:span>\Filter({"name":"StringTrim"})
     * <xhtml:span class="hljs-doctag">@Annotation</xhtml:span>\Validator({"name":"Between","options":{"min":5,"max":20}})
     * <xhtml:span class="hljs-doctag">@Annotation</xhtml:span>\Attributes({"type":"range"})
     */</xhtml:span>
    <xhtml:span class="hljs-keyword">protected</xhtml:span> $bar;
}
</xhtml:code></xhtml:pre>
<xhtml:p>One developer testing the support wanted to use a combination of
<xhtml:a href="http://doctrine-project.org">Doctrine</xhtml:a> annotations and
ZF2 form annotations — that way his entities could also describe
validation and representation.</xhtml:p>
<xhtml:p>I did some work to make this happen, and everybody was happy.
Except then that same developer went to use that entity with
Doctrine, and Doctrine's annotation parser started raising
exceptions on all the ZF2 annotations.</xhtml:p>
<xhtml:p>After some debate, I realized: (a) we were basically just making
up syntax for our annotations; it'd be better to use an established
syntax; but (b) we should still retain the ability to use arbitrary
syntax, as we can't really know what sorts of annotations
developers may already be using.</xhtml:p>
<xhtml:p>So, we decided to make our annotation component depend on the
annotations support in <xhtml:code>Doctrine\Common</xhtml:code>, and to use the
annotation syntax they utilize. ZF2 would provide some code to make
it possible to plug in arbitrary parsers, and use the
<xhtml:code>Doctrine\Common</xhtml:code> annotation parser to parse annotations
officially supported by ZF2.</xhtml:p>
<xhtml:p>However, when I went to start making this happen, I ran into
immediate issues.</xhtml:p>
<xhtml:p>Remember how this post is about visibility? Well, the class I
was directly interested in,
<xhtml:code>Doctrine\Common\Annotations\DocParser</xhtml:code>, not only
contains private members, but is marked <xhtml:em>final</xhtml:em>.</xhtml:p>
<xhtml:p>My immediate response was to start dissecting the class, cutting
and pasting the bits interesting to my solution into a new class in
ZF2. I went down this route for several hours, gradually pulling in
more and more methods as I discovered how far down the rabbit hole
I needed to go to accomplish my task.</xhtml:p>
<xhtml:p>But at the back of my head, I kept thinking this was a bad idea.
If any patches ever came in for the original class, I'd need to
port them into our ZF2 solution. And I couldn't help but think that
I'd miss a crucial piece.</xhtml:p>
<xhtml:p>So I started playing with its public API, to see if there were
any shortcuts I might be able to take. And there were.</xhtml:p>
<xhtml:p>The class has a public <xhtml:code>parse()</xhtml:code> method. Based on how
Doctrine uses the code, I assumed I needed to pass a full PHP
docblock in — which ran counter to how I wanted to use the code. I
wanted to pass in an annotation at a time. But when I looked
closer, I realized that the parser didn't require a full docblock;
any fragment would do.</xhtml:p>
<xhtml:p>To make a long story short: I was able to feed the parser a
single annotation at a time from ZF2's
<xhtml:code>AnnotationScanner</xhtml:code>. This allowed me to build a very
simple class that allows registering a set of annotations it can
handle, and feeding it a single annotation string at a time to
decide (a) if it supports it, and (b) to parse it and return the
associated annotation object.</xhtml:p>
<xhtml:p>In sum: because the class in question was marked final and had
private members, I found myself forced to think critically about
what I wanted to accomplish, and then thoroughly understand the
public API to see how I might accomplish that task without the
ability to extend.</xhtml:p>
<xhtml:h2>Conclusions</xhtml:h2>
<xhtml:p>Doctrine has a policy that encourages <xhtml:a href="http://en.wikipedia.org/wiki/Poka-yoke"><xhtml:em>poka-yoke</xhtml:em></xhtml:a>
solutions: code should be executable in a specific way. The policy
was developed to both aid users (having multiple ways of doing
something is often confusing), as well as to ease maintenance
(fewer extension points means less liklihood of developers doing
hard-to-debug things in extending code and reporting it back to the
project). These have led them to heavily use <xhtml:em>private</xhtml:em> and
<xhtml:em>final</xhtml:em> visibility.</xhtml:p>
<xhtml:p>I've said it before, and I'll say it again: I feel that
frameworks and libraries should use <xhtml:em>private</xhtml:em> and
<xhtml:em>final</xhtml:em> sparingly. Over the years, I've seen code repurposed
in simply wondrous ways — largely due to keeping the code as open
as possible to extension. I like to enable my users as much as
possible.</xhtml:p>
<xhtml:p>That said, I can also see Doctrine's argument — and can see
where, while it can often be frustrating, it can also lead to
potentially more sound and elegant solutions.</xhtml:p>
<xhtml:p>I'll probably continue shying away from <xhtml:em>private</xhtml:em> and
<xhtml:em>final</xhtml:em> visibility, but I do plan to experiment with it more
in the future. What about you?</xhtml:p>
<xhtml:div class="h-entry"><xhtml:img class="u-photo photo" width="50" src="https://avatars0.githubusercontent.com/u/25943?v=3&amp;u=79dd2ea1d4d8855944715d09ee4c86215027fa80&amp;s=140" alt="matthew"/> <xhtml:a class="u-url u-uid p-name" href="https://mwop.net/blog/2012-06-28-oop-visibility.html">On
Visibility in OOP</xhtml:a> was originally published <xhtml:time class="dt-published" datetime="2012-06-28T21:20:00-05:00">28 June
2012</xhtml:time> on <xhtml:a href="https://mwop.net">https://mwop.net</xhtml:a> by
<xhtml:a rel="author" class="p-author" href="https://mwop.net">Matthew
Weier O'Phinney</xhtml:a>.</xhtml:div>
</xhtml:div>
    </content>
  </entry>
</feed>
