Planet-PHP
So when is the Symfony CMF release?
In January, Lukas wrote a collection of things left to do. Later I wrote a tentative release schedule that turned out to be too optimistic. I just updated that document with new dates. Sorry about this.
There are two actually quite cool reasons for the delays. One is that we had two projects at Liip where we had to integrate the CMF into existing projects. It was fun, but we found quite a lot of issues and missing features in Doctrine PHPCR-ODM that we fixed resp. implemented. (The Symfony2 Form component is incredibly powerful, but requires the persistance layer to work very exactly and we did not want any more workarounds and hacks to a achieve functionality.) The other reason is that many other people started using the CMF too. Some found issues that need to be fixed, others even managed to contribute fixes themselves - but which took time to review and comment on. Also, a lot of new features have been built or are currently being built.
One feature I am particularly happy with is that PHPCR-ODM can now cascade persist referrers. This is quite useful for example to embed route and menu editing into the edit form for static content, as shown in the screenshot. (This is already in the ContentBundle and should come into the sandbox with the next update.)
Getting to a releaseAs soon the above 2 client projects have stabilized, Lukas and I plan to focus on cleaning the base layers PHPCR and Jackalope to a point where we can tag release candidates, then bring Doctrine PHPCR-ODM to a state that can be called 1.0. We might have to postpone new features, but try to find all the interface changes and similar things to avoid BC breaks once 1.0 is stable.
Getting things out depends on contributions from the community too. While it is great to get new features, we now need to focus on cleaning up those we already have. On improving the documentation. On investigating bugs. The Release plan links the important missing pieces, if you want to dig into something.
There is the idea for a hackday in May or June. Please contact me or Lukas if you are interested. If we have enough interest, it is much more likely that we actually organize something.
I will present PHPCR at the Symfony Live conference in Paris beginning of April. I will also be at the hackday on Saturday if anybody is interested in meeting me there. Additionally, Thomas and me planned a (very focused) hackday on April 3rd to integrate SonataPagesBundle with PHPCR on the 3rd. If you are interested in helping with that integration, please contact me or Thomas.
Documentation hackdayThis week, we also did a hackday at Liip, with focus on documentating some of those new features people built. I tried to collect what we achieved that day:
- Allow to edit menu and routes embedded in content documents
- Slideshow block and documentation
- Documentation for the Reference collection form type
- Documentation for the Image form type. And a imagine cache invalidator service. Wanted to make the form type more powerful, but still looking for the right solution.
- Improved Symfony documentation on doctrine events
- Doctrine exposes the method to get the current locale of a document regardless of whether the locale is mapped on the document.
- The Image and File documents of doctrine are cleaned up
- Started work on another problem when replacing child documents but still discussing the concept
- Jackalope-Jackrabbit will give better exceptions on login problems
Ideas of March
I wasn’t going to write about Ideas of March this year. I wasn’t even sure it was an idea worth spreading last year. It’s important to me, but I’m struggling to blog as often as I’d like, so I’m hardly setting a good example.
Then, Google decided to shut down Google Reader. If you were subscribed to their blog, you probably read about it there. Otherwise, you probably read about it on Twitter or Facebook. Food for thought.
Many people are upset. Far more than I would have guessed. Others believe the decision makes sense, because RSS is niche. That might be true, but it seems like an awfully big niche, especially if you account for those who use it but don’t know it. Marco Arment thinks Google’s decision is excellent news:
It may suck in the interim before great alternatives mature and become widely supported, but in the long run, trust me: this is excellent news.
That might also be true, but it feels like we’re going to be taking a few steps back in order to go forward.
I don’t really have much to say other than it’s a bummer. The more I see stuff getting shut down, the more I believe in the value of owning your own data. That’s the real lesson here.
I use Twitter every day, but real writing happens on blogs, and as cool as the next new thing might seem, it’s not as good as your own blog. You never know when it’s going to disappear.
Make your blog the best startup of this year. I’ll do my best to join you.
If you’d like to participate, just share your thoughts about all of this stuff on your own blog, share it on Twitter with the #ideasofmarch hashtag, and encourage your friends to do the same. Even if for just a few days, let’s remind ourselves that we have more to say than can fit in 140 characters.
Krëfel service: een nieuw dieptepunt
Het verhaal begint op 13 oktober 2012. Toen kochten wij een koelkast bij Krëfel. Niets speciaals, een tafelmodel dat onder het keukenblad past. We hadden vooraf eens op de site gekeken, hadden een model gevonden en daarbij stond duidelijk vermeld dat de deur omkeerbaar was (vandaag 14 maart 2013 staat dat er nog steeds bij).
Eenmaal thuisgekomen met de koelkast blijkt dat de deur aan de rechterkant draait terwijl het voor ons handiger is als ze aan de linkerkant draait. Geen probleem! Ik neem de handleiding erbij en begin de deur te demonteren om ze vervolgens aan de andere kant te bevestigen.
Probleem #1: Het scharnier van de bovenkant kan niet gebruikt worden aan de linkerkant van de koelkast. Er zit namelijk een metalen pin in het scharnier en die haakt in een opening van de deur. Om het scharnier links op de schroefgaten te doen passen, moet het scharnier omgedraaid worden… waardoor de metalen pin naar boven wijst en dus niet meer in de deur kan.
Geen probleem! Ik kijk wel even in de verpakking. Daar zal wel een ander scharnier in zitten.
Probleem #2: Geen scharnier voor de linkerkant te vinden…
Dan bel ik even naar de winkel waar we de koelkast gekocht hebben.
Probleem #3: Blijkbaar moest de kant van de deur vooraf vermeld worden en dan had men de koelkast zo geleverd. De verkoper heeft ons dat toen helaas niet gevraagd en vermits ze als omkeerbaar op de website stond gingen wij ervan uit dat we dat, zoals meestal, zelf konden doen.
Na veel vijven en zessen wil men uiteindelijk het andere scharnier als wisselstuk bestellen. Een wisselstuk leveren duurt helaas minstens 20 werkdagen (!!). Ik heb medelijden met alle klanten die met een defect te maken krijgen… op die tijd kan normaal gezien iets een paar keer de wereld rond.
Probleem #4: “We bellen wel als het wisselstuk binnen is”. Als een zin begint met de woorden “We bellen wel…” is het meestal een leugen. Die stelling is in dit geval helaas ook geldig.
Na ongeveer 30 werkdagen en zelf een paar keer te bellen is er eindelijk nieuws. Het wisselstuk is eindelijk binnen. Snel naar de winkel om het wisselstuk te halen en…
Probleem #5: Ze hebben gewoon nog eens hetzelfde scharnier geleverd *zucht*. Bij nadere inspectie staat het zelfs al op de verpakking, evenwel in het Duits (“Rechte Seite”).
Terug naar de winkel, terug een bestelling van een wisselstuk dus – jawel- nog eens 20 werkdagen wachten.
Probleem #6: Deze keer krijg ik wel telefoon met de mededeling dat het gevraagde wisselstuk niet bestaat! Ik vraag me dan af hoe Krëfel dan in godsnaam een model zou kunnen leveren waar de deur links draait. Na wat over-en-weer te bellen nodigt een medewerker me uit in de winkel om exact te tonen wat het probleem is want ze begrijpen het niet.
Ik neem de tijd om nog maar eens naar de winkel te gaan en het probleem te illustreren. De medewerker begrijpt dan eindelijk wat het probleem juist is en begint vanalles uit te pluizen om na te gaan of de deur effectief omkeerbaar is. De handleiding bevestigt dat (wist ik al) en ook alle gaten zijn aanwezig om de draairichting aan te passen (wist ik ook al). De medewerker geeft dan ook toe dat de deur omkeerbaar moet zijn en probeert nogmaals het wisselstuk te bestellen met een (hopelijk) duidelijkere omschrijving. Op dat moment is het al 19 januari 2013, meer dan 3 maanden na de oorspronkelijke aankoop.
Wisselstuk bestellen, dus weer eens 20 werkdagen wachten… en wachten… en wachten op een telefoon die niet komt.
Probleem #7: Op 7 maart 2013 nemen we nogmaals contact op met de winkel. Er is nog steeds geen nieuws ivm het wisselstuk. De medewerker belooft een e-mail te sturen om meer uitleg te vragen.
Op 8 maart contacteren we de winkel nogmaals om te informeren naar het resultaat van de e-mail. Blijkt dat de e-mail nog niet vestuurd was maar de medewerker zou het dan onmiddellijk doen.
Probleem #8: Op 13 maart bellen we weer eens naar de winkel. De e-mail was verstuurd maar “heeft wat vertraging opgelopen dus er is nog geen antwoord”. Die uitleg trekt nergens op en zeker niet als je zelf werkt als ICT’er.
Dus ondertussen wachten we al 5 maanden op een scharnier en meer en meer krijgen we de indruk dat we gewoon aan het lijntje worden gehouden. Ons geduld raakt stilaan op en we zullen in ieder geval twee keer nadenken voor we nog iets bij Krëfel zullen kopen.
PHP 5.4.13 and PHP 5.3.23 released!
How To Test Legacy Applications
Mocking with Phake
Always Return Something
Behavior Driven Development
XSS Is Still Tricky
This works in Safari, Firefox, Chrome, and Opera.
<!DOCTYPE html><head><title>Oh no!</title><script type="text/javascript">var xss = "</script><script>alert('XSS');</script>";</script></head><body><p>And you thought parsers were smart.</p></body></html>
PHP Innovation Award Winner of 2012 - Lately in PHP podcast episode 33
They also discussed the usual batch of PHP topics of interest like Zend Optimizer+ source code that was released, the PHP 5.5 feature freeze and roadmap, as well an article that compares PHP to an Hobbit, as well other languages to Lord Of The Rings story characters.
Listen to the podcast, or watch the podcast video, or read the transcript to learn about these and other interesting PHP topics.
PHP 5.5.0alpha6 released
Writing Intentionally Bad Code
Book Review: The Grumpy Programmer’s PHPUnit Cookbook
Composer: an update on require-dev
Using require-dev in Composer you can declare the dependencies you need for development/testing. It works in most simple cases, but when the dev dependencies overlap with the regular ones, it can get tricky to handle. In too many cases it also tends to just fail at resolving dependencies with quite strange error messages.
Since this was quite unreliable, I set out to rework the whole feature this week-end. The patch has been merged, and it fixes six open issues which is great. The short story there is that it now does things in one pass instead of two before, so it should be faster and a lot more reliable. Also dev dependencies can now impact the non-dev ones without problems since it's all resolved at once.
Workflow changesI took the chance to change another thing while I was at it. The update command now installs dev requirements by default. This makes sense since you should only run it on dev environments. No more update --dev, the dev flag is now implicit and if you really don't want these packages installed you can use update --no-dev instead.
The install command on the hand remains the same. It does not install dev dependencies by default, and it will actually remove them if they were previously installed and you run it without --dev. Again this makes sense since in production you should only run install to get the last verified state (stored in composer.lock) of your dependencies installed.
I think this minor change in workflow will simplify things for most people, and I really hope it doesn't break any assumptions that were made in third party tools.
PHP just does some things better. cloud backups, pecl-expect
Backups, yes we do backup occasionally, and I've been looking for a better solutions than my historical office<->hosting replication, which although cheap, always made me wonder if I was still making copies. So after our recent office move, and minor server upgrade, I thought better double check on it all.. As usual, the thing had failed due to various reasons, and needed replacing.
On Taming Repository Classes in Doctrine
Over at the easybib/dev Blog Anne posted an entry about their usage of Doctrine Repositories with a growing amount of query responsibilities. I want to respond to this blog post with two alternative approaches, because I have seen the easybib approach multiple times in different projects by different teams and think it can be approved upon a lot.
The problems with the approach outlined are:
The Repository API does not hide implementation details of the ORM, the QueryBuilder API is returned to the client code. This might seen like nitpicking, however it leads to bloated client code doing the query builder work over and over again. For example the ->getQuery()->getSingleResult(AbstractQuery::HYDRATE_ARRAY) call.
Different parts of the QueryBuilder filtering cannot be composed together, because of the way the API is created. Assume we have the filterGroupsForApi() call, there is no way to combine it with another call filterGroupsForPermissions(). Instead reusing this code will lead to a third method filterGroupsForApiAndPermissions().
This can lead to combinatorial explosion of methods that the developer using the repository needs to know. And wading through a list of 100 methods to find the right one is never fun, most importantly when the naming of methods is imprecise.
Generally introducing a new object such as a repository should pass the “Composite is simpler than the sum of its parts” rule. However the approach also clearly demonstrates a bad abstraction. In OOP the primary goal is avoiding changes to affect the whole system.
Instead of using the QueryBuilder outside of the Repository, lets start with an alternative refactoring. I will introduce a Criteria class for the User:
<?php
class UserCriteria
{
public $groupId;
public $hydrateMode = Query::HYDRATE_OBJECT;
}
It is important not to introduce a constructor here, because when we add more and more criterions, the constructor will get bloated. Static factory methods that create a criteria do make sense however.
Now we can introduce a match method on the UserRepository. Lets see that on an interface level first, to see how simple usage is for the client side of the repository:
<?php
interface UserRepository
{
/**
* @param UserCriteria $criteria
* @return array<User>|array<array>
***/
public function match(UserCriteria $criteria);
}
Put in a $criteria get back users or array data. Very nice and simple! The implementation would look like this:
<?php
/**
* @param UserCriteria $criteria
* @return array<User>
***/
public function match(UserCriteria $criteria)Truncated by Planet PHP, read more at the original (another 34441 bytes)
pecl_http-1.7.5
Nearly a year and 170k downloads after the last release (1.7.4 was released April 2nd 2012).
It fixes a single bug:
- Bug #64310 (weak etags W/"abc" are quoted as "W/"abc"")
- If you utilize libcurl's TIMECOND feature through pecl_http's lastmodified request option, libcurl ignores response bodies from servers that do not closely follow the RFC and send a 200 OK response instead of a 304 Not Modified when the condition is unmet.
Confoo: Testing, Performance, Metrics and APIs
Bottleneck Analysis Slides from Confoo
On predictable PHP release cycles
There is currently a vote going on to include Zends Optimizer+ opcode cache into PHP core. I am very happy with finally adding an opcode cache to the core distribution if only because it then forces to actually ensure that there is a working opcode cache together with every new release. What troubles me though is that its being proposed very late in the game for PHP 5.5, therefore causing a likely delay of 5.5 of at least about 2 months in the best case scenario if it were included. The other option of including it in 5.6 does not seem to be as popular at this point. This saddens me quite a bit since I believe that predictable release cycles would carry several advantages. First and foremost it will ensure that developers that propose a new feature will have a better idea of when their feature will be part of a release. This can encourage developers to actually bother with sharing code and it also prevents developers from getting disgruntled if their feature is deemed not yet ready for the upcoming release or even more importantly prevents half baked solutions from being pushed in just to prevent an unknown further wait time. Furthermore it makes it easier for PHP end users, especially larger frameworks and application maintainers, to plan their releases. Finally it poses the chance that distributions will better schedule the freeze time for PHP versions, rather than the current rather random choice they tend to do.
Now people (ok Zeev in particular) are throwing around numbers in regards to adoption rates. They are talking about how quickly new features are adopted by frameworks etc. However none of the presented data holds much use for this argument. We have never had predictable releases over a long period of time. So right now we are still not predictable. Furthermore it takes time for these frameworks/applications/distributions, even if they have the trust that PHP actually follows its release cycles, to actually start getting used to this and leveraging this in their planning.
The reality is that its quite easy to find a new must have feature for every release that makes it worth in the short term to delay the release a little bit, thereby getting a feature a feature 10-11 months earlier. But if we do this even every 2nd or 3rd release, we loose the benefit of a predictable release cycle. What is even stranger for this case is that we are just talking about an extension here. Its not a language feature, there is no engine level integration. So even if its not added to core, people can easily get Optimizer+ via PECL. So in this case we are not talking about people having to wait another 10-11 months. Don't get me wrong I think getting an opcode cache into core is awesome, but the reality is that shared host users will probably still not have access to it (correct me if Optmizer+ is more shared host friendly than APC) and the rest can still get it, albeit with a bit more effort. So I really do not understand the rush here ..
Update: Anthony makes some additional very good arguments why there is no reason to delay.