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
PHP: Hypertext PreprocessorPHP 5.5.16 is released (22.8.2014, 00:00 UTC)
The PHP Development Team announces the immediate availability of PHP 5.5.16. This release fixes several bugs against PHP 5.5.15 and resolves CVE-2014-3538, CVE-2014-3587, CVE-2014-2497, CVE-2014-5120 and CVE-2014-3597. All PHP users are encouraged to upgrade to this new version.For source downloads of PHP 5.5.16, please visit our downloads page. Windows binaries can be found on windows.php.net/download/. The list of changes is recorded in the ChangeLog.
Link
Matthew Weier O'PhinneyTesting Code That Emits Output (21.8.2014, 19:30 UTC)

Here's the scenario: you have code that will emit headers and content, for instance, a front controller. How do you test this?

The answer is remarkably simple, but non-obvious: namespaces.

Prerequisites

For this approach to work, the assumptions are:

  • Your code emitting headers and output lives in a namespace other than the global namespace.

That's it. Considering that most PHP code you grab anymore does this, and most coding standards you run across will require this, it's a safe bet that you're already ready. If you're not, go refactor your code now, before continuing; you'll thank me later.

The technique

PHP introduced namespaces in PHP 5.3. Namespaces cover classes, as most of us are well aware, but they also cover constants and functions -- a fact often overlooked, as before 5.6 (releasing next week!), you cannot import them via use statements!

That does not mean they cannot be defined and used, however -- it just means that you need to manually import them, typically via a require or require_once statement. These are usually anathema in libraries, but for testing, they work just fine.

Here's an approach I took recently. I created a file that lives -- this is the important bit, so pay attention -- in the same namespace as the code emitting headers and output. This file defines several functions that live in the global (aka PHP's built-in) namespace, and an accumulator static object I can then use in my tests for assertions. Here's what it looks like:


namespace Some\Project;

abstract class Output
{
    public static $headers = array();
    public static $body;

    public static function reset()
    {
        self::$headers = array();
        self::$body = null;
    }
}

function headers_sent()
{
    return false;
}

function header($value)
{
    Output::$headers[] = $value;
}

function printf($text)
{
    Output::$body .= $text;
}

A few notes:

  • headers_sent() always returns false here, as most emitters test for a boolean true value and bail early when that occurs.
  • I used printf() here, as echo cannot be overridden due to being a PHP language construct and not an actual function. As such, if you use this technique, you will have to likely alter your emitter to call printf() instead of echo. The benefits, however, are worth it.
  • I marked Output abstract, to prevent instantiation; it should only be used statically.

I place the above file within my test suite, usually under a "TestAsset" directory adjacent to the test itself; since it contains functions, I'll name the file "Functions.php" as well. This combination typically will prevent it from being autoloaded in any way, as the test directory will often not have autoloading defined, or will be under a separate namespace.

Inside your PHPUnit test suite, then, you would do the following:


namespace SomeTest\Project;

use PHPUnit_Framework_TestCase as TestCase;
use Some\Project\FrontController;
use Some\Project\Output;                 // <-- our Output class from above
require_once __DIR__ . '/TestAsset/Functions.php'; // <-- get our functions

class FrontControllerTest extends TestCase
{
    public function setUp()
    {
        Output::reset();
        /* ... */
    }

    public function tearDown()
    {
        Output::reset();
        /* ... */
    }
}

From here, you test as normal -- but when you invoke methods that will cause headers or content to emit, you can now test to see what those contain:


public function testEmitsExpectedHeadersAndContent()
{
    /* ... */

    $this->assertContains('Content-Type: application/json', Output::$headers);
    $json = Output::$body;
    $data = json_decode($json, true);
    $this->assertArrayHasKey('foo', $data);
    $this->assertEquals('bar', $data['foo']);
}

How it works

Why does this work?

PHP performs some magic when it resolves functions. With classes, it looks for a matching class either in the current namespace, or one that was imported (and potentially aliased); if a match is not found, it stops, and raises an error. With functions, however, it looks first in the current namespace, and if it isn't found, then looks in the global namespace. This last part is key -- it means that if you redefine a function in the current namespace, it will be used in lieu of the original function defined by PHP. This also means that any code operating in the same namespace as the function -- even if defined in another file -- will use that function.

This technique just leverages this fact.

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