Tag Archives: PHP

Mac popup notification for a PHP error

Receive a notification when PHP errors are logged on Mac

I have PHP configured to log all of its errors to a single log file. I always have Terminal open and tail watching this file. However, sometimes I don’t realize that new errors have been logged right away, which is annoying. To overcome this, I thought it would be nice if I could get a popup notification each time there was an error, just like many Mac apps do. I found this thread on SO, which helped me solve my problem.

If you have Homebrew installed, all you need to do is run:

$ brew install terminal-notifier
$ brew install fswatch

Then add this function to your .bash_profile:

notify-php-logs() {
	fswatch -0 ~/zebug.log | xargs -0 -n 1 \
		terminal-notifier -title "PHP Error" \
			-message "New errors in zebug.log" \
			-group "php-errors" \
			-activate "com.apple.Terminal"
}

Then run:

$ notify-php-logs >/dev/null 2>&1 &
$ tail -f ~/zebug.log

You’ll want to replace ~/zebug.log with the path of the log file that you want to listen to, of course.

Now whenever there is a PHP error, you will get a notification, and when you click on it the Terminal app will be brought to the front so you can see the error.

PHPUnit and the WordPress file system API

If you unit test your WordPress projects with PHPUnit, sooner or later you’ll want to test some code that interacts with the filesystem. If you are interacting with the filesystem properly, you’ll be using the $wp_filesystem object.

A few months ago I found myself needing to test some code that created a file using the WordPress filesystem API. I searched for a good solution, and found the information about mocking the filesystem on the PHPUnit website. But after tinkering with vfsStream, I decided it would be easier to build a simple filesystem mocker myself than to integrate vfsStream with the WP Filesystem API. So I did.

The result is the WP Filesystem Mock.

[It] Provides a class that can be used as a mock filesystem, and also a shim for the WordPress filesystem API that uses it. This is useful in unit tests that include simple filesystem operations.

Enjoy!

Unserializing Safely

Avoid object injection with this:

	
    if ( 1 !== preg_match( '~O:\d~', $maybe_dangerous ) ) {
        // All is well, this is safe to unserialize.
    }

For security it is best if you use json_* or something else instead. But if you are working with a project built by someone else and you have no choice, this will keep you from unserializing any objects.

Creating Your Own PHPUnit @requires Annotations

PHPUnit offers a feature that lets you skip a test when certain requirements aren’t met. This can be done in two ways:

  1. You can manually check if the requirements are met, and then skip the test with $this->markTestSkipped() if they are not.
  2. In some cases, you can use the @requires annotation, and the test will be skipped automatically when the requirements aren’t met.

Using the @requires annotation is nicer, but PHPUnit only has so many options built in. Sometimes you have custom requirements that can’t really be checked reliably with any of the built-in options. An example is when you need some tests you’ve written for a WordPress plugin to run only when WordPress’s multisite feature is enabled on the test site. In my tests, I find myself needing this a lot. So I’ve been writing this over and over:

if ( ! is_multisite() ) {
     $this->markTestSkipped( 'Multisite must be enabled.' );
}

But just yesterday I realized that this was silly, and that I could easily add my own custom @requires annotation. So I did. Here is the code:

	protected function checkRequirements() {

		parent::checkRequirements();

		$annotations = $this->getAnnotations();

		foreach ( array( 'class', 'method' ) as $depth ) {

			if ( empty( $annotations[ $depth ]['requires'] ) ) {
				continue;
			}

			$requires = array_flip( $annotations[ $depth ]['requires'] );

			if ( isset( $requires['WordPress multisite'] ) && ! is_multisite() ) {
				$this->markTestSkipped( 'Multisite must be enabled.' );
			} elseif ( isset( $requires['WordPress !multisite'] ) && is_multisite() ) {
				$this->markTestSkipped( 'Multisite must not be enabled.' );
			}
		}
	}

You just need to add that method to your base test case class, and you will then be able to use @requires WordPress multisite instead of messing with markTestSkipped() all the time. For tests that should only run when multisite isn’t enabled, you can use @requires WordPress !multisite.

You could easily add more options for any other requirements your tests commonly have.

Travis CI, Composer, and PHP 5.2

Once I’ve written some PHP unit tests for my plugins, I like to make sure I put them to good use. I develop the plugins on GitHub, so with the right tools, it’s easy to set up Travis CI to run my tests. This will let me run the tests against all of the PHP versions I need too without the hassle of trying to do this locally.

The only problem is that WordPress still supports PHP 5.2, and while I want to run my tests against that version, I’m using composer to install some of my dev dependencies. And as you probably know, composer requires PHP 5.3. So I searched around the internet to see if anyone had a solution to this dilemma. I did find one project on GitHub, but it requires you to have a separate config file for PHP 5.2, and doesn’t appear to be maintained at this time.

What I was really hoping for was a way to run composer using PHP 5.3 even when the tests are running on 5.2, since all of the PHP versions are installed on the Travis test box. I couldn’t find any helpful information about switching PHP versions on Travis, but with a little research into phpenv (which Travis uses to manage the PHP environment), I was able to figure something out.

It’s actually as easy as this:

phpenv global 5.3
composer install
phpenv global "$TRAVIS_PHP_VERSION"

Just drop that into the before_install section of your .travis.yml, and you’re ready to go!