Matthew Weier O'PhinneyDeployment with Zend Server (Part 2 of 8) (26.8.2014, 13:30 UTC)

This is the second in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed getting started with Zend Server on the AWS marketplace and using zf-deploy to create ZPK packages to deploy to Zend Server.

Today, I'm looking at how to created scheduled/recurring jobs using Zend Server's Job Queue; think of this as application-level cronjobs.

Tip 2: Recurring Jobs

I needed to define a few recurring jobs on the server. In the past, I've used cron for this, but I've recently had a slight change of mind on this: if I use cron, I have to assume I'm running on a unix-like system, and have some sort of system access to the server. If I have multiple servers running, that means ensuring they're setup on each server. It seems better to be able to define these jobs at the applicaton level.

Since Zend Server comes with Job Queue, I decided to try it out for scheduling recurring jobs. This is not terribly intuitive, however. The UI allows you to define scheduled jobs... but only gives options for every minute, hour, day, week, and month, without allowing you to specify the exact interval (e.g., every day at 20:00).

The PHP API, however, makes this easy. I can create a job as follows:


$queue = new ZendJobQueue();
$queue->createHttpJob('/jobs/github-feed.php', [], [
  'name'       => 'github-feed',
  'persistent' => false,
  'schedule'   => '5,20,35,40 * * * *',
]);

Essentially, you provide a URL to the script to execute (Job Queue "runs" a job by accessing a URL on the server), and provide a schedule in crontab format. I like to give my jobs names as well, as it allows me to search for them in the UI, and also enables linking between the rules and the logs in the UI. Marking them as not persistent ensures that if the job is successful, it will be removed from the events list.

The question is, where do you define this? I decided to do this in my post_activate.php deployment script. However, this raises two new problems:

  • Rules need not just a path to the script, but also the scheme and host. You _can_ omit those, but only if the script can resolve them via $_SERVER... which it cannot due during deployment.
  • Each deployment adds the jobs you define... but this does not overwrite or remove the jobs you added in previous deployments.

I solved these as follows:


$server = 'http://mwop.net';

// Remove previously scheduled jobs:
$queue = new ZendJobQueue();
foreach ($queue->getSchedulingRules() as $job) {
    if (0 !== strpos($job['script'], $server)) {
        // not one we're interested in
        continue;
    }

    // Remove previously scheduled job
    $queue->deleteSchedulingRule($job['id']);
}

$queue->createHttpJob($server . '/jobs/github-feed.php', [], [
  'name'       => 'github-feed',
  'persistent' => false,
  'schedule'   => '5,20,35,40 * * * *',
]);

So, in summary:

  • Define your rules with names.
  • Define recurring rules using the schedule option.
  • Define recurring rules in your deployment script, during post_activate.
  • Remove previously defined rules in your deployment script, prior to defining them.

Next time...

The next tip in the series is a short one, perfect for following the US Labor Day weekend, and details something I learned the hard way from Tip 1 when setting up deployment tasks.

Other articles in the series

I will update this post to link to each article as it releases.
Link
Matthias NobackDecoupling your (event) system (25.8.2014, 22:00 UTC)

About interface segregation, dependency inversion and package stability

You are creating a nice reusable package. Inside the package you want to use events to allow others to hook into your own code. You look at several event managers that are available. Since you are somewhat familiar with the Symfony EventDispatcher component already, you decide to add it to your package's composer.json:

{
    "name": "my/package"
    "require": {
        "symfony/event-dispatcher": "~2.5"
    }
}

Your dependency graph now looks like this:

Dependency graph

Introducing this dependency is not without any problem: everybody who uses my/package in their project will also pull in the symfony/event-dispatcher package, meaning they will now have yet another event dispatcher available in their project (a Laravel one, a Doctrine one, a Symfony one, etc.). This doesn't make sense, especially because event dispatchers all do (or can do) more or less the same thing.

Though this may be a minor inconvenience to most developers, having just this one extra dependency may cause some more serious problems when Composer tries to resolve version constraints. Maybe a project or one of its dependencies already has a dependency on symfony/event-dispatcher, but with version constraint >=2.3,<2.5...

Some drawbacks of the Symfony EventDispatcher

On top of these usability issues, when it comes to design principles, depending on a concrete library like the Symfony EventDispatcher is not such a good choice either. The EventDispatcherInterface which you will likely use in your code is quite bloated:

namespace Symfony\Component\EventDispatcher;

interface EventDispatcherInterface
{
    public function dispatch($eventName, Event $event = null);

    public function addListener($eventName, $listener, $priority = 0);
    public function addSubscriber(EventSubscriberInterface $subscriber);
    public function removeListener($eventName, $listener);
    public function removeSubscriber(EventSubscriberInterface $subscriber);
    public function getListeners($eventName = null);
    public function hasListeners($eventName = null);
}

The interface basically violates the Interface Segregation Principle, which means that it serves too many different types of clients: most clients will only use the dispatch() method to actually dispatch an event, and other clients will only use addListener() and addSubscriber(). The remaining methods are probably not even used by any of the clients, or only by clients that help you to debug your application (a quick search in the Symfony code-base confirms this suspicion).

Personally, I think it's not really nice that events need to be objects extending the Event class. I understand why Symfony does it (it's basically because that class has the stopPropagation() and isPropagationStopped() methods which enables event listeners to stop the dispatcher from notifying the remaining listeners. I've never liked that, nor wanted it to happen in my code. Just like the original Observer pattern prescribes, all listeners (observers) should be able to respond to the current situation.

I also don't like the fact that the same event class can be used for different events (differentiated by just their name, which is the first argument of the dispatch() method). I prefer each type of event to have its own class. Therefore, to me it would make sense to pass just an event object to the dispatch() method, allowing it to return its own name, which will always be the same anyway. The name returned by the event itself can then be used to determine which listeners need to be notified.

According to these objections to the design of the Symfony EventDispatcher classes, we'd be better off with the following clean interfaces:

namespace My\Package;

interface Event
{
    public function getName();
}

interface EventDispatcher
{
    public function dispatch(Event $event);
}

It would be really great to be able to just use these two interface in my/package!

Symfony EventDispatcher: the good parts

Still, we also want to use the Symfony E

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

Link
SitePoint PHPPINQ – Querify Your Datasets – Faceted Search (25.8.2014, 16:00 UTC)

In part 1, we briefly covered the installation and basic syntax of PINQ, a PHP LINQ port. In this article, we will see how to use PINQ to mimic a faceted search feature with MySQL.

We are not going to cover the full aspect of faceted search in this series. Interested parties can refer to relevant articles published on Sitepoint and other Internet publications.

A typical faceted search works like this in a website:

  • A user provides a keyword or a few keywords to search for. For example, “router” to search for products which contain “router” in the description, keyword, category, tags, etc.
  • The site will return the products matching the criteria.
  • The site will provide some links to fine tune the search. For example, it may prompt that there are different brands for a router, and there may be different price ranges and different features.
  • The user can further screen the results by clicking the different links provided and eventually gets a more customized result set.

Faceted search is so popular and powerful and you can experience it in almost every e-Commerce site.

Unfortunately, faceted search is not a built-in feature provided by MySQL yet. What can we do if we are using MySQL but also want to provide our users with such a feature?

With PINQ, we’ll see there is an equally powerful and straightforward approach to achieving this as when we are using other DB engines - at least in a way.

Extending Part 1 Demo

NOTE: All code in this part and the part 1 demo can be found in the repo.

In this article, we will extend the demo we have shown in Part 1 and add in some essential faceted search features.

Let’s start with index.php by adding the following few lines:

$app->get('demo2', function () use ($app)
{
    global $demo;
    $test2 = new pinqDemo\Demo($app);
    return $test2->test2($app, $demo->test1($app));
}
);

$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app)
{
    global $demo;
    $test3 = new pinqDemo\Demo($app);
    return $test3->test3($app, $demo->test1($app), $key, $value);

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

Link
PHP ClassesThe False Decline of PHP - Lately in PHP podcast episode 50 (25.8.2014, 09:07 UTC)
By Manuel Lemos
It seems the popularity of PHP continues to upset people that do not sympathize with the language for some reason. The release of yet another article claiming the PHP decline was one of the main topics discussed by Manuel Lemos and Arturs Sosins in the episode 50 of the Lately in PHP podcast.

They also discussed the latest decisions about the features being planned for PHP 7, the last release of PHP 5.3 and PHP 5.4 going into security releases mode, and the (Facebook) PHP language specification effort.

Now listen to the podcast, or watch the hangout video or read the transcript to learn more about the details of these interesting PHP discussions.
Link
Remi ColletPHP 5.6 as Software Collection (25.8.2014, 08:46 UTC)

RPM of upcoming new major version of PHP 5.6, are available in remi repository for Fedora 19, 20 and Enterprise Linux 6, 7 (RHEL, CentOS, ...) in a fresh new Software Collection (php56) allowing its installation beside the system version.

As I strongly believe in SCL potential to provide a simple way to allow installation of various versions simultaneously, and as I think it is useful to offer this feature to allow developers to test their applications, to allow sysadmin to prepare a migration or simply to use this version for some specific application, I decide to create this new SCL.

Installation :

yum --enablerepo=remi install php56

emblem-important-2-24.pngTo be noticed:

  • as the SCL is independant from the system, and doesn't alter it, this SCL is available in remi repository
  • installation is under the /opt/remi tree
  • the Apache module, php56-php, is available, but of course, only one mod_php can be used (so you have to disable or uninstall any other, the one provided by the default "php" package still have priority)
  • the FPM service (php56-php-fpm) is available, it listens on default port 9000, so you have to change the configuration if you want to use various FPM services simultaneously.
  • the php56 command give a simple access to this new version, however the scl command is still the recommended way.
  • for now, the collection provides 5.6.0RC4, but stable version should be released soon.
  • more PECL extensions will be progressively are also available.
  • only x86_64, no plan for other arch.

emblem-notice-24.pngAlso read other entries about SCL.

$ scl enable php56 'php -v'
PHP 5.6.0 (cli) (built: Aug 28 2014 08:14:49)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies
with Xdebug v2.2.5, Copyright (c) 2002-2014, by Derick Rethans

As always, your feedback is welcome, a SCL dedicated forum is open.

Link
tillWhat's wrong with composer and your .travis.yml? (24.8.2014, 00:19 UTC)

I'm a huge advocate of CI and one service in particular called Travis-Ci.

Travis-CI runs a continuous integration platform for both open source and commercial products. In a nutshell: Travis-CI listens for a commit to a Github repository and runs your test suite. Simple as that, no Jenkins required.

At Imagine Easy we happily take advantage of both. :)

So what's wrong?

For some reason, every other open source project (and probably a lot of closed source projects), use Travis-CI wrong in a way, that it will eventually break your builds.

When exactly? Whenever Travis-CI promotes composer to be a first-class citizen on the platform and attempts to run composer install automatically for you.

There may be breakage, but there may also be slowdown because by then you may end up with not one, but two composer install runs before your tests actually run.

Here's what needs fixing

A lot of projects use composer like so:

language: php
before_script: composer install --dev
script: phpunit

Here's what you have to adjust

language: php
install: composer install --dev
script: phpunit

install vs. before_script

I had never seen the install target either. Not consciously at least. And since I don't do a lot of CI for Ruby projects, I wasn't exposed to it either. On a Ruby build, Travis-CI will automatically run bundler for you, using said install target.

order of execution

In a nutshell, here are the relevant targets and how the execute:

  1. before_install
  2. install
  3. before_script
  4. script

The future

The future is that Travis-CI will do the following:

  1. before_install will self-update the composer(.phar)
  2. install will run composer install
  3. There is also the rumour of a composer_opts (or similar) setting so you can provide something like --prefer-source to the install target, without having to add an install target

Fin

Is any of this your fault? I don't think so, since the documentation leaves a lot to be desired. Scanning it while writing this blog post, I can't find a mention of install target on the pages related to building PHP products.

Long story short: go update your configurations now! ;)

I've started with doctrine/cache and doctrine/dbal, and will make it a habit to send a PR each time I see a configuration which is not what it should be.

Link
Matthias NobackSymfony2: Event subsystems (23.8.2014, 22:00 UTC)

Recently I realized that some of the problems I encountered in the past could have been easily solved by what I'm about to explain in this post.

The problem: an event listener introduces a circular reference

The problem is: having a complicated graph of service definitions and their dependencies, which causes a ServiceCircularReferenceException, saying 'Circular reference detected for service "...", path: "... -> ... -> ...".' Somewhere in the path of services that form the circle you then find the event_dispatcher service. For example: event_dispatcher -> your_event_listener -> some_service -> event_dispatcher.

Your event listener is of course a dependency of the event_dispatcher service, but one of the dependencies of your event listener needs the event_dispatcher itself! So you accidentally introduced a cycle in the dependency graph and now you need to dissolve it.

The wrong solution: injecting the service container

Assuming there is no way to redesign these services in a better way, you finally decide to make the event listener "container-aware". You will fetch some_service directly from the service container, which gets injected as a constructor argument:

use Symfony\Component\DependencyInjection\ContainerInterface;

class YourEventListener
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function onSomeEvent()
    {
        $someService = $this->container->get('some_service');

        ...
    }
}

This will break the cycle since you depend on something else entirely: event_dispatcher -> your_event_listener -> service_container. However, it also introduces a nasty dependency on the service container, making your class coupled to the framework, the service definitions themselves, and making it less explicit about its actual dependencies. Besides, I really think that a dependency issue at configuration level should not affect a class this much.

The solution

There is an entirely different and much better way to break the cycle, which is to avoid any dependency on the main event_dispatcher in your own services at all. Let me explain this to you.

In the past, whenever I introduced a new event in my code, I used the application's main event_dispatcher service to dispatch the event and I also registered any listeners for the new event to the same event_dispatcher, using the kernel.event_listener service tag like this:

services:
    my_service:
        arguments:
            - @event_dispatcher

    my_event_listener:
        class: ...
        tags:
            - { name: kernel.event_listener, event: my_event, method: onMyEvent }

However, the application's main event dispatcher depends on so many services (via the event listeners registered to it), that sooner or later the dependency mess will start to show cycles. Still, to work with events, we need an event dispatcher (or event emitter, event manager, etc.). Since our code is already written with the Symfony EventDispatcherInterface in mind, we just need to work around the main event_dispatcher service.

Event subsystems

We can avoid the event_dispatcher altogether by introducing event subsystems.

In the old situation we depended on the event_dispatcher. In the new situation, each set of custom events comes with its own event subsystem. This subsystem consists of a dedicated event dispatcher, and an easy way to register event listeners for the custom events.

Since Symfony 2.3 it's really easy to set up your own event dispatcher and to conveniently register event listeners and subscribers in the same way as before.

Example: a subsystem for domain events

A highly relevant example would be an event subsystem for domain events. You don't want those events to be dispatched by the same event dispatcher that Symfony2 uses for its core events.

To be able to use the domain event subsystem, we first need to define a new event dispatcher service:

services:
    domain_event_dispatcher:
        class: Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher
        arguments:
            - @service_container

Now we want to register event listeners for the domain event subsystem in the following, familiar way:

services:
    some_domain_event_listener
        class: ...
        tags:
            - {
                name: domain_event_listener,
                event: my_domain_event,
        

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

Link
SitePoint PHPQuick Tip: Install Zephir and Phalcon 2 on Vagrant (23.8.2014, 08:25 UTC)

This quick tip will show you how to install Phalcon on a Homestead Improved instance, and will help you get a sample Phalcon app up and running.

The version of Phalcon we’ll be using in this Quick Tip will be 2.0 - a pre-release. If you read this when Phalcon is already in a mature 2.x stage, let us know and we’ll update the post. To install the stable 1.x version, just run sudo apt-get install php5-phalcon and it should work.

Continue reading %Quick Tip: Install Zephir and Phalcon 2 on Vagrant%

Link
SitePoint PHPBuild a New App with Laravel and EmberJS in Vagrant (22.8.2014, 16:00 UTC)

Nowadays, everything is turning into a web application. Even simple websites have a mobile app relying on a REST Api. Web applications are accessible everywhere - on a laptop, desktop, tablet, mobile, and recently on wearable devices like smartwatches. Everything is becoming smaller and faster - front ends are becoming separated from back ends, and only communicate with the server through APIs.

What will we be building?

In these series, we are going to create a photo uploading app. For the front-end, we will use EmberJs and Foundation 5. EmberJs is a front-end framework featuring good integration with REST Apis. Foundation 5 will help us make a fast prototype of our front end. For hosting, we will use Heroku’s free tier (for more information about PHP on Heroku, see here). For the back-end, we will use Laravel. The source code will be available per-part, and in final shape in the final part of this series. You can download the code for part 1 here.

Let’s get started

A good way to start a new project in PHP is using Vagrant. Vagrant gives us the space to experiment a lot from project to project. I can have different PHP versions if I want with Apache for one project, Nginx for another. If something goes bad, I revert all my work and simply vagrant up after that - and I never pollute my host operating system with various other installations.

The easiest way to get started is by following this quick tip, which will take you through a fast installation process and show you a working Laravel app in a matter of minutes so you can start hacking away. If you’re still not convinced why you should use Homestead and Vagrant, see here.

Continue reading %Build a New App with Laravel and EmberJS in Vagrant%

Link
Paul ReinheimerManaged Accounts at WonderProxy (22.8.2014, 01:14 UTC)

I’ve made plenty of mistakes in the code powering WonderProxy, perhaps most famously equating 55 with ∞ for our higher-level accounts (issues with unsigned tinyint playing a close second). Something I think I got right though, was the concept of “managed accounts”. It’s a simple boolean flag on contracts, and when it’s set, the regular account de-activation code is skipped.

Having this flag allows us to handle a few things gracefully:

  • Large value contracts
    By marking them as managed, they don’t expire because someone was on vacation when the account expired. They stay happy, the revenue continues, the expiry date remains accurate.
  • Contracts with tricky billing processes
    The majority of our contracts pay us with PayPal or Stripe. A selection of contracts however have complex hoops involving anti-bribery policies, supplier agreements etc. This gives us some time to get this ironed out.
  • Contracts where we’ve failed to bill well
    We occasionally make mistakes when billing our clients. When we’ve screwed up in the past, this helps ensure that there’s time for everything to resolve amicably.

This doesn’t mean the system has been without flaw. We currently get daily emails reporting on new signups, expired accounts, etc. It mentions all accounts that were not expired because of the managed flag.

Like most features, that was added after mistakes were made: we’d left some managed accounts unpaid for months. With better reporting, though, now, we couldn’t be happier with it.

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