Report inadequate content

Php in Harecoded

Features in PHP 5.4

 -

We had to create a file upload form that allows a user to upload big files. In order to keep a good experience for the user we decided to show the progress bars.

There are several ways of doing that but it came to my mind that PHP 5.4 had an improvement on file upload, making it easier now and wondered if I had the last excuse to upgrade the servers from 5.3 to 5.4.

This is a list of some of the features PHP 5.4 comes with. There are more, but I came here with the intention of speaking about the ones that they care to me. This is not a 5.4 review, but examples.

Session upload progress

I already mentioned it, PHP 5.4 will be handy because now you can ask the server in realtime how the upload progress is going. Mixed with HTML5 you can have a kicking-ass upload form.

Speed

It seems that PHP 5.4 is faster than its ancestry, and I say that it seems because even there are plenty of sites claiming that I still have not run any benchmarks with my app.

Traits

Kids deserve  a candy sometime. We have regret many times using PHP because unlike other languages there has never been multiple inheritance. Now PHP gives us a sugar-free candy to mitigate this. Traits are not the multiple inheritane but might help you out sharing common functionallity between classes. And traits can use traits. This is an example of how a simple trait would work:

<?php
namespace Mammal\Primate;

trait Feeding
{
        public function getDiet( $age )
        {
                if ( $age < 3 )
                {
                        return [ 'breastfed' ];
                }
                else
                {
                        return [ 'fruit', 'leaves', 'flowers', 'buds', 'nectar', 'seeds', 'insects', 'bird eggs' ];
                }               
        }
}

Then your trait can be attached to any class like this, no matter if your class already extends something else:

class Gorilla extends VertebrateKingdom implements Animalia
{
        use \Mammal\Primate\Feeding;
        // ...
}

Now you can use the trait methods directly:

$gorilla = new Gorilla();
$gorilla->getDiet( 5 );

Python-alike stuff: lists and anonymous functions

Being a former pythonist I'm glad to have these two back in town:

Anonymous functions

Create functions on the fly: 

$dump = function( $var ) { var_dump( $var ) ; };
$dump( $gorilla->getDiet( 5 ) ); // Array containing 'fruit', 'leaves'...

Short array syntax

This is the same format than python lists, and the ability to get rid of temporary variables:

// Before: PHP < 5.3:

function getMammals()
{
        return array( 'monkey', 'zebra', 'dolphin', 'cat', 'John' );
}

$mammals = getMammals();
echo $mammals[0];

// Now: PHP 5.4+
function getMammals()
{
        $mammals = [ 'monkey', 'zebra', 'dolphin', 'cat', 'John' ];
}

echo getMammals()[0]; // Look that you don't need the temp variable anymore

Webserver

Finally, now you can run a debugging server without the need apache:

 php -S localhost:8080 -t /var/www/tests 

Not very useful in my case scenario where I have a full virtual environment with puppet and so on, but maybe for running temporary scripts might be useful. With earlier versions remind that you can always execute inline PHP from command line like this:

php -r "phpinfo();"

Yeah!!!

Apache RewriteCond -f check file exists solution

If your Apache virtualhost or htaccess configuration uses a rewrite condition (RewriteCond) in order to allow nice URLs, you should be aware that since Apache 2.2 the "check if file or exists" works a little bit different. Any of the following examples might have stopped working for you:

   RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-s

The solution to correct it is very simple, but I couldn't see it documented. All you have to do is to add the variable DOCUMENT_ROOT before the REQUEST_FILENAME

The following example redirects all non existing files to index.php, here is the difference.

Before Apache 2.2:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.+) /index.php [QSA,L]

Apache 2.2 and later:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^/(.+) /index.php [QSA,L]

The Apache 2.2 documentation is here: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

Llamadas cURL a través de distintas interfaces


 - Si tu servidor web dispone de varias interfaces de red y quieres que ciertas peticiones que haces con cURL salgan a través de una IP específica puedes modificar el flag CURLOPT_INTERFACE de cURL pásandole la IP.

Un ejemplo tonto podría ser:

...
// Todas mis interfaces de red:
$interfaces = array(
        '91.121.157.41',
        '178.33.161.225',
        '188.165.128.67',
        '178.33.166.125',
        '178.33.163.125',
);
// Salir aleatoriamente por una de ellas:
$rand_interface = $interfaces[rand(0,count($interfaces)-1)];
curl_setopt($curl_handle, CURLOPT_INTERFACE, $rand_interface );
...

Esto te puede servir tanto para balancear carga, como para forzar que una petición venga de un orígen único. Especialmente útil para hacer cosas feas en servidores con IP failover.

En una máquina con IP Failover la lista de interface de red puede ser:

cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 91.121.157.41
        netmask 255.255.255.0
        network 91.121.157.0
        broadcast 91.121.157.255
        gateway 91.121.157.254


auto eth0:0
iface eth0:0 inet static
        address 178.33.161.225
        netmask 255.255.255.255

auto eth0:1
iface eth0:1 inet static
        address 188.165.128.67
        netmask 255.255.255.255


auto eth0:2
iface eth0:2 inet static
        address 178.33.166.125
        netmask 255.255.255.255

auto eth0:3
iface eth0:3 inet static
        address 178.33.163.125
        netmask 255.255.255.255

Smarty: Concatenation of variables inside block parameters

In Smarty sometimes you need to concatenate 2 variables and pass it as a single variable inside a block. But the placeholder won't allow any expected PHP syntax

You want to accomplish something like:

{assign var="MYVAR" value=$variable1.$variable2}

But, the dot in smarty is for array access, so, what about...

{assign var="MYVAR" value=$variable1+$variable2}

No. It does not work either. Ah! Let's try a modifier:

{assign var="MYVAR" value=$variable1|cat:$variable2}

Aha! That's the solution!

Dedicated to my friend Sambel, no pun intended!

How to setup a remote development environment over SFTP (working copy)

This article explains how to setup the server and client to work with a remote working copy.

To properly understand this post you should have read the previous post, When to setup a remote development environment over SFTP (working copy).

To have the enviroment up and running you must setup once the server, and then apply the configuration of the client in every developer machine. But the client side is very simple and requires no installation at all.

Here's how:

Read more

When to setup a remote development environment over SFTP (working copy)

When a programmer has a local copy of the code and an environment fully functional where the web can be tested before going live, we usually call it a working copy.

The action of moving/copying/putting this work in the final live server (a.k.a production server/environment) is called the deploy action.

There are many ways of having a working copy up and running. We, the key stroker maniacs, use to work more or less with one of the following working copy configurations:

  • No working copy. The one who enters via SSH and uses the editor vi. Yeah!
  • Edit via FTP/SFTP with an editor installed in the local machine. No working copy, the return.
  • Local web server. Usually a pre-built LAMP solution, such as MAMP or XAMPP. Valid until you need to add 2 or 3 more services like Memcached, Sphinx, Solr, MongoDB, Redis or anything like that, or the Virtual host configuration starts to change over and over.
  • A web server in your LAN. Several users using a machine with all the services configured, having their own running copy. Different DocumentRoot per user.
  • The Virtual machine lover, who runs a VirtualBox or VMWare with a full linux installed and exports and shares the appliance with colleagues if necessary.
  • The Vagrant chef, who has an automated system to deliver pre-configured environments to any number of developers using VirtualBoxes underneath.

In this post, I am proposing something different, it has the smell and aroma of the early 90's development, but still, a good solution when you have a middle team (2-20) where people don't want to be bothered with constant database changes and service tunning. It is the private remote working copy over SFTP. Keep reading...

Read more

Merge Json files

With this small script you could merge some json files in a new one in json validated format.  The script uses each file name like array key.

Look the example:

file1.json:

{"array1":["elem1","elem2","elem3"],"array2":["elem1","elem2","elem3"]}

file2.json

{"array3":["elem1","elem2","elem3"]}

 

Whit our script you could run:

  • php merge_jsons.php file1.json file2.json > merged_jsons.json

 

Now you can open merged_jsons.json and look this:

{"file1":["array1":["elem1","elem2","elem3"],"array2":["elem1","elem2","elem3"]],
"file2":["array3":["elem1","elem2","elem3"]]}

The script:

for ( $i=1; $i{
$file_name = basename($argv[$i]);
$key_name = strstr($file_name,'.',true);
$data = file_get_contents( $argv[$i] );
$result[$key_name]=json_decode( $data );}echo json_encode( $result );
}

Convert a CSV to JSON with PHP

Imagine a data list dumped in a plain text file (e.g: CSV) and you need to convert it to JSON format. You could use this simple php script to do such task.

It's the simplest version but from here you can customize it to fit your requeriments.

Usage:

php script_name.php file_to_convert.csv > result.json

The script:

$csv = file_get_contents( $argv[1] );
$csv = explode("\n", trim($csv) );

foreach ( $csv as &$line )
{
$line = trim( $line );
}

print json_encode($csv);

This example covers a "single column" CSV file. If you want to add several columns you only need to add an explode with the separator character, be comma, somicolon or tab.

Instalar PHP 5.3 en CentOS

Me tienen contento!

Hace muchísimo que deberían haber incluído la versión de PHP 5.3 en los paquetes php por defecto de CentOS, pero parece que se van a quedar con la 5.2 hasta el fin de los tiempos. Ofrecen la versión 5.3 como un paquete separado (php53), lo que implica desinstalar PHP y librerías asociadas para reinstalar la 5.3 con este paquete distinto (incompatible con el anterior claro).

Así que, no pudiéndome aguantar más y con mono de namespaces, funciones lambda y toda la pesca, he migrado mi CentOS 5.5 a la 5.7 (esto no viene al caso ahora ni es necesario, via yum update.) y luego PHP a la 5.3 utilizando un repo externo. Para ello me he servido del repositorio REMI. Si no lo tienes para instalarlo sólo hay que hacer:

cd /etc/yum.repos.d/
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm

Y para disfrutar de la 5.3:

yum --enablerepo=remi update php

Si no tienes aún PHP instalado entonces usa "install" en vez de "update".

Ale! Todo listo.

Writing complex regular expressions

Regular expressions are usually hard to read and understand. Even if you have a lot of experience on the subject, when you retakeone that you wrote some time ago, it is difficult to catch up.

Some days ago, a very smart guy at work named Zoltán recommended us to write complex regular expressions sepparating each logical part in a different line and also comment every one.

I did not know that this was possible at all, but he shown us how the modifier "x" (see it at the end of the following example) makes the compiler to ignore any whitespaces (spaces, tabs, line breaks) and even comments!!

So, with this, you can write crazy regular expressions easy to parse and understand. Here there is a silly example, imagine it in a single line!:

if ( preg_match('/
    ^                       # We match the beginning because we match full string.
    (Can|May)\x20           # May is more formal, can Can is also OK.
    [yY]ou\s                # You can match space with backslash and space or any whitespace with \s
    (please)?\x20           # "Please" is optional ;)
    (comment|document)\x20  # Commenting = documenting
    this\ regexp\x20        # If UNICODE mode is on (modifier "u"), you can also match space with \x20
    to\s(know|see)\x20
    (what|WTF)\x20          # WTF = World Taekwondo Federation
    it\ does\?              # Note the "x" modificator int he next line. If makes regexp ignore whitespaces.
    $                       # We match the end because we match full string.
    /x',
    "Can you please comment this regexp to know what it does?" ) )
{
    echo "Thank you!";
}
 

Thank you Zoly!