TAB (Tools Automation Build-kit) for PHP is now available for both download or pulling from git hub. I’ve seen people try to clone rake before, but it generally lacks cause well PHP lacks as a language, especially compared to Ruby. However, since PHP 5.3 is now out, there is no reason not to take advantage of namespaces and anonymous functions.
This is basically a usable prototype, hoping to get some feedback and do a real release later with documentation and tests. If you know how to use rake and the command line in general, this should not be too hard to figure out, however some basic usage examples are posted on the wiki on git hub.
The Zend Framework documentation lacks when it comes to showing the ins of out of some of its components, the Zend Framework captcha seems to fall under that category. You would think there would be a ton of useful blog posts and if there are useful posts, I don’t think google is catching them. I did find some useful code on this blog, sankhomalik’s tutorial on using the zend image captcha. It does make some decent notes, so please go read this post first (and thank him, cause so far he has the best notes on the ZF captcha thus far), but the code did not seem to work with the current version of Zend that I have which is currently version 1.7.8. The other post is using some kind of Iterator and expecting the zend namespace to have a getIterator method, for some reason this was not working for me.
Here is the modified/refactored version that creates a static wrapper Captcha class using the image captcha. To reiterate what the other blog says, Make sure you have GD enabled, make sure you have a font file, make sure you have the file paths pointing to the right place, and make sure you have the right permissions for the folders that contain the images and font file.
PHP Captcha Class
class Capatcha
{
/**
* validates the last image captcha that was created
* and put into the current session.
*
* @param string $postPrefix the prefix of the post value i.e. 'captcha[id]'
* @return boolean
*/
public static function validate($postPrefix = "captcha")
{
$captcha = $_POST[$postPrefix];
$captchaId = $captcha['id'];
$captchaInput = $captcha['input'];
$captchaSession = new Zend_Session_Namespace('Zend_Form_Captcha_' . $captchaId);
$captchaWord = $captchaSession->word;
if( $captchaWord )
return $captchaInput == $captchaWord;
return false;
}
/**
* generates the captcha image and returns the image id.
*
* @param string $postPrefix the prefix of the post value i.e. 'captcha[id]'
* @return string
*/
public static function generate($postPrefix = "captcha")
{
// replace the path/to with the correct path...
// same with /images/captcha
$captcha = new Zend_Captcha_Image(array(
'name' => $postPrefix,
'wordLen' => 6,
'timeout' => 600,
'font' => "path/to/IMPACT.TTF",
'imgdir' => "path/to/images/captcha",
'imgurl' => "/images/captcha"
));
return $captcha->generate();
}
}
PHP ZF Controller
// in your action in the controller,
// it would look like some variation of this
if($this->getRequest()->isPost())
{
if(!Capatcha::validate())
{
$id = Capatcha::generate();
$this->view->captcha = $id;
$this->view->message = "captcha was invalid";
return;
} else {
$this->view->message = "saved!";
}
}
else
{
$this->view->message ="";
$id = Capatcha::generate();
$this->view->captcha = $id;
}
XHTML View
<!-- above your form using with short tags on -->
<div class="error"><?= $this->message ?></div>
<!-- somewhere in your form -->
<img src="/images/captcha/<?= $this->captcha ?>.png" alt="captcha" />
<input type="text" name="captcha[input]" value="" />
<input type="hidden" name="captcha[id]" value="<?= $this->captcha ?>" />
If you are not familiar with type/value boxing using objects, head over to wikipedia’s object_type article to grasp the concept. While languages such as Java and C# support this natively, PHP does not. However it can be accomplished, to some degree in PHP, just not eloquently as the language itself does not have constructs to support it. Having box types in PHP could help with chaining, keeping everything object oriented and allows for type hinting in method signatures. The downside is overhead and the fact that you now have extra checking to do using the “instanceof†construct. Having a type system is also a plus when using development tools that have intellisense or code assist like PDT. Rather than having to google/bing/yahoo for the method, it exists on the object, and you can use the tool to provide a drop down.
Boxing and Unboxing with Midori PHP
In Midori PHP I’ve add box types for native values in PHP. Granted not all the types are there yet, as i’m slowly porting them in, writing documentation, writing tests, and refactoring what currently exists from the prototype. The key classes to look at would be the Midori_Object, Midori_Nullable, and Midori_String. The Midori_Nullable class currently abstracts a nullable value into a class which is built on the Midori_Object and is the parent of Midori_String. So using these box classes might look like the follow:
PHP
// boxing example
$str = new Midori_String("my cool new value"); // value is now boxed
$str2 = $str->replace("value", "test");
// unboxing
$unboxedStr = $str2->value; // unboxed value
echo $unboxedStr; // my cool new test
echo $str // my cool new value
echo $str2 // my cool new test
Midori_String uses the magic method __toString to allow echo to called on the object and the Midori_String will even allow for dot concatination since it has __toString. The “value” property is the actual value inside of the Midori_String box object to which it wraps. The Midori_String also returns the new value and does not affect the original value, during each method call, so that actual object acts just like a value type.
Understanding Chaining Methods after Instantiation
Another problem in PHP is that when you instantiate an object, it does not allow for chaining right away, which can be bothersome.
PHP
// incorrect way to chain in PHP
$str = new Midori_String("don't objectify me, sidekick")->concat("!"); // epoch fail
// correct way to chain
$str = new Midori_String("don't objectify me, sidekick");
echo $str->concat("!"); // don't objectify me, sidekick!
So in hopes of getting around that and to use common box types often: I propose creating and using functions “box_x” to wrap the instantiation of a box type and to allow for chaining. I also thinking having an “unbox” function to allow for unboxing of values if the object is an instance of Midori_Nullable, would also be handy.
PHP
// boxing example with forth coming helper methods
// these methods are prototypes and would like feed back.
$str = box_str("my cool new value")
->replace("value", "test") //chain 1, replacing a value
->toUpper() // chain 2, uppercasing.
->value; // chain 3, returning the unboxed value
echo $str; // MY COOL NEW TEST
$str = box_str("my cool new value!")->trimEnd("!");
$unboxed = unbox($str);
echo $unboxed; // my cool new value!
PHP does not allow for operator operations on objects
// example of what you have to do to add two box objects in PHP
$grade = new Midori_Int32(90);
$grade2 = new Midori_Int32(60);
// correct way to add 2 boxed objects in PHP using Midori
$sum = unbox($grade) + unbox(grade2);
$sum = $grade->value + $grad2->value;
echo $sum; // 150
// incorrect way, though it would be nice if PHP could support it
$sum = $grade + $grade;
As most web developers know there is a difference between HTTP GET and HTTP POST and sometimes you end up using a combination of these items and take precedence depending on what are you are trying to accomplish. In the Zend Framework, when working with controllers there is a Zend_Controller_Request_Http object used in conjunction with controllers. The object has useful methods like determining what kind of HTTP Request it is (isPost, isXmlHttpRequest, isGet, etc), getting various request variables (_getParam, getParams, getPost,etc).
While working on a search page for a client, I came across a need to get POST values which could sometimes also be in the query string already, but needed the HTTP POST variables to take precedence in being loaded. When using $this->_request->_getParam() inside of the controller, the HTTP GET values were taking precedence. The reason why: there is no $this->_request->getGet() method on the request object, HTTP GET data must be acquired through $this->_request->_getParam() or by calling for the property (which invokes the magic method __get on the request object). The _getParam() method always checks GET data first. However there is a $this->_request->getPost() method which can be used to retrieved the post values.
PHP
// in the controller action method....
// too long to use a ternary.
// TIP:
// technically $this->_request->search should be the same as
// $this->_request->getPost('search');
if($this->_request->isPost())
$params = $this->_request->getPost('search'); // HTTP POST
else
$params = $this->_getParam("search", array()); // HTTP GET
// there is no $this->getGet('search')
While working with the Zend Framework and partial loops, I ran into a few issues. One was not getting the data to load, which was easily solved after looking at partials documentation. Make sure you set the object key in the controller for the partial loop. The other issue of trying to pass local variables into the partial loop took time to see there was really no current answer without extending or creating a new helper, or the evil global.
PHP
// in the action method
global $otherVariable;
$otherVariable = "should be the same through each iteration";
$this->view->partialLoop()->setObjectKey('model');
$this->view->paginator = Zend_Paginator::factory($array); //etc
// in the view
<?= $this->partialLoop('path/to/_partial.phtml', $this->paginator) ?>
// in the _partial.phtml
<?php
$model = $this->model
global $otherVariable; // just seems so hackish to have to do this.
?>
I have already added a task to Midori PHP to extend the Partial Loop Helper to overcome the lack of the ability to pass in local variables to the partial loop.
disclaimer: this is not to start a flame war but for me to rant on things that have cost me time out of my life but should not have.
PHP die hard fans galore and actual reputable programmers that use PHP press forward for how great a tool it is to build websites and that it is enterprise ready. While it is a moderately decent tool that does have it’s uses, I might argue that enterprise point one day once I get my house in order. Which is hard to do cause I lack time, because PHP and some technologies just suck my time. Vicious Cycle.
Even though method names slightly vary, today, its easier to be navigate and productively use 5 or 6 programing languages through common conventions and consistencies through those languages. Even more so with frameworks that pushes these common consistencies, it adds to that performance boost of just getting things done. However, while working on a PHP framework to help overcome its continual IE6 like blight on the web, I constantly run into little things that just make me writhe in mental anguish.
PHP has no common object types, though it looks like a pecl extension is working on this issue with SPL Types which sadly isn’t bundled inside of PHP5.3. PHP has a ton of functions to manipulate its values, str_x functions, array_x functions, etc. On top of that, those functions were aimed at low barrier to entry and suffer from the “I’m going to be so clever with this” design syndrom that it not only trains new programmers learning PHP to learn bad concepts. Its also hard to remember and guess functionality since quite a few of these functions deviate from common practice, thus leaving not so easy to remember caveats that makes it harder for developers to switch languages.
To demonstrate this issue, I bring up the almighty “indexOf” method that is typically found on a String object/class. “IndexOf” is known to take a string or char and search a string for the index of the specified value. It returns the index position of this search or a -1 if the value is not found…. ahh but not so in PHP. Even Javascript has a string class with an indexOf method that returns a -1, but not PHP, it has a strpos function that returns false instead of -1 inside of a language that has dynamic typing. <sarcasm>GENIUS</sarcasm>
This presents a problem for doing conditional statements because “false” equates to “0″ with dynamic typing. When using strpos or indexOf, any return value over -1, including 0, means that search found something.
So if you incorrectly check for false, which can also mean 0 in php, you can see where this would cause bugs in your software. Developers who do more than one language might easily overlook this.
c#
var index = "Don't objectify me, sidekick.".IndexOf("test"); // -1
if(index > -1)
Console.WriteLine("I've been objectified");
ruby
index = "Don't objectify me, sidekick.".index('test') // -1
if !!index # testing for null well nil is better than false
puts "I've been objectified"
Javascript
var index = "Don't objectify me, sidekick.".indexOf('test');
if(index > -1)
console.log("I've been objectified");
php
$index = strpos("Don't objectify me, sidekick.", 'test'); //false or equates to 0
if($index !== false) // um ick totally not easy to remember.
echo " I've been objectified ";
if($index != false)
echo " The index has to be 1, if the index is 0... epoch fail ";
if(index > -1) // could run the risk of being casted as a 0, if strpos returns false
echo " oops now i'm all buggy, cause i ducktyped false into 0 ";
There are other functions that do this same kind of scenario in PHP returning an unexpected value than what other languages are doing in some consistent fashion across the board. This kind of thing makes the barrier a little higher for programmers that do various languages, increases the room for bugs to be introduced and even increases the barrier to entry for hard core PHP programmers into other languages.
For those of you who read the f* manual and see that section called object-comparison. You already realize that its a misnomer or you might be oblivious to another reason why objects in PHP are still second, even third class citizens.
I think its sad that PHP 5.3 is currently at RC2 as I write this post and the only thing you can really check with object is equality using ==. You can not use operators like greater than (>), less than(<), etc on objects in PHP. The code below will illustrate php’s lack of true object comparison. Though I won’t say this takes away from the whole notion that PHP is enterprise ready, it does take away from the ease of use of objects in PHP and thus could take away from its maintainability.
class Midori_Int32
{
public $value = 0;
public function __construct($value = 0)
{
$this->$value = $value;
}
}
$a = new Midori_Int32(45);
$b = new Midori_Int32(10);
//this would be legal, for shallow checking use ==, use === for deep comparisons
$condition = ($a== $b)
// this is illegal in php
$condition2 = ($a >= $b);
In Ruby (where everything is an object) they allow for operator overloading on method so you can define custom object types with comparability.
class MidoriInt32
def initialize(value)
@value = value
end
def === (obj)
return @value === obj
end
def > (obj)
return @value > obj
end
end
a = MidoriInt32.new(3)
b = MidoriInt32.new(4)
condition = (a === b)
condition = (a > b)
though it may be unknown, you can do the same in dot .net using IComparable. If you need to override things like math operators or type conversion you need to check out the wicked cool operator keyword
using System;
public class MidoriInt32 : IComparable
{
public MidoriInt32(int value)
{
this.Value = value;
}
public int Value { get; set; }
public static MidoriInt32 operator +(MidoriInt32 objA, int objB)
{
return new MidoriInt32(objA.Value + objB);
}
public static MidoriInt32 operator +(MidoriInt32 objA, MidoriInt32 objB)
{
return new MidoriInt32(objA.Value + objB.Value);
}
public int CompareTo(object obj) {
{
if(obj is int)
return this.Value.CompareTo(obj);
else
throw new ArgumentException("Object is not an integer");
}
}
// test
class TestStuff
{
public void Test()
{
var a = new MidoriInt32(3);
var b = new MidoriInt32(4);
var condition = (a > b);
var condition2 = (a === b);
}
}
Midori-PHP is the PHP version of the Midori Generative Framework.  Its aim at providing building blocks and springboarding into creating an application. Â
Midori-Php was created in order to be used with the Zend Framework initially to bring in some rails like concepts as well as help generate the data layer with a type system. Â PHPÂ unfortunately is not a pure object oriented language and lacks core classes similar to what ruby and many other popular languages have to day. Â On top of that problem what types PHP’s SPL does provide is surely lacking in both power and simple api, instead conforming to keep the terrible naming convention of its functions. Â Â