Internet Strategy Guide

tutorial

MAMP PRO, PECL, SSH2, and OSX CLI (AKA acronym madness)

by on Nov.08, 2011, under development, php, tutorial

Or madness in general. So as you may know, I've started using PHPStorm to work locally. I decided to dust off an old SSH2 wrapper I wrote and play with how PHPStorm uses PHPUnit and does refactoring. I knew that I would have to install the extension via PECL and was like, "Oh it can't be that bad to do it through MAMP PRO" and as you may have guessed, I sealed my own fate for a couple hours. One thing I can say is that, even though I use a convenient app like MAMP PRO to set up my local development environment, I'm glad my sysadmin-fu is up to snuff enough to fly without the conveniences because after this ordeal, I feel like I might as well have made my MAMP stack from scratch with all the hoops I jumped tonight. (I'm pretty sure that last sentence is also one of the worst run-on sentences ever).

The first thing you need to know is that the PECL command is located at the directory

/Applications/MAMP/bin/php/php5.3.6/bin

when I tried to run

sudo ./pecl install -a ssh2 channel://pecl.php.net/ssh2-0.11.3

from that directory, I got the error:

Notice: unserialize(): Error at offset 267 of 1133 bytes in Config.php on line 1050
PHP Notice: unserialize(): Error at offset 267 of 1133 bytes in /Applications/MAMP/bin/php/php5.3.6/lib/php/PEAR/Config.php on line 1050
ERROR: The default config file is not a valid config file or is corrupted.

I found out later that the error is most likely caused by the file

/Applications/MAMP/bin/php/php5.3.6/conf/pear.conf

So if you get an error, try doing

sudo mv /Applications/MAMP/bin/php/php5.3.6/conf/pear.conf /Applications/MAMP/bin/php/php5.3.6/conf/pear.conf.bkp

If you're still getting the error, you can also the following:

  1. Install Xcode Tools from your Mac OS X DVD or download it from Apple Developer Connection
  2. Download the complete PHP source code from php.net into /Applications/MAMP/bin/php/php5.3.6/
  3. Create an include directory in the the php5.3.6 directory.
  4. Unzip/tar the php source archive and move it to/Applications/MAMP/bin/php/php5.3.6/include/
  5. Rename the php source directory to just php (so then it will look like /Applications/MAMP/bin/php/php5.3.6/include/php)
  6. In Terminal use the following commands to compile the extension:
    cd /Applications/MAMP/bin/php/php5.3.6/include/php
    ./configure

That should allow you to run the PECL command however, you will probably get a complaint about not having libssh installed. So you will have to

  1. go download libssh2 (http://www.libssh2.org/). As much as I like git, I recommend  downloading the latest release tarball instead of cloning the repo. For some reason, I got a version incompatibility error when trying to run the PECL install with the repo version and had to do all these steps over with the tarball release version.
  2. unzip the directory and cd to the upacked directory in the terminal.
  3. run: ./configure; make all install;
    libssh should compile and place the output file in src/*.o
  4. copy all headers from the include folder within the libssh2 directory to
    /usr/local/include/
  5. copy all compiled files (*.o) from the src folder within the libssh2
    directory to /usr/local/lib/

After you've successfully ran the the PECL install, it should tell you to  Add the line

extension=ssh2.so

to the Dynamic Extensions area of your php.ini file. I believe both MAMP and MAMP PRO allow you to edit the necessary ini through File>Edit Template.

MAMP edit php.ini

 

Lastly, restart apache. You should be able to see the SSH2 extension when you load a phpinfo() page.

Bonus round:

I'm not sure how I have  PHP CLI working in OSX but if you've followed the steps above and try to verify the extension install with through the cli, it won't show up.

$ php -a
php> phpinfo();

This is because (if you're also using MAMP PRO) the binaries are different. The good news is that you can make things happy in 3 easy steps

  1. run `sudo ln -s /Applications/MAMP/bin/php/php5.3.6/lib/php/extensions/no-debug-non-zts-20090626/ssh2.so /usr/lib/php/extensions/no-debug-non-zts-20090626/ssh2.so` in the terminal.
  2.  Edit the /etc/php.ini (copy /etc/php.ini.default if /etc/php.ini doesn't exist)  like you did for the MAMP php.ini(s)
  3. profit.

Note: I still have to install PHPUnit into my current setup so that may or may not elicit another blog post.

Sources:

  • http://smbjorklund.no/how-enable-pecl-uploadprogress-extention-mamp
  • http://php.net/manual/en/ref.ssh2.php
  • http://forum.mamp.info/viewtopic.php?t=13815
Enhanced by Zemanta
View Comments more...

zend_log_exception ‘bad log priority’

by on Feb.24, 2009, under noobtip, php, web dev, zend

I'm writing this post because there are a few times I've gotten this particular exception and then look at the trace and can't figure out what's wrong. More often than not, I'll get to the line in the trace and be like, "wtf! there's no priority here. It's a method call not a constant". This turns into, let's see if something is happening before this method is called and finally comes down to looking at the Zend_Log source and remember, "oh yeah, Zend_Log allows you to use log by priority name as a method in lieu of using the log method" and what I once thought of as slick when I read the documentation turns into a waste of a few minutes and added amount of aggrevation. So to save myself and others some time and aggrevation, I'm going to go into a bit of detail as to why you may be getting this exception.

Take the following for example:

// assume taht $log is a valid instance of Zend_Log
$log->addEventItem('foo','bar');

It looks like it should work, right? It won't because the correct method call would be

$log->setEventItem('foo','bar');

As I explained in the introduction, the 'bad log priority' exception will be thrown for this sort of error. This error will occur because Zend_Log overloads the __call function so that you can do

$log->priorityName('message');
// instead of logging with the log method
$log->log('message',Zend_Log::PRIORITY_NAME);

So if you're like me and get this exception but only see a method where this error is being thrown, you now know why and hopefully be less confused and aggrevated.

I wish I could provide a solution to this issue but I see no way that Zend_Log can contextually tell if you're wanting to use the priorityName shortcut or not. This only leaves the option of removing the the priorityName shortcut entirely, which will break somebody's code. The shortcut is nice because of its flexibility but definitely a case where flexibility can increase complexity or rather, flexibility leading into complications that require complex understanding. I haven't had time to read all the arguments in the comments on the flexibility/complexity issue that Federico Cargnelutti brought up recently to have an overall opinion on the matter but in regards to Zend_Log, the flexibility should've been left out. I would've preferred that Zend kept it simple and just made log the only method of logging. Or maybe I'm an edge case that logs more information than the initial event items give me.

View Comments :, , , more...

string searching, you’re doing it wrong

by on Dec.18, 2008, under noobtip, php, tutorial, web dev

First off, I'm not trying to be a complete jack-ass, just a helpful one. This article, by Stefan Ashwell, popped up on my news feed and I wanted to comment on it but can't remember my login for the site and after 10 minutes of waiting the password reset email has yet to arrive. The non-arrival of the password process is irritating me and shows in this article title and my tone.

In the article, Stefan shows how strpos or stripos to locate a desired string or block of text.

The example he gives is as follows:

if ( stripos($sentence, 'string') ) {
   // yes it does
} else {
   // no it doesn't
}

The problem with this example is that it will yield a false positive. This is a common mistake made by a lot of people. If we examine the php manual entry further we see, "Returns the numeric position of the first occurrence of needle in the haystack string." The key word being numeric. This means if the string position is 0, then the expression ( stripos($sentence, 'string') ) will evaluate to false.

EDIT: Expanded explaination on why this can yield a false positive. If the string your searching for is at the beginning of the sentence, then the position returned is 0. When php reaches the statement if ( stripos($sentence, 'string') ) it interprets the return value (0) as false.

Here is a more expanded example:


$eval=(stripos('The quick brown fox jumped over the lazy dog','The'));

echo '($eval) : ';
echo ($eval) ? "pass\n" : "fail whale\n";
echo '($eval==0) : ';
echo ($eval==0) ? "pass\n" : "fail whale\n";
echo '($eval===false)';
echo ($eval===false) ? "pass\n" : "fail whale\n";
echo 'eval is '.$eval."\n";

/**
output is:

($eval) : fail whale
($eval==0) : pass
($eval===false)fail whale
eval is 0

*/

As you can see, if you want to properly search for a string using stripos or strpos, you must test for the boolean value of false ($eval===false). Alternately, you can use regex, if you're comfortable with it. I'm of the opinion that learning some basic regex doesn't ever hurt you.

I want to re-iterate that I wanted to leave this whole post as a comment but that doesn't seem possible right now since that email has yet to arrive and the article requires login for commenting.

View Comments :, , , , , , , , , , more...

Zend_Log quickstart

by on Dec.17, 2008, under noobtip, php, tutorial, web dev, zend

Lately, I've found that I need to create a more robust logging system for both audits and debugging. I found a great logging primer from DevShed that offers some good insight into going about making a more robust system. Other than the theory, you shouldn't really take much more away from it since, as one comment points out, the implementation is poor aka globals are bad. Caveat: my implementation probably won't be all that great either but I hope to avoid making beginner's mistakes.

That being said, the reason this particular article is centered on Zend is because I'm pretty much in love with Zend right now. The main reason for writing this article is that, while the Zend documentation on Zend_Log is thorough and easy to understand when you read it, I hate back and forth between the sections of Zend_Log to make sure I understand what I'm needing to do.

I'm assuming you have at least gone through the Zend Quickstart before reading on. For my filesystem and db configuration, I use Zend_Config to load up settings such as the logfile name and log database adapter. I could've set the path for the file but I want a certain degree of flexibility.

At this point, I have the logger configuration from zend config  and the db adapter so let's move on to some code examples. This is partially taken from my in-progress class.

making a full filepath:

$filepath=(isset($options['FilePath'])) ? $options['FilePath'] : INC_PATH."/".$this->_systemConfig->system->logfile;
$writer = new Zend_Log_Writer_Stream($filepath);

the filepath is used with the Zend_Log_Writer. Next we set a format for the writer and then instantiate Zend_Log with the writer

$formatter=new Zend_Log_Formatter_Simple($format);
// specify format
$writer->setFormatter($formatter);
$logger=new Zend_Log($writer);

Note: $format is a text string that indicates how each log entry will appear.

The important things to remember here is that Zend_Log creates an associative array with all the basic useful log information. This array can be accessed in a variety of ways. For my purposes, knowing what is accessible by the stream and database writers are important.
If you have read the documentation thoroughly, you will have found that in section 30.1.6 Zend documents this array expressly. Unfortunately, unlike some most of their other documentation, this useful bit of information is almost secreted away. I've scoured the docs a lot to find the keys created by Log so here they are as a quick reference.

  • timestamp
  • message
  • priority
  • priorityName

These little gems are pretty much the keys to the Kingdom of Zend_Log.
If you want to reference them for formatting in a stream, you can do something like:

$format = (isset($options['LogFormat'])) ? $options['LogFormat'] : '%timestamp% '
.PHP_EOL.'%priorityName% (%priority%)'
.PHP_EOL.'%message%' . PHP_EOL.PHP_EOL
.str_repeat("=",100). PHP_EOL;

or if you need to use them for your db, you can use set column mapping like so:

$columnMapping = array('lvl' => 'priority','Priority'=>'priorityName', 'msg' => 'message');
$writer = new Zend_Log_Writer_Db($db, 'log_table_name', $columnMapping);

That should cover the basics.

Pro-tip discussion: For auditing, you may want to make separate log files for access,create,and changes made to your app/system. Error logging should log everything into files, but a separate debug copy would probably out in the development environment. I usually do a tail -f on debug/log file. It seems obvious to, me that any logging/exception system you make should have a simple outside error handling function to alert you of that logging broke. I believe this can be done by setting the error handler in the constructor. Haven't played with this yet. It seems to me that any robust logging system you implement will run into a chicken vs the egg type problem

View Comments :, , , , , more...

stupid *nix tricks

by on Nov.07, 2008, under *nix, noobtip

[Edit: Seems like the -u flag is on debian systems such as Ubuntu. Did a man on a FreeBSD system and saw it didn't have the flag available.]
I use the cp and mv a lot that the -r and -f flags almost always accompany them. I also now realize I've used them for so long with so little thought that I forgot that there were other flags. My newest infatuation is the -u flag.

Basically -u lets you do a merge, which came in handy when I had to manually update wordpress for the first time. I could tell you more or you could RTFM

View Comments :, , , , , , , more...

understanding zend ini (Zend_Config_Ini)

by on Oct.21, 2008, under pdo, tutorial, zend

So I just spent the past half hour reading and sorting through documentation on Zend_Db, Zend_Config and Zend_Config_Ini so that I could set my driver options in my config file.

I could've set the options in the bootstrap but figured there had to be a way to set things up in my ini file. After all, what would the point of an ini file be if you can't set your configuration options in them?

The key to my issue ended up being Zend_Db. The bootstrap (if you followed the quickstart like i did) uses Zend_Db::factory() to set up your database connection. It does this by loading the configuration ini that you made. What the quickstart fails to mention is how to decipher your ini file. Or maybe it's some kind of Zend right of passage to figure out how to go beyond setting up your environemnt host/dbname/username/password. Or maybe I'm just incredibly dumb. I'm more prone to believing the latter.

So for the sake of anyone else like me that possesses the curiousity to know why things work the way they do but don't possess the patience to root documentation while doing a quickstart, here is a brief "wft is going on here".


Zend_Db::factory($configuration->database);

gives us a database adapter. It does this by parsing a Zend_Config object. If you're using an ini, then Zend_Config_Ini parses your ini file by replacing creating arrays by (to extremely simplify) exploding the dots (.). So

database.adapter=PDO_MySQL
database.params.host=localhost
database.params.dbname=kittens

becomes equivalent to

$database=array(
  "adapter"=>"PDO_MySQL",
  "params"=>array(
         "host"=>"localhost",
         "dbname"=>"kittens"
          )
    )

Sidenote: I found that if you have a password that contains non-alphanumeric values, it's best to encapsulate them in double-quotes. (i.e. database.params.password="kittens!") otherwise it cause Zend to hate you (short version of the outcome).
This basic understanding on how the ini file is parsed lead me to being able to do all sorts of fun stuff. In particular, was setting the driver options.
At first I thought I could do something like database.driver_options or database.driver.options to set things up. It made sense to me since the adapter is set outside of the connection parameters. What I eventually discovered was that according to Zend_Db, the params key isn't limited to the connection. It also encompasses the driver settings. So in order to set my PDO driver settings to the way I want them to be, I ended up doing:

database.params.driver_options.PDO::ATTR_PERSISTENT=true
database.params.driver_options.PDO::ATTR_ERRMODE=PDO::ERRMODE_EXCEPTION
database.params.driver_options.PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=true
database.params.driver_options.PDO::ATTR_DEFAULT_FETCH_MODE=PDO::FETCH_ASSOC

I think I'm going to have a lot of fun with my config ini in the future.

View Comments :, , , , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!