Skip to content

Signaling PHP

Dear Reader,

PrintI’ve just finished my 3rd book – and my first mini-book – and wanted to tell you about it.

“Signaling PHP” is about using PCNTL signals like SIGINT in PHP command line scripts.

Most of the PHP I write these days is CLI scripts. I really wanted to be able to trap signals in some of my scripts. I struggled with this for a while; I even spent an entire weekend googling and reading only to find out that most of the information out there was either wrong, confusing, or incomplete. I decided that once I figured it out, I was going to put everything I learned together in one place to help others that were struggling with this topic as well.

So it is that I present to you “Signaling PHP”. The book is approximately 30 pages long, and is available in PDF, Kindle, and mobi formats.

You can get your copy by visiting http://signalingphp.com.

Until next time,
I <3 |<
=C=

Managing the Verbosity of symfony’s Command Object With a Trait

Dear Reader,

Update:
I was wrong and Kris Wallsmith called me on it. When installing the Command component, composer did NOT pull in any other symfony packages, or any other packages at all. I started this project with Silex and I believe that had pulled in a lot of stuff. To Composer’s credit. when I went in and removed Silex and put in the symfony component, it removed all the Silex dependancies and then dropped in the symfony component. Thank you Kris!

Long Rambling Intro of No Concequence

Recently I came up with a project I needed to build. Honestly, it’s one of those “not useful to anyone but me” kind of projects. I decided though that while I was at it, I wanted to learn something new. Since I’ve been a die-hard Zend guy since Zend Framework was 0.2, and more recently a Silex believer, I thought I would drop down a level form Silex and dig into symfony itself.

This project is strictly a command line project. No API, no web interface, just a command and a few switches. Digging around I found Symfony\Component\Console\Command\Command so I decided to give it a try. Honestly, I really like what I saw. It was even better that I was able to use composer to install it.

The project itself was a simple pump to move data from EventBright into MailChimp. Those of you who don’t know me, I do a lot of virtual events like DayCamp4Developers and NomadPHP, so this is a real time saver for me.

The one rough edge that I had was dealing with the verbosity setting of Symfony\Component\Console\Output\OutputInterface. That is what I am going to cover in this blog post.

Verbosity

When reading the symfony Command manual page it talks about verbosity. When you actually run the ./console.sh you can see that the -v tag is supported.

cal$ ./console.sh 
Nomad PHP Maintenance Script version 0.1.0

Usage:
  [options] command [arguments]

Options:
  --help           -h Display this help message.
  --quiet          -q Do not output any message.
  --verbose        -v|vv|vvv Increase the verbosity of messages: 
                             1 for normal output, 
                             2 for more verbose output and 
                             3 for debug
  --version        -V Display this application version.
  --ansi              Force ANSI output.
  --no-ansi           Disable ANSI output.
  --no-interaction -n Do not ask any interactive question.

Available commands:
  autodelete   Handle the autodelete process
  ebdatapump   Populates MailChimp lists from EventBrite events
  help         Displays help for a command
  list         Lists commands
  listLists    Prints a formatted list of the lists for a given mailChimp 
               account.

However, you have to piece things together a bit to finally get to the the point that:

-q OutputInterface::VERBOSITY_QUIETL
No options OutputInterface::VERBOSITY_NORMAL
-v OutputInterface::VERBOSITY_VERBOSE
-vv OutputInterface::VERBOSITY_VERY_VERBOSE
-vvv OutputInterface::VERBOSITY_DEBUG

It’s not confusing or anything but it it’s not really clear from the documentation.

Once I worked out the verbosity level, everything was awesome…at least until I got into my code. Then I realized that I was writing a LOT of lines that looked like this:

if ($this->output->getVerbosity()==OutputInterface::VERBOSITY_VERBOSE) {
    $this->output->writeln("My Message Goes Here");
}

That’s not really that bad until you start writing a lot fo them. In some cases I do like very verbose output, especially when debugging.

If you are curious, it is $this->output-> because I always take the $output object and store it in $this->output so I can get to it from any method in the object.

My First Solution

It didn’t take long to figure out that my Command class needed it’s own writeln() method.

protected function writeln($message,$level=1)
{
	if (is_null($this->output)) {
		return;
	}

	if ($this->output->getVerbosity()>=$level) {
		$this->output->writeln((isset($this->testing) && 
                                        $this->testing?'TESTING - ':'') . 
                                        $message);
	}

	return;
} // protected function writeln($message,$level=1)

Now, we’ve got things a little better. First, if it can’t find the $this->output, it fails silently. Second, This is where the IF statement lives so I don’t have to wrap every writeln() in a IF. It makes for much prettier code. the method takes an optional verbosity parameter so that I can specify what level the message should be displayed at. IF the message is VERBOSITY_VERY_VERBOSE and the verbosity level is VERBOSITY_NORMAL, the method just discards it and keeps going.

Finally. All of my commands support a -t testing mode. This let’s me do a dry run and make sure everything is going to work. I want it to be very clear when I am in testing mode so I prepend “TESTING “ to each line.

At this point I know a lot of you are asking “Why not just use logging?” The easy answer to that one is “I didn’t want to.” I don’t need full-on logging, I just need to be able to print stuff out to the terminal.

The Final Solution

This all looked pretty good to me. I was feeling rather pleased with myself…until I wrote my NEXT command for this toolset. (As you can see from the output above, there are a total of 3 now, it kinda got out of hand.) I started the second Command and realized I needed the writeln() there as well. So I did what most everyone does, I copied and pasted it. (Hush, you’ve done it too.)

I quickly realized the error of my ways. In the past, I would have subclassed Symfony\Component\Console\Command\Command and added it to the child class, and used that. That didn’t feel right either. So I wrote my very first Trait in PHP, this felt right. I love the simplicity of sharing it amongst all the other Commands. I love that I don’t have to manage sub-classes of the parent class, and yet I don’t have to hack the core either. (Again, hush, you’ve done it at least as much as I have.)

So, for better or worse, I now have a trait.

namespace NomadPHP\Traits;

trait WritelineTrait {
	protected $output;

	protected function writeln($message,$level=1)
	{
		if (is_null($this->output)) {
			return;
		}

		if ($this->output->getVerbosity()>=$level) {
			$this->output->writeln((isset($this->testing) && 
                                               $this->testing?'TESTING - ':'') . 
                                               $message);
		}

		return;
	} // protected function writeln($message,$level=1)
} // trait writeline

To use I just add this line inside of my Class definition.

use FollowMe\Traits\WritelineTrait;

Inside my class gets me everything I need and I never have to worry about it again…at least for this project.

Conclusion

Until next time,
I <3 |<
=C=

How I got Zend_Tool working on Windows

Dear Reader,

I love Zend Framework. I love it so much I wrote the very first book about Zend Framework. (Note: It’s no longer the best Zend Framework book, but still, it’s a good one) I’ve written projects using it and I now find myself teaching another class on it. One of the cool things about Zend Framework is it’s cli tool, Zend_Tool. (zf) When zf works, it’s awesome. However, when it breaks, it’s a real pain in the butt. Thanks to buddies like Ralph Schindler though (the author of the tool) when it does break, I can usually get help getting it back up and running.

The latest version of zf that comes with Zend Framework 1.10.x and better is much better than previous version and it shows that Zend (well, at least Ralph) listens when people point out problems and work to solve them.

Even though it’s made great strides, setting up zf is still not seamless. To that end, here is my list of steps needed to setup zf.

My setup

I should note before I start that I am running Windows 7. This means symlinking stuff is right out and we have to resort to physically copying files around. On top of Windows 7, I’m running XAMPP. (anyone know, is that pronounced X-AMP ot ZAMP?) this means that my PHP sits in \xampp\php. I’ve added that directory to my WIndows path so I can execute php from any cmd window. With that understanding, here’s my list.

The steps

  1. Download Zend Framework and unpack it somewhere on your harddrive where you want it to live.
  2. Make sure php.exe is in your PATH and make sure you know where php.exe is.
  3. Find the bin directory in your Zend Framework directory. In it there are 2 files, zf.bat (or zf.sh for Linux) and zf.php. Copy those to the same directory php.exe is in. (Linux users, feel free to just symlink them)
  4. Your Zend Framework directory should contain a library directory, change directory into it.
  5. from the library directory, test your zf to make sure it works, zf show should give you what you need.
  6. Type zf --setup storage-directory On Windows 7, this will create a directory named .zf in c:\Users\<Your Profile Name>
  7. Type zf --setup config-file. On WIndows 7, this will create a file .zf.ini in c:\Users<Your Profile Name>
  8. Using your favorite text editor, open c:\Users\<Your Profile Name>\.zf.ini. There should only be a single line in it that contains the include_path zf will use. Add the full path to your Zend Framework directory here. It should end in “\library\”.

Test it

That’s all there is to getting it setup. (I remember the days when it took twice as long and required cursing just to get it working) To test it out, cd to any directory other than the Zend Framework directory and type zf show version That should give you the current version of the framework you have installed.

Now you are free to start using it to create projects, etc.

Small problem

There is still a problem with defining your own providers. I tried to add my twitter provider (yes, I can use zf to tweet!) and it won’t yet recognize it. I’ve brought this to Ralph’s attention and impressed upon him the importance of being to tweet from zf. I have no doubt that a solution will be forthcoming.
UPDATE
As pointed out in the comments, this has been fixed, just not documented. This page shows how to add your own providers either manually or via a command.

You can either manually add a line to your .zf.ini

basicloader.classes.0 = "My_ClassName"

or you can use zf to update itself

zf enable config.provider class-name

So now I can tweet from zf again. :)

Until next time,
I <3 |<
=C=

[Disclaimer: I use to work at Zend and still have great friends there like the lovely Nili and the walking ray of sunshine that is Andrea. That having been said, it’s been a long time since they gave me any money. So the point of this disclaimer is really just so I can mention Nili and Andrea. :) ]