Mike's sudden inspirationsHear, hear (18.6.2013, 16:26 UTC)
I was about to write "in early February" but actually it already was in late January that I stumbled over this tweet:
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js">
Fast-forward five months – now I am very excited to be able to announce that the Awesomes over at SmugMug, Inc. have hired me to work full-time on the core of PHP.

Hide bugs.php.net, expect massive amounts of commits, sleep well. Thank you for reading the simple words of the proudest man alive. Thank you SmugMug!

Link
Fabien PotencierPacking a Symfony full-stack Framework Application in one File -- Bootstrapping (18.6.2013, 08:30 UTC)

This article is part of a series of articles that explains how to pack a Symfony full-stack application in one file. The first article explains why this might actually be useful: 1) Introduction, 2) Bootstrapping, ...

The most common way to create a Symfony project is to start with the Symfony Standard Edition: it defines a sensible directory structure for your project and it make things a lot easier when someone want to take over an existing project as he knows where the templates, the controllers, or the configuration are stored. So, let's start our journey with the Symfony Standard Edition:

$ composer.phar create-project -n symfony/framework-standard-edition se/ 2.3.0

From there, let's remove a bunch of code to get the bare minimum of code needed to keep it working:

rm -rf LICENSE README.md UPGRADE* bin/ app/SymfonyRequirements.php \
       app/autoload.php app/bootstrap.php.cache app/AppCache.php app/check.php \
       app/console app/phpunit.xml.dist app/Resources src/ web/config.php \
       web/favicon.ico web/robots.txt web/apple-touch-icon.png web/app.php web/bundles/ \
       app/cache/* app/log/* .travis.yml app/.htaccess web/.htaccess
 

I've removed all those files and directories because there are not needed for the purpose of our challenge.

Next, let's simplify the configuration and move everything into just one file:

# app/config/config_dev.yml
framework:
    secret:          $ecret
    router:
        resource: "%kernel.root_dir%/config/routing_dev.yml"
    form:            ~
    csrf_protection: ~
    validation:      { enable_annotations: true }
    templating:
        engines: ['twig']
    session:         ~
    fragments:       ~
 

The routing_dev.yml file has been emptied for now, and all other configuration files have been removed.

We can also remove most of the bundles from the application kernel class:

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
 
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        return array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
        );
    }
 
    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
    }
}
 

We can also simplify the web/app_dev.php code:

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;
 
require_once __DIR__.'/../vendor/autoload.php';
Debug::enable();
 
require_once __DIR__.'/../app/AppKernel.php';
 
$kernel = new AppKernel('dev', true);
$request = Request::

Truncated by Planet PHP, read more at the original (another 2876 bytes)

Link
Michael KimsalSmall catch up (17.6.2013, 21:17 UTC)

So… I didn’t write much since April.  I took a bit of time off and went to Russia (some pics here - more to come later), and have been finishing up some contracts in May/June, and am now looking for the next thing to sink my teeth in to, so to speak (ping me if you’ve got an interesting project you think I might be a fit for).

We’ve got an interesting talk on PHP’s Composer project slated for our next PHP user group in Raleigh with our very own Jason Grimes - definitely looking forward to this one (come on out if you’re anywhere near the area!)  If you don’t follow Jason already, get to it – he’s got a lot of useful stuff on his blog.

The indieconf conference for web freelancers is coming again this year – still nailing down a date – but the call for presenters is open right now – submit your proposal to present if you’re interested in joining us this year!

It’s hard to believe 2013 is almost half over already!!!


I'm currently working on a book for web freelancers, covering everything you need to know to get started or just get better. Want to stay updated? Sign up for my mailing list to get updates when the book is ready to be released!

Web Developer Freelancing Handbook

Link
PHP ClassesPHP 5.5 Release Date Imminent - Lately in PHP podcast episode 36 (17.6.2013, 09:42 UTC)
By Manuel Lemos
The PHP 5.5.0 final release is about to happen. After about 16 months of development PHP 5.5 is bringing even more maturity to the PHP language, which by Google numbers is present in 75% of the Web sites.

This was one of the main topics discussed by Manuel Lemos and Ernani Joppert in the episode 36 of the Lately in PHP podcast.

They also discussed some new features proposed for PHP 5.6 like incremental decoding of large JSON data streams and overloading arithmetic operators for arbitrary precision math.

They also debated the meaning of Google finally adding support to PHP in their cloud hosting platform Google AppEngine.

Also in this episode it was discussed an article about good practices to quickly detect and fix PHP code bugs that only show up in production environments.

Listen to the podcast, or watched the Google hangout video, or read the text transcript to learn more about these very interesting PHP topics.
Link
Fabien PotencierPacking a Symfony full-stack Framework Application in one File -- Introduction (17.6.2013, 08:00 UTC)

This article is part of a series of articles that explains how to pack a Symfony full-stack application in one file. The first article explains why this might actually be useful: 1) Introduction, 2) Bootstrapping, ...

Sometimes, I'm wondering if I'm not just completely crazy. I like small things, but I'm the author of Symfony, a not-so-small framework (about eighty thousand lines of code excluding comments as of today). And that's probably because I like to push the limits of what's possible when coding.

In 1985, my first useful piece of code was about managing a portfolio of stocks for my parents. I was twelve years old at that time. I won a contest. It was an interesting challenge: coding a full game in less than 10 lines of code. And my code was published in a French magazine.

In 2009, I tweeted an implementation of a dependency injection container in less than 140 characters (I did the same with a web framework).

And most of the time, those experiments helped me get to the next level. Twittee, my service container that fits in a Tweet, was an experiment, but then, it became Pimple, a small dependency injection container that is used today in Silex, a micro-framework based on the Symfony components.

So, that's not about just trying to push the limits, or trying to have fun. It's also about experimenting different approaches to known problems and see if they can have practical usage.

So, 2013... time for another challenge, right? What about packing a Symfony full-stack application in a single file. No Silex, no phar allowed, no compilation phase, just everything in a single readable file: from assets to controllers, from templates to Composer configuration.

Why?

This is yet another step toward my Quest of the PHP Holy Grail. But besides being a though challenge, there are many other reasons that makes it interesting for everyone.

First, that's a good way to learn more about the Symfony internals and especially about the Kernel class. Nowadays, thanks to all the talks about HttpKernel given by various speakers at various conferences, and thanks to my series of articles about it on my blog, a lot of developers understand how Symfony handles requests and how it manages the conversion to responses. There is even a full chapter about it in the official documentation.

But the Symfony Kernel is less well-known. This is a shame as it is also a very interesting piece of software. I hope that this challenge will give you more information about the Symfony Kernel and that, as a result, more Open-Source projects will adopt it instead of just using the components.

Then, I want to showcase once more the flexibility of the Symfony core framework and the decoupling between all aspects of the framework. If you are just a Symfony developer, you might not realize how the low level architecture of Symfony works, and I'm going to give you some insights about it.

Also, there is a more practical usage: bug reporting. When you report a Symfony bug, sometimes, it is not that easy to reproduce it. Probably because it involves third-party bundles, a specific configuration, or a chain of controller calls. For such bugs, it is almost impossible to make a patch without a way to reproduce it. As a matter of fact, we often ask reporters to fork the Symfony Standard Edition and modify it in a way that exhibits the issue. But doing so is tedious for both the reporter and the developer that will try to fix the bug. Doing the same with Silex is more easier as most of the time, the reporter is able to package everything is a single file. So, being able to do the same with the full-stack framework would be a huge step forward.

Reporting bugs is fine, but being able to experiment things in a small environment also helps. A few weeks ago, Jordi submitted a new API layer to simplify the configuration of Symfony's Security. To better understand how to use it and to get a feeling for the new API, I decided to create

Truncated by Planet PHP, read more at the original (another 2550 bytes)

Link
Anthony FerraraGoogle Glass - A First Impression (17.6.2013, 00:49 UTC)
This past Thursday evening I picked up my Explorer edition of Google Glass. I was lucky enough to have my #ifihadglass tweet chosen to receive the chance to pay an arm and a leg to get them. Needless to say, I did choose to pony up the cash, and on Thursday evening I walked home with my brand new piece of technology dangling off of my right temple. Since first impressions are often strong, but can be misleading, I chose to wait until I had used them for a few days before writing my thoughts. So here they are:

Read more »
Link
Qafoo - PHPEmbedding REST Entities (13.6.2013, 08:35 UTC)
During my talk at IPC Spring I showed an approach for embedding entities in REST responses. This methodology might be useful if the standard use-case for your API is to request multiple related entities together. The downside of such an approach is the raised complexity of caching and especially purging logic. In this blog post I will further elaborate on the approach of resource embedding.
Link
Ulf WendelPHP: PECL/mysqlnd_ms 1.6 – automatic retry loop for transient errors (12.6.2013, 09:56 UTC)

PECL/mysqlnd_ms is client-side load balancing driver plugin for PHP MySQL that aims to increase distribution transparency when using any MySQL based cluster: failover, read-write splitting, abstraction on consistency (e.g. read-your-writes), partitioning/sharding support, … it’s all there. Until a few minutes ago, we had no special handling of transient errors. Sometimes a database server replies “come back in a bit and retry, no need to fail over yet”. And, that’s what the client shall do before giving up. PECL/mysqlnd_ms 1.6 (development version) is capable of hiding the retry loop, which makes it easier to use any existing PHP MySQL application with a cluster of MySQL servers.

Transient (temporary) errors are rarely observed with MySQL Replication but can be seen with MySQL Cluster. MySQL Cluster is an eager (synchronous) update anywhere (multi-master) cluster: all replicas accept reads and writes, replication is synchronous. See also the slide deck DIY: A distributed database cluster, or: MySQL Cluster for a brief introduction in distributed database theory relevant to MySQL users (presentation from the International PHP Conference 2013 Spring Edition).

Transient errors

MySQL Cluster scales well for write loads because it features transparent sharding (see slides). It automatically partitions data over multiple replicas. Over the time, for example, when adding replicas to the cluster, data may b redistributed. Rebalancing is an online operation, it does not lock out clients. Thus, you may observe a temporary error such as:

ERROR 1297 (HY000): Got temporary error 1204 'Temporary
failure, distribution changed' from NDBCLUSTER 


There may be other causes for temporary errors as well. In any case, its safe to ignore a 1297/HY000 and retry the command.

The latest versions of MySQL Cluster feature an implicit retry loop before returning the error to the client, if it is believed that your command is not time critical. Means, Cluster resends the command for you a couple of times with a short sleep period in between before returning control to the client to tell about the temporary problem. PECL/mysqlnd_ms 1.6 alpha got a similar loop: very basic and experimental. Here’s the idea.

Automatic retry loop

The dream of Andrey when he created PECL/mysqlnd_ms was to make using a cluster transparent. It should be possible to move an application from a single MySQL to a cluster of MySQL servers without code changes. Thus, as a first step, I have opted against offering a callback to decide on errors (like Connector/J does). Instead, it is possible to configure the retry loop in the config file.

The example config snippet instructs the driver plugin to start an implcitiy command retry loop when there is an error with the error code 1297. Its possible to configure a list of arbitrary error codes. Whenever 1297 happens, the command is retried for max_retries = 2 times. Between the retry attemps PECL/mysqlnd_ms 1.6 sleeps for usleep_retry = 100 milliseconds. In an ideal world, the temporary error is gone by the end of the wait loop. In the worst case of the error persisting, it is forwarded to whatever PHP API you use (mysqli, PDO_MySQL) leaving it to your application to deal with it.

{
  "myapp": {
    [...]
    "transient_error": {
      "mysql_error_codes": [
        1297
      ],
      "max_retries": 2,
      "usleep_retry": 100
    }
  }
}


Please, send us your feature requests: this is a "live report" from the hacking and nothing is set.

You can check whether an implicit retry loop has been performed by inspecting the statistics provided by PECL/mysqlnd_ms.

$stats = mysqlnd_ms_get_stats();
printf("Implicit retries to hide transient errors: %d", 
  $stats['transient_error_retries']);

Failover vs. transient error

When talking to a cluster instead of a single machine there are two additional error conditions to handle:

  • Permanent error: replica disappeared, forget about replica – for now: fail over to someone else…
  • T

Truncated by Planet PHP, read more at the original (another 1392 bytes)

Link
Derick RethansImporting OpenStreetMap data into MongoDB (11.6.2013, 08:49 UTC)

Importing OpenStreetMap data into MongoDB

In many recent MongoDB related presentations I have used OpenStreetMap data as basis for most of my examples. I wrote a script that imports OpenStreetMap (OSM) nodes, ways and to a lesser extend relations into MongoDB with a specific and optimal schema. I have written about this briefly before in Indexing Freeform-Tagged Data, but now MongoDB received numerous updates to geospatial indexes I find it warrants a new article.

In MongoDB 2.2 and before, the index type that MongoDB used was the 2d type, which was basically a two dimensional flat earth coordinate system index—with some spherical features built on top. MongoDB 2.4 has a new index type: 2sphere. Instead of just being able to index points described by x/y coordinates (longitude/latitude) it now has support for indexing points, line strings and polygons as defined by GeoJSON.

I have modified my import script to use those new types, and also added support for very simple multi-polygons that OpenStreetMap records through its relation tag. The script also creates an indexes on { l: '2dsphere' } (the GeoJson object), { ts: 1 } (the tags), and { ty: 1 } (the type).

The structure it converts a node from OpenStreetMap to looks like:

{
        "_id" : "n26486695",
        "ty" : NumberLong(1),
        "l" : {
                "type" : "Point",
                "coordinates" : [
                        -0.1580359,
                        51.4500055
                ]
        },
        "ts" : [
                "addr:housenumber=97",
                "addr:postcode=SW12 8NX",
                "addr:street=Nightingale Lane",
                "amenity=pub",
                "name=The Nightingale",
                "operator=Youngs",
                "source:name=photograph",
                "toilets=yes",
                "toilets:access=customers",
                "website=http://www.youngs.co.uk/pub-detail.asp?PubID=430"
        ],
        "m" : {
                "v" : NumberLong(5),
                "cs" : NumberLong(11229430),
                "uid" : NumberLong(652021),
                "ts" : NumberLong(1333911628)
        }
}

There are several sections that make up the document:

  • _id: Is a combination of n and the OSM node id.

  • ty: Is the type. For nodes, this is always 1.

  • l: The point's location in GeoJson format. An OSM point is translated to a GeoJson Point feature with an array describing the longitude and latitude.

  • ts: Are the tags that describe the node. Each tag is stored as a concatenation of its key and its value. This creates both a smaller index and it still allows for exact tag/value matches as well as matching against specfic keys through a regular expression match. For example, we could find the above document with:

    db.poiConcat.find( { ts: 'name=The Nightingale' } );

    And the index would also be used when we look for all amenities:

    db.poiConcat.find( { ts: /^amenity=/ } );

  • m: Contains meta information that describes the node. The following fields are currently present:

    • v: The object's version. This is the version number of the version that was found in the imported file. There is always just one version per object.

    • cs: The changeset ID in which this object was last updated.

    • uid: The user ID of the OpenStreetMap contributor who uploaded the latest version.

    • ts: The Unix timestamp of when this object was last updated.

OpenStreetMap ways are stored in two different types.

Truncated by Planet PHP, read more at the original (another 2929 bytes)

Link
Davey ShafikSpeaking at Conferences: How to write a talk and get it accepted (10.6.2013, 09:22 UTC)

After php[tek] this year (and the awesome mentorship summit), I wrote up a blog post detailing how I go about creating proposals, as well as giving some insight into how we chose proposals for Distill.

You can read that blog post on the Engine Yard Blog.

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP