Archive for the ‘PHP’ Category

Strlen issue for numbers

Saturday, March 9th, 2013

There is an issue you must keep in mind when dealing with PHP numeric types.

I was trying to validate a credit card number today, in order to apply Luhn’s algorithm I needed to know the number of digits in the credit card number string.

Let me give you an example:

Credit card number: 4415121641207182

Let’s say I’m using a function.

function luhnsFunc ($ccn){
    return strlen($ccn);
}

And call it like this:

$ccn = '4415121641207182';
echo luhnsFunc($ccn);

The returned value is: 16

But see what happens when the credit card number is not declared as a string.

$ccn = 4415121641207182; //No quotes
echo luhnsFunc($ccn);

The returned value is: 19

So what’s happening here?!

I did a var dump to each case and found out something pretty interesting.

For the first case I got:

string(16) "4415410012107183"

Which is ok, but let’s see the second case.

float(4.4154100121072E+15)

So it’s storing a float on scientific notation. Why?

Take a look at this:

http://www.php.net/manual/en/language.types.integer.php

Just above the warning you’ll read the following:

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that’s 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.

The purpose of creating the function is that no matter what I pass it as an argument it will always bring the correct result. Applying the Luhn’s algorithm to a 16 char length string is very different than applying it to a 19 chars length string.

So how do I solve this?

function luhnsFunc ($ccn){
    $type = gettype($ccn);
    switch($type){
        case 'string':
            break;
        default:
            $ccn = number_format($ccn,0,'',''); //The second parameter is a zero
            break;
    }
    return strlen($ccn);
}

An finally the length is correct

Credit card Number validation

Saturday, March 9th, 2013

Credit card validations are very important when it comes to E-commerce.

Most of the time your clearing house will validate the number and return an error message if something went wrong. If your clearing house does the validation it means that the order has already been closed and if your user typed the wrong credit card number he might have to go through the whole sale process again (choose items, fill out credit the card form, perhaps fill out the wrong credit card number again).

If the user is not aware of the error, perhaps after two attempts he’ll quit trying and the sale will be lost.

Let’s think in USABILITY.

If your user realizes he’s typing the wrong credit card number from the moment he’s filling the form, he won’t have to deal with the clearing house coming back with a rejected transaction.

How do you validate a credit card number?

You’ll have to check 2 thing:

  1. Credit card number type 
  2. Luhn’s algorithm

Both of them are important to get a correct validation for you credit card number. Both will help you give great hints to your user in case he’s typing an incorrect credit card number.

Credit Card Type

Most of credit card numbers are built with 4 blocks of information:

  • MII (Major Industry Identifier)
  • IIN (Issuer Identification Number)
  • Person’s account number
  • Check digit

So basically you can start your validations from the very first typed digit and by the time your user has typed the first six digits you can clearly identify the credit card’s issuer. For more information go to:

http://en.wikipedia.org/wiki/Credit_card_numbers

You’ll see that different industries have a specific IIN assigned to them.

Luhn’s Algorithm

The Luhn’s Algorithm is used to verify that the numbers sequence is valid by doing a checksum of the credit card’s number.

The details of the algorithm can be found here:

http://en.wikipedia.org/wiki/Luhn_algorithm

The best credit card validation would check both type and check digit to be correct. This is great because perhaps the user types a CCN for a Maestro card while his card is VISA; by means of switching an image the customer may realize something is wrong.

This validations can be done both in client and server side scripts before sending data to the clearing house.

Plugins in Zend Framework

Thursday, September 1st, 2011

There is no way you haven’t noticed that the Zend Framework documentation is pure garbage, almost every example they have is useless, there is no context, lacks of more in depth case of use and the quickstart makes you wonder if you really need to use something so complex to create something so simple.

I visit the crappy documentation for a quick reference, then I search for a more detailed explanation on google and 90% of the time there will be a link to a page that clearly explains the functionality I’m searching for and even goes deeper into some subjects.

Ok, enough of my complaints, let’s get to business.

One project I worked recently used the following approach for reusable constructor methods.

It creates a base controller with most common methods and all other controllers inherit from that base controller.

This looks like a good idea. Pretty simple and functional but then I came across this page.

As you can read it encourages others to use the helpers and plugins instead of a base controller. Even though at first it sounds like the base controller approach is justifiable you’ll later realize that helpers or plugins are a better option.

In my case there is a part of the app reserved for logged users so I needed to check the permissions to see if the controller should show something or ask a user to log in.

I read Matthew’s post and decided to go along with this approach. The whole explanation is right there, nevertheless it’s missing a little bit of info regarding the plugins/helpers folder location and how to make them available for your application.

I wanted my app folder schema to be consistent so I decided I’ll have my helpers and plugins folders under the application one.

Next thing to do is make them available; I did this in the bootstrap by adding the following method:

<?php
    protected function _initAutoloader(){
        $moduleLoader = new Zend_Application_Module_Autoloader(array('namespace' => '', 'basePath' => APPLICATION_PATH));
        $moduleLoader->addResourceType('Plugin', 'plugins', 'Plugin');
        $moduleLoader->addResourceType('Helper', 'helpers', 'Helper');
        return $moduleLoader;
    }
?>

Ok, so now both paths are available so every plugin or helper class will be found under those directories.

The following step is to create a plugin and a helper.

My plugin is quite simple: if a session namespace exists it would mean my user is registered and then I would like to set a couple of view variables like the user’s email.

Please note the event I used. This took me to figure out why.

The file is called: registered.php under plugins folder as formerly stated.

<?php
class Plugin_Registered extends Zend_Controller_Plugin_Abstract{
    public static $doNotValidate = false;
    public function postDispatch(Zend_Controller_Request_Abstract $request){
        if(!self::$doNotValidate){
            if(!Zend_Session::namespaceIsset('credentials')){
                //Oops! user isn't logged in, get them somewhere else!
                $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
                $redirector->gotoUrl('/');
            }
            else{
                //Nice! Proceed but set some variables first
                $namespace = new Zend_Session_Namespace('Credentials');
                //Get the view
                $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
                if (null === $viewRenderer->view) {
                    $viewRenderer->initView();
                }
                $view = $viewRenderer->view;
                $view->email = $namespace->email;
                //Use the following line when view resource is given in application.ini (resources.view[]...)
                //Zend_Controller_Front::getInstance()->getParam('bootstrap')->getResource('view')->email = $namespace->email;
            }
        }
    }
}
?>

You’ll need to register the plugin and this is really easy.
Again get to the bootstrap. I typed the following code as pointed out by Matthew (it’s within the bootstrap).

<?php
    protected function _initPlugins(){
        $front = Zend_Controller_Front::getInstance();
        //Check if user is logged in
        $front->registerPlugin(new Plugin_Registered());
    }
?>

Now your plugin is registered.
Some static and public available pages won’t need to do this validation, so the controller body would look something like this:

<?php
class IndexController extends Zend_Controller_Action{
    public function preDispatch(){
        Plugin_Registered::$doNotValidate = true;
    }

    public function indexAction(){
        $this->view->headLink()->appendStylesheet($this->view->baseUrl('css/index.css'));
        $this->view->headScript()->appendFile($this->view->baseUrl('js/jquery.js'));
    }

    public function logoutAction(){
        Zend_Session::destroy();
        $this->_redirect('/');
    }
}
?>

The trick here is the preDispatch method. What happens is that it sets the flag before the plugin executes and so the plugin works as expected. If you need a controller to validate a user then you don’t have to set that flag.

Matthew’s post was enlightening. I’m starting to feel more comfortable with ZF now.

Helpers work pretty much the same. I’ll post it later.

Logic questions 1

Monday, August 29th, 2011

A couple of days ago I received a call from a south american country.

They are searching for web developers to work with them in some projects involving Google. They read my profile on Linkedin and decided to contact me. It was a very interesting interview due to the fact that it was focused both in evaluating my technical and logic skills.

One of the questions that were made was quite simple but I liked it:

Given a random integer ¿how would you code a function that returns the mirrored integer?

It might sound simple, but I’ve been working with PHP for years and it’s not a strong typed language so my first answer was to deal with it as a string:

<?php
function mirror($number){
    return strrev($number);
}
?>

But then the interviewer told me that I should’t treat data as a string but as a number… ok… so I started thinking and came up with this:

<?php
function mirror0($number){
    $ret = 0;
    $prev = 0;
    $go = true;
    do{
        $quotient = (int) floor($number/10);
        $rest = $number - ($quotient * 10);
        $ret = ($prev * 10) + $rest;
        $prev = $ret;
        if($quotient===0){
            $go = false;
        }
        $number = $quotient;
    }while($go);
    return $ret;
}
?>

He liked my answer but told me that perhaps I could do it simpler by using a logarithm… this stuck into my mind so after the call ended I wrote a piece of code:

<?php
function mirror1($number){
    $ret = 0;
    $quotient = floor($number/10);
    $rest = $number - ($quotient * 10);
    if($quotient == 0){
        $ret = $rest;
    }
    else{
        $ret = ($rest * (pow(10,floor(log($number,10))))) + mirror1($quotient);
    }
    return $ret;
}
?>

I wrote a small benchmark code and the difference is unnoticeable.

Anyway, I’m just posting this 3 even though there might be a lot of different ways.

Zend Framework – View – $this->url()

Thursday, August 11th, 2011

Been using ZF a lot. It hasn’t amazed me because even though it’s really powerful it’s still very complicated to achieve simple task and the official documentation is very very messy.

Anyway, I have this layout for a project with a main menu.

Each of the menu options link to a different controller, instead of hard coding the menu links I used ZF url helper so for every link I was using something like this:

$this->url(array('controller'=>'console','action'=>'index'));

Which when ran gave me the following link

/[project_folder]/public/console

This looked just fine. Later on I created a product’s catalogue and from there a link to see a product’s detail. The link was:

$this->url(array('controller'=>'catalogue','action'=>'details','pid'=>[product_id]));

Everything worked just fine so I clicked the products details link. Everything looked fine. Then I clicked one of the main menu links to get to another section of the web page and then a bug popped.

For some reason all the links where appended with the GET parameters so when I clicked on the info link it took me to

/[project_folder]/public/info/pid/[product_id]

And obviously I was getting an error because there was no ‘pid’ action for the ‘info’ controller.

I searched and read a couple of google results, give the documentation a try (it sucks) and after a while I ended up in a simple blog entry with the solution.

I only needed to change my code to this:

$this->url(array('controller'=>'console','action'=>'index'),null,true);

Now GET params are not appended to the URL’s and everything works fine 😀

Imagick – Postscript delegate failed

Wednesday, August 10th, 2011

This new project I’m working on requires me to extract an image from a PDF file and show a preview on the web page. I knew this was possible but I didn’t knew how.

After googling it for a while I ended with some interesting results that pointed me to ImageMagick. It’s a nice tool to transform/extract images from one format to another. It is supported by many languages as C, Perl, Python and PHP. Since I am coding with PHP I went for it and activated the imagick extension for PHP on my Zend Server CE.

I’m using a Mac with Lion OS X.

I found a really good blog that has a whole section for Imagick with pretty neat results here.

After reading for a while I was ready to do my first test, so I used a code similar to this one:

<?php
/* Read page 1 */
$im = new imagick( 'test.pdf[0]' );
/* Convert to png */
$im->setImageFormat( "png" );
/* Send out */
header( "Content-Type: image/png" );
echo $im;
?>

And then ran it on my browser but to my surprise it was throwing an exception:

Postscript delegate failed `test.pdf': No such file or directory

The path was fine, I tested it with a jpg and a png image and it worked so I was really confused and started to dig into the issue. After a while I ended up reading ImageMagick documentation and somewhere I read that it uses third party commands to accomplish format transformations from vector images (like the ones stored within a pdf). Lastly I went to the server error logs and found this:

sh: gs: command not found

I guessed from previous experience that this message meant the following:

sh -> execute a shell command
gs -> ghostscript command
[text] -> error message

So it meant that the server was not being able to execute the ghostscript command, ¿really?
I went to a console and typed in:

which gs

It returned the command path so I knew I had ghostscript installed so the problem should be that the server user didn’t had the path set properly.
To check if my assumption was correct I typed the following in the console:

echo $PATH

And I got the PATH env variable.
On my PHP script I added the following line:

echo getenv('PATH');

And my script displays the PATH env variable being used by my web server. The result was different and the path where the ghostscript executable was not being included.
Now I was able to solve the issue and it was really simple. It required for me to provide the correct path for my server.
Now my script look like this:

<?php
putenv('PATH=' . getenv() . ':[absolute_path_where_the_ghostscript_executable_is]');
/* Read page 1 */
$im = new imagick( 'test.pdf[0]' );
/* Convert to png */
$im->setImageFormat( "png" );
/* Send out */
header( "Content-Type: image/png" );
echo $im;
?>

And finally everything works fine.

PHP classes autoload (namespaces) in Zend Framework

Thursday, June 9th, 2011

On previous posts I created a function to dynamically load namespace classes.
Now that I’m using Zend Framework I was wondering how can I use the same namespaces in combination with Zend’s. Following the logic I only needed to register my autoload function so that everything starts working as I wish.
Having read through the documentation I was starting to think it would be very difficult but turned out to be quite simple so I’m posting my learning experience here hoping it would be useful for others.

Background

I have a bunch of namespaces being used for several applications. I have them stored in a specific folder. I use Mac OS.
Let’s suppose I have the namespaces folder located under /var so the namespaces folder path is: /var/namespaces/
Also I have a folder with several non namespaced classes on the following path: /var/classes/

I can’t change paths because several other non ZF applications use that, and I won’t be copying and pasting them into the ZF library path cause if code needs to change I have them all in just one single place.

My ZF application is stored in the following path: /Users/spiro79/web/sites/ZFapp/

ZF must work and be able to load the classes from the different namespaces.

Making it work

I will be using the same logic used in previous posts regarding the autload. Believe it or not is pretty simple.
All changes are done within the bootstrap so open it.
First of all we need to create the autoload function. I wrote this code as a Bootstrap public static function.

    /**
     * Autoload function for PHP namespaces
     * @param string $class
     */
    public static function getMoreNamespaces($class){
        $class = strtolower($class);
        if(strpos($class,'\\')!==false){
            $class = preg_replace('/\\\/',DIRECTORY_SEPARATOR,$class);
        }
        $possibilities = explode(PATH_SEPARATOR, get_include_path());
        $found = false;
        foreach($possibilities as $path){
            if(file_exists($path . DIRECTORY_SEPARATOR . $class . ".php")){
                $found = true;
                require_once $path . DIRECTORY_SEPARATOR . $class . ".php";
                break;
            }
        }
    }

What this code does is that it searches for the namespace folder within all paths set on the include path.
The autoloader will call this function to try to load the namespaces classes.
Now let’s set the namespaces and classes folders in the application.ini file, just add these lines and make them match your own path.

nmspcspth = "/var/namespaces"
clssspth = "/var/classes"

The third and last step is to add my autoload function to the default autoloader. I did this by typing the following code also within the Bootstrap.

    /**
     * Init the autoloader for PHP namespaces
     */
    protected function _initMoreNamespace(){
        $namespacesPath = $this->getOption('nmspcspth');
        $classesPath = $this->getOption('clssspth');
        define('PHP_CLASSES_PATH',$classesPath);
        define('PHP_NAMESPACES_PATH',$namespacesPath);
        set_include_path(get_include_path() . PATH_SEPARATOR . PHP_CLASSES_PATH . PATH_SEPARATOR . PHP_NAMESPACES_PATH);
        $autoloader = Zend_Loader_Autoloader::getInstance();
        $autoloader->unshiftAutoloader(array('Bootstrap','getMoreNamespaces'));
    }

Done! Now you can use natural namespace syntax like:

Use Utils\Config as MyConfig;
$configObj = new MyConfig;
$otherNs = new Utils\Tool();

My problem has been solved and now I can proceed with development 😀

Multiple databases support on ZF

Wednesday, June 8th, 2011

Zend Framework is nice but learning it is very confusing and time demanding. Official doc isn’t that clear, lacks of good examples and sometimes is outdated. Whenever I want something to be done I read the official documentation and then google it so I can get a good picture of what everyone did.

One thing that I recently needed was to enable multiple schema support for a specific project. One schema stores client info, the other stores products. One very interesting thing is that the products schema depends on the account so clients for region 1 should use a schema called reg1, while clients from region 2 a schema called reg2.

So the products schema kind of switches dynamically according to users setup.

The first thing to do is setup the config file. This is the easy part, I added some lines that looked like this:

resources.multidb.maindb.adapter = oracle
resources.multidb.maindb.persistent = true
resources.multidb.maindb.host =
resources.multidb.maindb.username = usr
resources.multidb.maindb.password = usr123
resources.multidb.maindb.dbname = "(DESCRIPTION= (ADDRESS= (PROTOCOL=TCP)(HOST=oracle.host.com)(PORT=1521)) (ADDRESS= (PROTOCOL=TCP)(HOST=oracle2.host.com)(PORT=1521)) (LOAD_BALANCE=yes) (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srvcnm)))"

resources.multidb.seconddb.adapter = oracle
resources.multidb.seconddb.persistent = true
resources.multidb.seconddb.host =
resources.multidb.seconddb.username = usr2
resources.multidb.seconddb.password = usr2123
resources.multidb.seconddb.dbname = "(DESCRIPTION= (ADDRESS= (PROTOCOL=TCP)(HOST=soracle.host.com)(PORT=1521)) (ADDRESS= (PROTOCOL=TCP)(HOST=soracle2.host.com)(PORT=1521)) (LOAD_BALANCE=yes) (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srvcnm2)))"

resources.multidb.thirddb.adapter = oracle
resources.multidb.thirddb.persistent = true
resources.multidb.thirddb.host =
resources.multidb.thirddb.username = usr3
resources.multidb.thirddb.password = usr3123
resources.multidb.thirddb.dbname = "(DESCRIPTION= (ADDRESS= (PROTOCOL=TCP)(HOST=toracle.host.com)(PORT=1521)) (ADDRESS= (PROTOCOL=TCP)(HOST=toracle2.host.com)(PORT=1521)) (LOAD_BALANCE=yes) (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srvcnm3)))"

Notice I’m storing everything in a multidb array with three different elements: maindb, seconddb and thirddb. Let’s consider the maindb to be the users schema, for products I’ll be switching between seconddb and thirddb.

First of all the main connection needs to be set so we can login, update, delete and o more stuff with a user account. Alo this connection will be set as the default adapter. I did this in the bootstrap. Here is the code:

/**
* Init the main database connection.
*/
protected function _initDatabase(){
    $applicationConfig = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', APPLICATION_ENV);
    $config = $applicationConfig->toArray();
    $dbIni = $config['resources']['multidb']['maindb'];
    $db = Zend_Db::factory($dbIni['adapter'], $dbIni);
    Model_DbTable_Db::setDefaultAdapter($db);
}

So now we have the main connection up and working as a default adapter. This works the same as a basic database configuration. Now to the interesting part… set up the other database connection according to the user region. In my case the user’s account has a field/property that stores the correct products schema name so one of the things I’ll be doing is reading that property to know which schema I need to connect to for the products details. I won’t explain the account part because it’s quite simple.

We use a baseController from which we inherit all other controllers so we can easily concentrate most of the common methods in one single place. Within that baseController I added the following method:

/**
* Depending on the account we set up the adapter for the products tables
* @param Account A valid account object
*/
private function setProductsSchema(Account $account){
    if(!Zend_Registry::isRegistered('erpdb')){
        $applicationConfig = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', APPLICATION_ENV);
        $config = $applicationConfig->toArray();
        $dbIni = $config['resources']['multidb'][strtolower($account->getSchemaName())]; // In this case $account->getSchemaName() may return 'seconddb' or 'thirddb' 😀
        $erpdb = Zend_Db::factory($dbIni['adapter'], $dbIni);
        Zend_Registry::set('erpdb',$erpdb);
    }
}

Now the application is able to dynamically choose the proper schema for products according to the account. It’s important to add it to the registry with a name, in this case is erpdb. This is necessary in order to let the DbTable objects know which schema they’ll use. Be sure to call this method before making a query to the secondary schema.

Now let’s set up the DbTable objects so they know which connection they’ll be using. Right now all DbTable objects are using the default adapter set in the bootstrap, for those objects that refer to products we need to make them aware that they’ll be using the secondary connection. doing this is pretty straightforward.

Go to your DbTable object and add the following method:

/**
* Set the default adapter for this object
*/
public function init(){
    $this->_setAdapter('erpdb');
}

That’s it! Notice that we set the adapter name the same as the db registry added before.

And that’s basically all we need to do to make the connection dynamic 😀

Hope it helps.

Forms and encoding

Sunday, May 8th, 2011

Ok, Zend Framework has lots of components to do almost anything.
One of the coolest is the form component, it reduces the time spent coding a form and it’s validation and you can then reuse the form code wherever you want and it will behave exactly the same.
One thing was annoying me. When in a form element label you use accents the label, once parsed, will display either weird characters or the raw html code.
For example take a look at this code:

$this->addElement('text','email',array(
            'size'=>'50',
            'label'=>'Correo Electr&oacute;nico*',
            'required'=>true,
            'validators'=>array('NotEmpty','EmailAddress')
            ));

I wanted it to read: Correo Electrónico, but instead of ‘ó´it was displaying a weird character or the raw html code for an accented ‘o’ (&oacute;) so I was wondering how can I solve this. It didn’t take me a lot of time to figure this one out, the solution was simple and elegant. When declaring a form element there is a flag that will handle if the label gets escaped or not.

The only thing I did was to change the element declaration from the former to this:

$this->addElement('text','email',array(
            'size'=>'50',
            'label'=>'Correo Electr&oacute;nico*',
            'required'=>true,
            'validators'=>array('NotEmpty','EmailAddress'),
            'escape'=>false
            ));

That’s it, it works.
Oh, BTW, I have my encodings set to ‘utf-8’, if you have ‘iso-8859-1’ you may leave your accents without encoding as html.

PHP classes autoload (namespaces) Part II

Wednesday, April 20th, 2011

Ok so I made a few tests.

As a matter of fact I think it is better to use the function I wrote about in my previous post.

Turns out that I removed a couple of lines and added some more. At the end I decided to use the set_include_path because it’s more suitable for documentation purposes as well as configuration.

So after a few minutes I came up with this:

define('CLSS_PTH','path_to_classes_folder');
define('NMSPCS_PTH','path_to_namespaces_folder');
set_include_path(get_include_path() . PATH_SEPARATOR . CLSS_PTH);
set_include_path(get_include_path() . PATH_SEPARATOR . NMSPCS_PTH);

function __autoload($class){
    $class = strtolower($class);
    if(strpos($class,'\\')!==false){
        $class = preg_replace('/\\\/',DIRECTORY_SEPARATOR,$class);
    }
    $possibilities = explode(PATH_SEPARATOR, get_include_path());
    foreach($possibilities as $path){
        if(file_exists($path . DIRECTORY_SEPARATOR . $class . ".php")){
            require_once $path . DIRECTORY_SEPARATOR . $class . ".php";
        }
    }
}

So I added a path where to look for classes and namespaces, afterwards we go through all of those paths searching for the file. Works like a charm!