Posts tagged with “”

Install memcached on OSX via MacPorts

Evidently I’ve become too accustomed to MacPorts installs being just a little too easy to get working. With virtually every install I’ve done, it’s as simple as typing port install port-name (plus variants as desired). Today it wasn’t and took me far longer than it should have to track down the problem.

Having exactly zero experience with memcached, I set out to get it installed for use as a lightning quick quasi-message repository. I was a little surprised at how few instructions I found for installing the necessary components on OS X via MacPorts, but I managed to cobble together what I needed from various Linux instructions and configuration bits. I will now share the fruits of my labor with you:

 # Install the executable
 $ sudo port install memcached

# Install the bindings for PHP5 $ sudo port install php5-memcached # Verify that the executable exists in your path $ which memcached /opt/local/bin/memcached # Configure memcached to execute on startup, if desired sudo launchctl load -w /Library/LaunchDaemons/org.macports.memcached.plist # Start memcached for the current session memcached -d -m 24 -p 11211

That’s the “easy” part that I managed to get through pretty quickly. Unfortunately, it didn’t work. I wrote a simple, stupid PHP script to test and got a messaged that Class ‘Memcache’ not found. It seems that MacPorts installs all of the necessary files and even creates an Ubuntu-like, separate ini file that is included by php.ini to load the memcached extension. That file, appropriately named memcached.ini, loads the memcached extension:

extension=memcached.so

This is exactly the way I’d seen it written in each of the tutorials I’d found online, so I spent some time investigating other possibilities before I came back to it.

The problem, as it turns out, is that MacPorts doesn’t install the shared object file in its extensions/ directory. Instead, it stores it in a cryptically named subdirectory.

To get memcached fully operational I suppose you could move/copy the shared object to /opt/local/lib/php/extensions/, but I chose to edit the memcached.ini file to include the full path to the shared object:

extension=/opt/local/lib/php/extensions/no-debug-non-zts-20060613/memcached.so

I should add that I did try creating a symlink, but that didn’t work for me. Rather than spend any time figuring out whether it was a me problem, I decided to take the path of least resistance and just identify the fully qualified file path.

Restart Apache and your simple, stupid test script should work without error. For whatever it’s worth, here’s my simple, stupid script:

$memcached = new Memcached();
 $memcached->addServer( ‘localhost’, 11211 );

echo “

Memcached version:

“; new PHPDump( $memcached->getVersion() ); exit;

I’m using the php52 package (5.2.13), but I didn’t see anything to indicate that this wouldn’t work with 5.3 as well.

CakePHP: Watch Out for the compact() Function

Okay, so maybe this caveat isn’t specific to CakePHP since the function is a native PHP function, but I just spent the past hour trying to figure out why variables that I clearly set in my controller weren’t available to my view. I’ll never get that hour back, but maybe I can keep someone else from losing it. As far as I’ve been able to tell, this particular behavior isn’t documented, but I haven’t done any kind of exhaustive search.

The compact() function exists as a shorthand function to create an array of variables. The PHP documentation does a nice job of detailing the function and providing a few simple examples, so I won’t belabor that point. Within CakePHP, it’s a handy shortcut for passing variables from a controller to a view. In my case, I have a vendor application form with a few variances that I need to manage. Without using compact(), a snippet from the action method of my VendorsController would look like this:

public function index() {
   …
   $vendor_type      = ‘Food’;
   $application_type = ‘Commercial’;
   $states           = $this->Vendor->Address->State->find ( 
      ‘list’, 
      array ( ‘order’ => ‘State.title’ ) 
   );

$this->set ( ‘vendor_type’, $vendor_type ); $this->set ( ‘application_type’, $application_type ); $this->set ( ‘states’, $states ); … }

That’s not an intolerably verbose example, but it’s easy to see how it could become so. Being the laconic kind of guy that I am, though, I decided to use the compact() function to cut down on the verbiage. Now my action code looks like this:

public function index() {
   …
   $vendor_type      = ‘Food’;
   $application_type = ‘Commercial’;
   $states           = $this->Vendor->Address->State->find ( 
      ‘list’, 
      array ( ‘order’ => ‘State.title’ ) 
   );

$this->set ( compact ( ‘vendor_type’, ‘application_type’, ‘states’ ) ); … }

That’s a little better, but there’s a caveat.

Using this example, I went to my view code and tried to access my $vendor_type variable only to get an undefined variable error. After working my way through various debugging techniques, I pulled out the big gun. In my view, I dumped the output of PHP’s get_defined_vars() function and found that my $vendor_type variable had been renamed to $vendorType. I don’t know if the change was made by CakePHP or by PHP itself, but I didn’t expect it (nor do I have any reason to believe that I should have expected it) and the difference is as fatal to an application as it is obvious.

Install "Non-Stable" PEAR Packages

Today I needed to install two PEAR packages on my machine. When I did, I got this:

me@mine [~] $ sudo pear install ole
Failed to download pear/ole within preferred state "stable", latest release is version 1.0.0RC1, stability "beta", use "channel://pear.php.net/ole-1.0.0RC1" to install
Cannot initialize 'channel://pear.php.net/ole', invalid or missing package file
Package "channel://pear.php.net/ole" is not valid
install failed

I’d seen this message before, but never at a time or place where it was important for me to dig in and figure out a way around it. Today I needed to do just that and I found that there are two ways.

Install This Beta Package, This One Time

To do this, simply follow the instructions in the error message:

$ sudo pear install channel://pear.php.net/ole-1.0.0RC1

By explicitly defining the channel from which to install the unstable package, PEAR seems to assume that you know exactly what you’re doing and leaves you alone to do it.

Allow Non-Stable Packages Without Complaining

The ability to “tinker” with libraries is somewhat inherent to a development environment so this is the direction I chose to go. I learned that PEAR recognizes the following application states (though I’m not sure exactly how each is defined):

  1. stable
  2. beta
  3. alpha
  4. devel
  5. snapshot

This information can be shown by running the pear executable’s config-help command:

$ pear config-help preferred_state

I decided to lower my standards gradually in order to protect some level of stability while still getting the functionality I needed. I opted to lower my preferred_state to beta.

$ pear config-set preferred_state beta

Now I can install beta packages normally (i.e. I no longer have to specify a channel) without all of the whining. PEAR doesn’t make this information as easy to find as I’d have liked, so maybe this will help someone else.

PHP Sucks, But It Doesn't Matter

Well said and well evidenced:

PHP isn’t so much a language as a random collection of arbitrary stuff, a virtual explosion at the keyword and function factory.

I develop a lot of stuff with PHP these days, but I tend to agree that the language design is a massive suckfest. It’s the inconsistencies that drive me mad some days.