Lorna MitchellUsing Phing with Travis CI (17.7.2014, 15:44 UTC)

We've started using Travis CI on one of my projects to run some build processes to check that everything looks good before we merge/deploy code. One thing I ran into quite quickly was that I wanted to install phing in order to use the build scripts we already have and use elsewhere, but that it isn't provided by default by Travis CI.

In fact, you can install phing by adding it to the before_install section of your .travis.yml; so the file could look something like this:

language: php
  - "5.4"

  - pear channel-discover pear.phing.info
  - pear install phing/phing
  - phpenv rehash

    - phing -f src/build.xml phplint

That rehash is the magic sauce that makes your path pick up phing and so be able to run the command in the script section. I expect phing to be quite a common requirements for PHP projects, so it's good to know that it can easily be used with TravisCI.

Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only). This post was originally published at LornaJane

Bruno ŠkvorcA First Look at OroCRM and Extending with Bundles (16.7.2014, 16:00 UTC)

CRMs are a tricky business. What some devs consider to be “just log everything about the user” apps, others know to be incredibly advanced and convoluted business apps that not only monitor your interactions with the user, but improve both your communication with them and their experience with you - without either of you knowing that explicitly.

What’s a CRM?

Customer Relationship Management apps are often underrated and underused, and far too frequently “included” in the base of a company’s app. If you’ve ever worked in an office cubicle for a large company doing menial work day in day out, chances are you’ve had the company’s (ancient Java) app running in front of you on Windows XP, and if something important about a customer you were just talking to came up, it would be marked in a silly comment box next to their name in an obscure corner of the screen, if that.

CRM is much more than what you’re usually lead to believe - it’s not just semi-relevant and subjective information about a person you once did business with - it’s a collection and collation of all the knowledge about your interactions, and a presentation of all the parameters that statistically help you gain the favor of your correspondent.


Though the CRM field of the PHP world isn’t madly ripe, the recent flurry of developments from Oro had my interest piqued enough to make me take a look. OroCRM is a multi-language CRM built on PHP 5.4+ with the Symfony framework. It’s a behemoth in its own right, and is tuned nicely for cooperation with the Oro Platform, a business application skeleton you can use to build your own custuom business apps that take advantage of the data OroCRM provides. That’s a bit much for this piece, though, so we’ll just take a look at OroCRM this time. Note, however, that an OroCRM installation brings with itself an underlying instance of the Oro Platform, which it is based upon.

OroCRM was also announced on the Symfony2 blog, so give it a read if you’re interested in its youth - it was only four months ago.

Among other features, OroCRM boasts with their marketplace for third party plugins and extensions, their customer segmentation, and import of data from various established tools like Magento. Let’s see how it stacks up in a locally deployed demo app.

Continue reading %A First Look at OroCRM and Extending with Bundles%

Derick RethansNo to a Uniform Variable Syntax (16.7.2014, 15:48 UTC)

No to a Uniform Variable Syntax

As you might have heard, PHP developers voted on an RFC called "Uniform Variable Syntax". This RFC "proposes the introduction of an internally consistent and complete variable syntax". In general, this RFC argues for making PHP's parser more complete for all sorts of variable dereferences. For example:

[$obj1, $obj2][0]->prop

Thirty people voted for, and one against: Me.

Does that mean that I am against a unified variable syntax? No, I am not. I am actually quite a fan of having a consistent language, but we need to be careful when this hits existing users.

The already accepted RFC also has some negative aspects, in the form of backwards compatibility (BC) breaks. For example (quoted from the RFC):

// syntax               // old meaning            // new meaning
$$foo['bar']['baz']     ${$foo['bar']['baz']}     ($$foo)['bar']['baz']
$foo->$bar['baz']       $foo->{$bar['baz']}       ($foo->$bar)['baz']
$foo->$bar['baz']()     $foo->{$bar['baz']}()     ($foo->$bar)['baz']()
Foo::$bar['baz']()      Foo::{$bar['baz']}()      (Foo::$bar)['baz']()

This basically says that the RFC author knows there are BC breaks, but choses to ignore how this might annoy users.

Unlike keyword additions, or functions and/or settings being removed, this change in semantics is probably one of the worst BC breaks you can imagine. You can't really write a scanner for it, as the code could already have been converted. A tiny change like this however, can create very hard to debug issues within existing code. And this is exactly why people whine that PHP breaks BC and does not care about its users. In many cases, breaking BC happens by accident, and I'm no stranger to breaking BC due to some oversight. Accidents like this are certainly annoying, but slightly unavoidable as we do not have test cases for everything.

However, when you know for certain that you are going to break BC, there is no excuse. With such a marginal new "feature" as is outlined in this RFC, antagonising our users is not a good thing.

Davey ShafikCelebrating 10 Years of PHP 5.0 (15.7.2014, 20:45 UTC)

Yesterday I published a blog post on the Engine Yard Blog, Celebrating 10 Years of PHP 5.0.0.

As part of this post I researched and put together a timeline of the last 12 years (since the initial public release of Zend Engine 2) for PHP.

It’s always fun to be nostalgic, you should check it out.

I’ve been involved in PHP since right before PHP 4.0 went final, which means I never wrote code for PHP 3, and in that time I’ve seen our community grow alongside the language I love, and while other languages have come (and gone in some cases!) PHP has continue to grow, and at a pace that seems to be accelerating rather than slowing down as some seem to think.

This year has also seen the 5th anniversary of PHP 5.3 and PHAR (PHP Archives), and next year will be 15 years since PHP 4.0.0.

Obviously time marches ever forward, and the current question on every bodies mind is: what’s next? It looks like we’ll continue to see major improvements in performance thanks to phpng, and with that meaning a new major version due to internals BC breakage… hopefully we’ll see even more radical changes to the language.

Christian Weiskephorkie 0.4 with single-click remote forking (15.7.2014, 20:24 UTC)

I've just released phorkie 0.4.0, which brings you single click remote forking as well as a bunch of other new features.

Single-click remote forking

Phorkie is a self-hosted pastebin tool, but the fun of pastes on gist.github.com comes from the fact that you can simply click the "fork" button on a paste to make it your own.

Version 0.4 makes forking pastes from another user's phorkie instance to your own server as easy as clicking on the "Fork to remote system" button.


At first you need to tell your browser that your phorkie instance is the target of web+fork actions:

  1. Visit a paste on your server
  2. Fork dropdown Open the dropdown beside the "fork" button. Click "Help on remote forking".
  3. Register web+fork protocol handler Click "Register web+fork protocol handler".
  4. Confirm the browser's registration question.

Fork a paste

Now that everything is setup, visit a paste on some other server, e.g. phar on nginx vs. apache.

Fork to remote system Click "Fork to remote system".

Remote paste has been forked Your own phorkie instance will show up with the message "Remote paste has been forked".


I spent a considerable amount of time making phorkie work from inside a .phar file.

The phar contains all dependencies, and phorkie does work without configuration now (sensible auto-configuration!). So theoretically all you need is to drop the .phar into your web server's document root, and phorkie simply works.

Unfortunately, this is not reality (for now).

  • No Linux distribution I know lets PHP handle .phar files. Accessing a .phar with your browser will show you the source code in most cases.

    I've opened bug reports for Debian and Fedora for that issue.

  • Web-based .phar applications on FPM-fcgi do not work but will give you a redirection loop.

    I made a patch that is included in PHP 5.6.0, 5.5.15 and 5.4.31, so unless you have one of this or a higher version, you're out of luck.

Remote fork display

Remote fork display

Forking remote pastes is not fun when you don't see who forked, and from where you forked.

When forking a paste, your phorkie will talk to the remote system by sending a linkback (Webmention or Pingback)

The remote system then verifies the fork by checking your newly forked paste HTML page and adds it to the "Forks" list.

Get it

phorkie's .phar and .tar.bz2 release is available on it's homepage on sourceforge.

The source code can be found on sourceforge's git server and github.

Happy forking!

Bruno ŠkvorcSocial Network Authentication: Merging Accounts (15.7.2014, 16:00 UTC)

In this part, we will have a look at how we can make sure people don’t have multiple accounts after signing into our application through different means.

Merging accounts

If you allow users to sign up through different social networks and perhaps your own registration system, there is a good chance some users will have multiple accounts. How annoying can it be for a user who signed up through Facebook earlier, to come back later and log in through Twitter because he thought he used that one?We can prevent this by letting the user merge manually or try to use an automatic system to try and identify duplicated users.


I suggest a setup of two database tables. The first table is the general user table, which contains all information about the user.

  `username` varchar(255) NOT NULL,
  `password` varchar(255) DEFAULT NULL,
  `firstname` varchar(50) NOT NULL,
  `lastname` varchar(50) NOT NULL,
  `emailaddress` varchar(50) NOT NULL,
  `city` varchar(50) NOT NULL,
  `birtdate` date NOT NULL,
  `gender` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)

Note: As you can see, I used the fields that we also used in our SocialLoginInterface. You might need more or less fields depending on your application. You even could decide to split this table in a user and user_profile table if you wish.

The second table contains all data regarding any third party logins the user used.

Continue reading %Social Network Authentication: Merging Accounts%

Lorna MitchellQuickly add Amazon Cloudfront as a CDN (15.7.2014, 09:21 UTC)

Right now I'm working on an application which is experiencing lots of interest - and therefore lots of load! We needed to look at ways of trying to bring down the pressure on the servers, and decided to use a CDN (Content Delivery Network) for our image files. It was surprisingly painless to implement once I got into it so here it is in case it's helpful.

The way it works is that you point your image URLs to Amazon, and Amazon knows how to map those onto the images which continue to live where they are on your webserver and to be accessible by their own URLs. If Amazon gets a request for an image it doesn't have, it grabs it from your server and serves it - but then caches them all so the next request (or 10,000 requests!) will hit Amazon's servers and not yours. It also helps a bit because the domain is different and there is a limit on how many parallel requests browsers will make to any given domain, so you get more parallel requests on your page too.

Configurable Image Paths

I was able to switch out my image paths very easily because all images in the system had a path like $config['productImagePath'] - mostly this can help on dev platforms if they're not all the same, but also it helps if you need to move your images at a later date, as I had known could happen (and it did!). If this isn't already in place, you need to go find every image and make its URL configurable.

Set up Amazon Cloud Front

Head over to your Amazon Web Services console https://console.aws.amazon.com (it'll prompt you to sign up or log in as appropriate) and look for "Amazon CloudFront" in the "Storage" section.

Click the "create distribution" button and configure a few things:

  • Delivery method: web
  • Origin domain name: [domain where the images are served from right now]
  • Price class: choose which regions you need your images served from, it affects the cost

Then you need to wait for a few minutes while the cogs turn and it all gets created.

Testing Your Setup

You will get a URL for your CloudFront that looks like http://uttergobbledegook.cloudfront.net and you use that in place of the source domain you set earlier. So if your images were at http://mygreatsite.com/product_images/whisk.jpg now you should be able to request http://uttergobbledegook.cloudfront.net/product_images/whisk.jpg in your browser. Once it's cached, the response time should be very quick too.

Now go back and where your configuration settings once pointed to a URL on your own site, they will now point to the path under the CloudFront domain ... you probably need different distributions for your various staging/live platforms, and these can be enabled and disabled differently.

I found this was a very painless way of getting a CDN into place - no changes to the development platforms, minor config changes to the staging/live platforms, and the images stay in the same place that they always lived!

Whatever Next?

There are actually a few things you can do from here:

  • Use a cname alias to make a nicer URL such as http://static.mygreatsite.com
  • Tweak the caching rules to make sure they make sense for your application, they are very VERY configurable
  • If the images you're serving are assets rather than upload files, consider deploying them straight to S3 and setting up your CloudFront to server from there

Did this work for you? What did I miss? And did Amazon update their interface since I wrote this post (this happens often). Please leave a comment :)

Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only). This post was originally published at LornaJane

Bruno ŠkvorcSocial Network Authentication: Google+ (14.7.2014, 16:00 UTC)

In the previous part of this series, we created our initial interfaces which we’ll be using for all future parts. In this article, we will integrate Google+ within our application.

You can view the code for all the articles on this Github page.

Google+ login

We start off by creating the following directory: src/SitePoint/SocialLogin/Google. This will be the directory we will be working in for the rest of the article. Within this directory, we create the GoogleLogin class. This class implements the SocialLoginInterface interface which we created in the previous article. Make sure a property called service is available to store our service in (see code below).

Google has some specific needs to make sure we can log in. So make sure we have the following 3 properties present in the class:
- client id
- key
- callback URL

Since all 3 properties are required for our application to work, our constructor will receive these 3 variables as parameters and set the properties.

Until now, our code looks like this.


namespace SitePoint\SocialLogin\Google;

use SitePoint\SocialLogin\Interfaces\SocialLoginInterface;

class GoogleLogin implements SocialLoginInterface {

     * Google service
     * @var string
    protected $service;

     * OAuth client ID
     * @var string
    protected $clientId;

     * OAuth key
     * @var string
    protected $key;

     * Callback url
     * @var string
    protected $callbackUrl;

     * Constructor
     * @param $clientId string
     * @param $key string
     * @param $callbackUrl string
    public function __construct($clientId, $key, $callbackUrl)
        $this->clientId = $clientId;
        $this->key = $key;
        $this->callbackUrl = $callbackUrl;

     * Initializes our service
    public function init()


     * Returns the login url for the social network
     * @return string
    public function getLoginUrl()

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

Bruno ŠkvorcGuide: How to Install OroCRM on a Vagrant Box (13.7.2014, 19:00 UTC)

OroCRM is a CRM application we’ll be describing in a post dedicated to it tomorrow. This guide merely covers its installation and first run on a Vagrant Box - in particular, our good old Homestead Improved. If you need to get up and running with Homestead, see the original Quick Tip. If you want to follow along with tomorrow's post on OroCRM, get a head start by installing it with the procedures below!


Before we begin, make sure your original Homestead Improved instance is working well, then destroy it. If you want symlink support and are on Windows, re-run the command prompt and/or Git Bash window through which you’ll be using Vagrant commands with Administrator privileges:

This is optional - symlinks are not required for Oro to work.

Step 1: Add a Site

In Homestead.yaml, add the site:

    - map: test.app
      to: /home/vagrant/Code/orocrm/web

The web subfolder is needed due to Symfony being the foundation Oro is built upon. This is the last operation we’ll do outside the VM. Enter it now with vagrant ssh after running vagrant up.

Step 2: Clone

cd Code
git clone http://github.com/orocrm/crm-application.git orocrm

Step 3: Create the Database

mysql -u homestead -psecret

Step 4: Configure Nginx and PHP

The configuration required for OroCRM in this case is as follows (replace the folder paths with your own if necessary). Put this into /etc/nginx/sites-available/test.app, replacing the original content:

Continue reading %Guide: How to Install OroCRM on a Vagrant Box%

Official Blog of the PEAR Group/PEAR PresidentPEAR 1.9.5 is out (12.7.2014, 19:48 UTC)

The PEAR installer version 1.9.5 has been released today.

The new version – three years after the last stable 1.9.4 and 2 weeks after the preview – is a bugfix only release. 13 bugs have been fixed. Among them are the following:

  • #18466: Modifying paths during installation broken on Windows
  • #20203: PEAR channels on github user pages do not work
  • #20283: Report correct php.ini directive on xdebug installation (and every other zend_extension)

Our plan is to work on a new version 1.10 that is E_STRICT and E_DEPRECATED clean and ships a couple of new features.

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