Archive for the ‘PHP’ Category.

Customizing Codeception Database Cleanup

Recently, I was looking into ways to speed up the runtime of the test suite at Blopboard. We use the Codeception framework to write functional tests for our REST API, part of which entails putting the database into a known state using Codeception’s Db module. The behavior of this module is similar to that of the PHPUnit Database extension with one exception: where PHPUnit only truncates tables and leaves their schemas intact, Codeception removes the database structure and expects the SQL dump it uses to recreate it between tests.

I must admit to not understanding this design decision of Codeception, nor attempts to clarify it. Be that as it may, I had a hunch that subverting it might lead to a faster runtime for our test suite, so I set about trying to find a solution to facilitate that. I found one, and while it’s a bit hacky, it works.

<?php

namespace Codeception\Module;

/**
 * Extends the standard Db helper to override cleanup behavior so that tables
 * are truncated rather than dropped and recreated between tests.
 */
class DbHelper extends \Codeception\Module\Db
{
	protected function cleanup()
	{
		$dbh = $this->driver->getDbh();
		if (! $dbh) {
			throw new ModuleConfigException(
				__CLASS__,
				"No connection to database. Remove this module from config if you don't need database repopulation"
			);
		}

		try {
			if (! count($this->sql)) {
				return;
			}

			/** Start **/
			$dbh->exec('SET FOREIGN_KEY_CHECKS=0;');
			$res = $dbh->query("SHOW FULL TABLES WHERE TABLE_TYPE LIKE '%TABLE';")->fetchAll();
			foreach ($res as $row) {
				$dbh->exec('TRUNCATE TABLE `' . $row[0] . '`');
			}
			$dbh->exec('SET FOREIGN_KEY_CHECKS=1;');
			/** End **/

		} catch (\Exception $e) {
			throw new ModuleException(__CLASS__, $e->getMessage());
		}
	}
}

The above module class is used in place of the Db module. To come up with it, I started by digging into the logic of the Db module class itself. Codeception has several hook methods for modules that it calls internally. One of these is _initialize(), which is called after the module class is instantiated and configuration for it is loaded but before any tests are run.

Looking at the _initialize() implementation in the Db module class, I found that it makes a call to a method to obtain a driver object for the particular database in use. This driver object implements a cleanup() method that the Db module class’s own cleanup() method calls between tests to handle resetting the database state.

There’s a problem here, though: the call to obtain the driver object is to a static method, which means there’s no way for me to specify my own logic for how to obtain a driver object rather than the logic that Codeception uses by default. This inhibits extensibility as well as testability.

I could have gotten around this by extending the Db module class and overriding its _initialize() method to call out to different code to obtain an instance of my own driver class. However, that would have meant duplicating most of the logic of that method, which is not of a trivial size. This would raise the likelihood that my code would not work with subsequent versions of Codeception if the method I was overriding changed.

In the end, the alternative I found was to instead extend the Db module class and override its cleanup() method. While this still results in duplication of code, the code being duplicated (which is demarcated by /** Start **/ and /** End **/ comments in the above code sample) is shorter, simpler, and less likely to be changed such that it impacts my code’s functionality. It is worth noting, however, that the above code sample will likely only work with MySQL, and would need modifications to work with other database servers.

Had the Db module class encapsulated its call to Driver::create() within an instance method, I could have simply overridden that method in my subclass and had a cleaner solution.

Alternatively, Codeception could have supported a solution like this:

<?php

namespace Codeception\Module\Db;

interface DriverFactoryInterface
{
  public function create($dsn, $user, $password);

  // ...
}

class DriverFactory implements DriverFactoryInterface
{
  public function create($dsn, $user, $password)
  {
    // The contents of Driver::create() would go here.
  }
}

namespace Codeception\Module;

class Db extends \Codeception\Module
{
  protected $driverFactory;
  protected $driver;

  public function _initialize()
  {
    // ...
    if (!isset($this->config['driverFactoryClass'])) {
      $this->config['driverFactoryClass'] = '\Codeception\Module\Db\DriverFactory';
    }
    $this->driver = $this->getDriverFactory()->create(
      $this->config['dsn'],
      $this->config['user'],
      $this->config['password']
    );
    // ...
  }

  public function getDriverFactory()
  {
    if (!$this->driverFactory) {
      $driverFactoryClass = $this->config['driverFactoryClass'];
      $this->setDriverFactory(new $driverFactoryClass);
    }
    return $this->driverFactory;
  }

  public function setDriverFactory(DriverFactoryInterface $driverFactory)
  {
    $this->driverFactory = $driverFactory;
  }

  // ...
}

In the above solution, there is a DriverFactoryInterface interface with, among others, a create() instance method, and a DriverFactory class that implements this interface. The Db module class allows the specification of a class that implements this interface via its configuration. It then handles instantiating this class and calls that object’s create() method from its _initialize() method rather than calling Driver::create() as it presently does. With this code in place, I could write my own class implementing the interface to return my own driver. This would allow me to accomplish my goal without having to resort to subclassing.

In any case, my hunch and solution paid off: with the solution in place, we were able to cut our test suite runtime by roughly 30%. Another pleasant side effect was that I no longer needed to maintain a copy of our database schema apart from the one we already maintain using Liquibase.

I hope this solution and my thoughts on Codeception’s present design are helpful to someone. Thanks for reading.

Travis and Composer and virtPHP, oh my!

I recently ran into an issue with one of my repos on GitHub when integrating it with Travis. When I installed dependencies with Composer and ran the PHPUnit tests on my local system running Ubuntu 13.10 and its stock PHP 5.5.3 apt package, they passed. However, I’d configured Travis to also do this under current 5.3 and 5.4 versions as well.

In the first build, everything worked fine under 5.4 and 5.5, but upon getting to the composer install instruction to install project dependencies and PHPUnit, the job for 5.3 failed with some rather unintuitive output from Composer that implied it didn’t recognize the platform package requirement that I’d provided for the minimum PHP version.

Your requirements could not be resolved to an installable set of packages.
Problem 1
- The requested package php could not be found in any version, there may be a typo in the package name.

Side note: While Travis does support Composer, the version of it available by default when running a job is frequently behind the current build. I’ve brought this up with them, but it doesn’t seem they’ve addressed it as of this writing. In any case, it’s easy enough to work around by including a composer self-update instruction as part of the build like so. This ensures that you won’t be affected by any recently fixed bugs in Composer.

Since the cause of my issue wasn’t immediately obvious from Composer’s output, my first thought was that I needed to begin my attempt at troubleshooting the issue by replicating it on my local machine. My second thought was that seemed like an abysmally miserable prospect, as it would require that I have several different versions of PHP installed other than the current one on my system.

I’d heard recently about a new project recently via Twitter called virtPHP that purported to be PHP’s answer to virtualenv for Python or rvm for Ruby. Thinking that my situation seemed a great use case for it, I proceeded to install it.

First, you have to read a bit past the cursory installation instructions on the landing page of virtPHP’s web site, particularly the “Using phpenv and php-build” section of virtPHP’s README file including the portion on package requirements. virtPHP doesn’t accomplish this great feat all on its own. It actually builds on two other existing projects by Christoph Hochstrasser, phpenv and php-build, and functions (in a rather PHP-like vein) more like glue to make working with these projects and managing what they produce easier. More specifically, it provides support for things like differing per-project PHP, PECL, and PEAR configurations.

In reality, all I ended up needing for what eventually proved to be a rather quick-and-dirty sort-of use case was phpenv and php-build alone, though I suspect virtPHP will be indispensable when I inevitably need a more long-term setup like this. Installing all three based on the installation instructions in their README files was fairly straightforward. I used them to create three PHP installations of the versions used on Travis (5.3.27, 5.4.25, and 5.5.9 as of this writing) and to quickly switch between them to re-run the composer install command that had failed on Travis, which consistently failed under 5.3 and worked under 5.4 and 5.5 on my local system.

Eventually, I opened the composer.json file and realized the problem: I’d misrecalled the minimum PHP version I’d set for my project to be installed as 5.3 when I’d actually set it to 5.4. Composer appropriately, though perhaps not intuitively, reacted by outputting errors when the local environment was running 5.3, a PHP version that did not meet the requirement I’d set in composer.json. In poking around, I found that this sort of user error is not entirely uncommon. Once I changed the requirement to 5.3 and pushed it to GitHub, the next Travis build succeeded for all PHP versions I’d specified.

So, thanks to the folks behind virtPHP for producing this project. I suspect I’ll be making more use of it in the future. :)

Sunshine PHP 2014

Due to uncertainties in my work schedule, I decided this year not to submit to the Sunshine PHP 2014 conference. However, the schedule turned out such that I was able to attend the conference. Many thanks to my awesome employer Blopboard for providing the time and funding to make this possible.

I was a speaker at the inaugural Sunshine PHP conference in 2013 and enjoyed that experience, but being able to just be an attendee this year was a nice change of pace. I’ve enjoyed the awesome content presented by excellent speakers.

With this year’s Sunshine PHP came a new member of the elePHPant family: Sonny, the yellow elePHPant. The process of obtaining your very own Sonny was a rather novel idea thought up by the hosts of Sunshine PHP. Attendees were given a bingo sheet where each space was branded for a sponsor and would visit the sponsor’s booth to get that space stamped. Once all spaces were stamped, you could turn in the bingo sheet to get Sonny.

In going through this process, I spoke with some very friendly guys at AppDynamics. I was able to learn more about their product, which is an alternative to the New Relic service I currently use at work for monitoring the performance of our product. I noted that AppDynamics isn’t currently listed in the Heroku add-on marketplace, but they clarified for me that it can still be installed on Heroku and pointed out related documentation.

The interaction was great and I’ll certainly be checking out the product further, but this quest to get Sonny is what instigated that conversation, which I think is awesome. Many thanks to Zend for sponsoring this fun activity within the conference.

Thanks to everyone who made Sunshine PHP a spectacular event to attend. I hope to see you again next year.

Sonny the yellow elePHPant

 

The OOP in PHP Slides Posted

I’ve posted the slides from my “The OOP in PHP” session that I presented at Lone Star PHP 2013. You can find them in the Publications section of this site.

Why I Love the PHP Community

I had my first contact with the PHP community in late 2005 or early 2006; I can’t remember exactly when it was. Before that point, I’d spent the better part of my life struggling with being bullied and depressed and to some degree still do. If my peers didn’t show me ostracism, they mostly showed me indifference. I often felt like my life had little meaning and that I had no one I could relate to.

Then I found the #phpc channel on the Freenode IRC network. I had the honor and privilege of meeting too many individuals to list here. They didn’t belittle me with ego, much as I might have put some of them on pedestals and perhaps still do. They didn’t admonish me for my lack of knowledge or experience at the time. They didn’t laugh or insult me when I asked questions and showed desire to learn like one might expect in other communities.

They welcomed me. They befriended me. They supported me in my endeavors to become better, as a professional and as a person. They made me feel liked, accepted, and respected. They made me feel like a part of something greater, a community, a family of friends. If everyone could have this, I believe the world would be a much better place.

That’s why I’m so sad when I see public displays that I think might prevent people within that community from sharing my feelings or discourage them from taking part in it. I know what it’s like to feel excluded, marginalized, demoralized, degraded, and discouraged. I don’t wish that on anyone, least of all people I know and respect within this community. I feel that people shouldn’t be singled out or made to feel inferior or objectified. Gender, gender identity, race, creed, ethnicity, sexual orientation — no one should be made to feel like this based on those attributes.

I’m a very sympathetic and empathetic person. I feel things very deeply. I try to consider carefully who I might hurt when I say or do something. I may not always succeed, but I try anyway. In any situation, I do my best to understand where other people are coming from and what their position is. I don’t do this for its own sake, but because I know what it’s like to be hurt and I don’t want to inflict that on another human being. And I especially don’t want it inflicted on others in my beloved community either. And I’m not the only one.

PHP as a language irks me sometimes. Heck,  a coworker of mine started phpsadness.com and it’s difficult to disagree with him on many of the problems that the language has. They don’t stop me from using it, though. I may have come for the technology 11 years ago, but I stayed for the community. And hopefully now, after reading this post, you understand why.

Speaking at SunshinePHP

Just a quick post to announce that I’m speaking on “Database Testing for Fun and Profit” at the SunshinePHP Conference being held in Miami, Florida on February 8-9. Hope to see you there!

I am speaking at SunshinePHP. February 8th - 9th, 2013 | Miami, Florida

7php Interview

This post is a bit belated, but 7php interviewed me last month about how I got started with PHP, my work on the PHP Master book, the Phergie project, my advice to beginning PHP developers, and other assorted topics. Feel free to give it a look.

WordPress SyntaxHighlighter font size fix

I use WordPress for this web site. To pretty up source code examples in my posts, I use the excellent SyntaxHighlighter Evolved WordPress plugin. The WordPress theme I use, Fluid Blue, does something with its CSS such that it and SyntaxHighlighter appear to conflict. The result is that source code examples processed by the plugin are displayed with a font size that’s too small to read comfortably.

In doing some digging, I learned about the child themes feature of WordPress, which allows you to effectively extend an existing theme. I created a directory under wp-content/themes called fluid-blue-custom. In this directory, I created a styles.css file with these contents:

/*
Theme Name: Fluid Blue (Custom)
Template: fluid-blue
*/

@import url("../fluid-blue/style.css");

body .syntaxhighlighter code, body .syntaxhighlighter .gutter { font-size: 12px !important; }

The Template line of the comment block indicates that this theme is a child theme of the existing Fluid Blue theme that resides in the wp-content/themes/fluid-blue directory. The @import line pulls in the styles.css file from that directory, after which I can apply any CSS overrides I like. The last line is a CSS rule specific enough to override applicable rules from the parent theme in order to increase the font size to something more easily readable.

It appears I’m not the only one who’s encountered this issue, so I hope this post helps someone else.

Setting up EC2 for Drupal with Puppet

I’m currently working on a project that involves running Drupal on Amazon EC2. To save time in setting up future new VM instances, I decided to take the opportunity to learn puppet. For the time being, I’m using a single VM to run the full LAMP stack and running puppet without a server by copying my puppet manifest to the VM and using puppet’s apply command to apply it locally. However, this manifest can easily be adapted for a multi-VM environment. After some tinkering, I came up with the code below.

class web {
    package { 'httpd':
        ensure => 'present',
    }

    package { 'php':
        ensure => 'present',
    }

    # Update this to use your respective time zone value
    exec { 'php_config':
        command => '/bin/sed -i "s/^;date.timezone =/date.timezone = \'America\/Chicago\'/g" /etc/php.ini',
        require => Package['php'],
    }

    service { 'httpd':
        ensure => 'running',
        enable => true,
        hasrestart => true,
        hasstatus => true,
        subscribe => Package['httpd', 'php'],
    }

    # Drupal requirements
    package { ['php-pdo', 'php-mysql', 'php-xml', 'php-gd', 'php-mbstring']:
        ensure => 'present',
        require => Package['php'],
    }
}

class mysql {
    package { 'mysql-server':
        ensure => 'present',
    }

    service { 'mysqld':
        ensure => 'running',
        enable => true,
        hasrestart => true,
        hasstatus => true,
        subscribe => Package['mysql-server'],
    }

    # Equivalent to /usr/bin/mysql_secure_installation without providing or setting a password
    exec { 'mysql_secure_installation':
        command => '/usr/bin/mysql -uroot -e "DELETE FROM mysql.user WHERE User=\'\'; DELETE FROM mysql.user WHERE User=\'root\' AND Host NOT IN (\'localhost\', \'127.0.0.1\', \'::1\'); DROP DATABASE IF EXISTS test; FLUSH PRIVILEGES;" mysql',
        require => Service['mysqld'],
    }
}

class {'web': }
class {'mysql': }

With this code saved to a file called manifest.pp (.pp being the file extension for puppet manifests), I can spin up a VM and do the following to set it up:

scp -i key.pem manifest.pp ec2-user@host:~/
ssh -i key.pem ec2-user@host
sudo yum upgrade -y
sudo yum install -y puppet
sudo puppet apply manifest.pp
rm -f manifest.pp
exit

At this point, I have a basic Apache/MySQL/PHP configuration capable of receiving a Drupal 7 installation.

Top 10 Posts of 2011

Following in the trail blazed by the likes of Cal Evans and Chris Cornutt, I decided to post a list of the posts on this blog that have received the most traffic this year along with some related commentary. However, in the spirit of Charles St. Michael, I decided to up the number of posts from three to 10. So, here we go:

10. Building PHP-GTK with Cairo Support on Ubuntu Jaunty – 2009-04-25

Very interesting that this post was in the running at all. It’s over two years old, goes back five Ubuntu versions, and deals with PHP 5.3.0RC1 (current is 5.4.0RC4) and PHP-GTK when Cairo support was relatively new. (There’s now a separate PECL extension for it now.) If you want to learn more about this, you should definitely check out Elizabeth Smith and Michael Maclean.

9. Renaming a DOMNode in PHP – 2010-02-09

It seems this isn’t as uncommon a problem as I would have thought. Sadly, in the 22 months that have passed since I authored the post, it seems the DOM extension hasn’t been updated further to support the DOM 3.0 standard or the renameNode() method mentioned in this post.

8. PHP_CodeSniffer Article in php|architect – 2011-04-28

It’s nice to see this post get attention even if was just a brief hand-waving to point people to the article, which is one of two I wrote for php|architect Magazine this year. It’s also nice to see that despite being seen by some as a more menial facet of quality assurance, other people consider it important enough to read the article and take something away from it.

7. ‘New SPL Features in PHP 5.3′ Hits php|architect – 2011-02-01

Another post that was just hand-waving to an article that dealt with a topic I saw as underrated. The article followed my php|tek 2010 session and preceded a Zend webinar this year on the same topic.

6. Process Isolation in PHPUnit – 2010-08-19

Between views and comments, it seems I wasn’t the only one who ran into this head-scratcher. However, if memory serves, I think there are plans to remove this feature from PHPUnit in future versions.

5. Node.js: A Beginner’s Perspective – 2010-10-19

The post is about a year old now, and sadly I haven’t done anything of merit with Node.js since (though I hope to change that), but it seems the community is still as vibrant and growing as it ever was. Heck, you can even integrate PHP-FPM with Node via FCGI now. Node is definitely a technology to continue keeping your eye on if you don’t already use it.

4. PHPUnit and Xdebug on Ubuntu Karmic – 2010-01-03

It’s surprising that this post is still relevant since there have been four Ubuntu releases since the version that this post deals with. I’ve since moved over to Fedora 16, at least for now, and it seems to address most of my regular needs. I may look at other distributions like Mint later on.

3. Models in Zend Framework – 2010-03-26

Even though it’s over a year old now, I think this post gets the traffic it does because there’s not really one prescribed way to build models and because the existing documentation describes a number of components that can be used to build models, but doesn’t really offer specific guidance on how to approach it. Bit of a double-edged sword, I suppose.

2. New SPL Features in PHP 5.3 – 2010-05-20

I published this post on the same day that I gave my session on the topic at php|tek 2010. It’s one of my longer and more content-rich posts and I’ve updated it on occasion as I’ve had cause to update the benchmarks that go along with it. Good to see that interest in SPL seems to be rising.

1. Database Testing with PHPUnit and MySQL – 2010-01-04

While I love that this post is driving as much traffic to my blog as it is, I do want to get around to contributing related documentation to the PHPUnit project. Hopefully that will happen soon. In the meantime, you can also read more about this topic in the Testing chapter of my most recent book.

So, one big take-away from this post has been that most of my high-traffic posts were written last year rather than this year. I can’t say it’s very surprising since, looking back, a number of my posts from this year were of the hand-waving variety. I’m hoping to publish more content-rich posts more frequently in 2012. I won’t call it a resolution, because I’d likely be jinxing myself in the process, but I will say that I’ll make my best attempt.

Best wishes to everyone in the new year.