Archive for October, 2014


A more verbose var_dump()

Have you ever noticed how when you do a var_dump() that it always goes so far into the tree then displays three dots … ?

Have you ever wanted to see beyond those three dots? The answer is your xdebug PHP ini settings!

; with sane limits
xdebug.var_display_max_depth = 10
xdebug.var_display_max_children = 256
xdebug.var_display_max_data = 1024 


; with no limits
; (maximum nesting is 1023)
xdebug.var_display_max_depth = -1 
xdebug.var_display_max_children = -1
xdebug.var_display_max_data = -1 

You can set this stuff on your script with  ini_set() :

ini_set('xdebug.var_display_max_depth', 10);
ini_set('xdebug.var_display_max_children', 256);
ini_set('xdebug.var_display_max_data', 1024);

Much better!

Advertisements

Using Emmet in your IDE

Emmet is awesome! It’s a little tool (once called Zen Coding) that gives you loads of keyboard shortcuts for generating HTML and CSS markup! Give it a try! Install an Emmet plugin into your IDE. Then, in a view file, try typing this:

table#applications.table-striped.table-hover.table>thead>tr>td*3^^tbody>tr>td*

In PHPStorm, hit TAB after typing that. In Eclipse/Aptana, you press CTRL-E. Suddenly, it changes to:

<table id="applications" class="table-striped table-hover table">
    <thead>
        <tr>
            <td></td>
            <td></td>
            <td></td>
         </tr>
    </thead>
    <tbody>
         <tr>
             <td></td>
             <td></td>
             <td></td>
         </tr>
    </tbody>
</table>

As you can imagine, this saves a LOT of time! Check out the Emmet Cheatsheet here:
http://docs.emmet.io/cheat-sheet/

You can download the plugin for your IDE here:
http://emmet.io/download/
Have fun!

Usually I just bung in 127 or localhost in order to connect up to my DB. However, if you aren’t allowing remote connections, then running on a unix socket is much faster and skips all the networking overhead involved with TCP/IP.

So! To use a socket, you use a DSN for the connection. I’ve done this a few times, but I keep forgetting the syntax, sop here it is, solely for my own memory’s sake:

mysql:unix_socket=/tmp/mysql.sock;dbname=my_db_name_here

Expanding upon my abstract DB class that auto creates Zend_Paginators on demand, I thought it was about time I did something regarding automatically sorting the records returned.

First thing I did was go in and edit my db base class (need a reminder? https://delboy1978uk.wordpress.com/2014/06/30/auto-paginator-with-zend_db_table/), adding a sort_field property, a setSortField() method, and a little if statement in our getResult() method :

    /** @var string $sort_field */
    protected $sort_field = null;
    /**
     *  For instance 'date_added DESC'
     *  @param int $no
     *  @return $this
     */
    public function setSortField($sort_and_direction)
    {
        $this->sort_field = $sort_and_direction;
        return $this;
    }
    /**
     * @param Zend_Db_Select|string $select
     * @return \Zend_Db_Table_Rowset_Abstract|Paginator
     */
    public function getResult($select)
    {
        if(is_string($select))
        {
            $select = $this->select()->where($select);
        }
        if($this->sort_field)
        {
            $select->order($this->sort_field);
        }
        if($this->paginator_flag == true)
        {
            return $this->getPaginator($select);
        }
        return $this->fetchAll($select);
    }

Now we have that, we can sort any queries like so:

        // Get the page number
        $page = ($this->getRequest()->getParam('page')) ?: 1;
                
        // Set pagination
        $db->setPaginatorFlag(true);
        $db->setNumPerPage(30);
        $db->setPage($page);
        
        // Get sort field
        $sort = $this->getRequest()->getParam('sort');
        $dir = $this->getRequest()->getParam('dir');
        
        // Set the sort
        $db->setSortField($sort.' '.$dir);

Again, in your DB class method, make sure it calls $this->getResult(); and not fetchAll().

Anyway, thats only one half of the equation, what we need is sort links! I create a view helper for this, which basically calls the url view helper, but with additional search capabilities. In the Bootstrap (as you’ll know), we define our routes as such:

$router->addRoute(
    'lead-assessor-view-supply',
    new Zend_Controller_Router_Route(
        '/lead-assessor/view-supply/:orgid/:id/:page/:sort/:dir',
         array(
            'controller' => 'lead-assessor',
            'action' => 'view-supply', 
            'page' => 1, 
            'sort' => 'date_from', 
            'dir' => 'DESC'
         )
      )
);

As you can see, I have added sort and dir in addition to page.  To get the links working, send the page, sort, and dir variables to the view, and in the view, instead of calling $this->url(blahblah); we will call our own view helper, sortLinks(); Here’s the class:

<?php 

class ESOS_View_Helper_SortLinks extends Zend_View_Helper_Abstract
{
    /** 
     *  Pass in a route name, and an array of any params which are the same for all the sort links
     *  @param string $route_name
     *  @param array $params
     *  @param string $field_name
     *  @param string $sort_field
     *  @param string $sort_dir
     *  @param string $field_label
     *  @param string $classes
     *  @return string
     */
    public function sortLinks(array $params,$route_name,$field_name,$field_label, $classes = null)
    {
        // Set the current sort field
        $current_sort_field = isset($params['sort']) ? $params['sort'] : 'ASC' ;
        
        // Set the Icon
        $icon = $this->view->sortIcon($field_name,$current_sort_field,$params['dir']);
        
        // Set params
        $params['sort'] = $field_name;
        $params['dir'] = $this->view->sortDir($field_name, $current_sort_field, $params['dir']);
        
        // Build the HTML
        $link = '<a href="';
        $link .= $this->view->url($params,$route_name);
        $link .= '" class="';
        $link .= $classes;
        $link .= '">';
        $link .= $icon;
        $link .= $field_label;
        $link .= '</a>';
        
        // Return the HTML
        return $link;
    }
}

Almost there! You’ll see it is calling another two view helpers, sortIcon and sortDir:

<?php

class ESOS_View_Helper_SortDir extends Zend_View_Helper_Abstract
{
    public function sortDir($field_name, $current_sort_field, $dir)
    {
        if($field_name == $current_sort_field)
        {
            switch($dir)
            {
                case 'ASC':
                    $dir = 'DESC';
                    break;
                case 'DESC':
                default:
                    $dir = 'ASC';
                    break;
            }
        }
        return $dir;
    }
}
<?php

class ESOS_View_Helper_SortIcon extends Zend_View_Helper_Abstract
{
    public function sortIcon($field_name, $current_sort_field, $dir)
    {
        if($field_name == $current_sort_field)
        {
            switch($dir)
            {
                case 'ASC':
                    $icon = '<i class="fa fa-caret-up"></i>&nbsp;';
                    break;
                case 'DESC':
                default:
                    $icon = '<i class="fa fa-caret-up"></i>&nbsp;';
                    break;
            }
        }
        else 
        {
            $icon = null;
        }
        return $icon;
    }
}

These just figure out which direction of sort the link will generate. The Icons are from Font Awesome, but feel free to use anything you like!

Tying it all together, in your view, define an array of any parameters that you will pass into each sort link (sort, and dir should always be in there, page if using the paginator):

    // Common params for the sortLinks
    $params = array(
        'orgid' => $this->org->getId(),
        'page' => $this->page,
        'sort' => $this->sort,
        'dir' => $this->dir,
    );

At the top of your table where you want your clickable sort links, call:

<?= $this->sortLinks($params,'portfolio-admin-users','name',$this->t('Organisation')); ?>

Sorting By Price

Sorting By Status

This will save a LOT of farting around in the future! Have fun! 🙂

Updating a forked GitHub Repo

At the PHPNW 2014 conference, they had a ‘Hackathon’, where everyone got together and started hacking away at projects. I had a shot at the JoindIn website.

Anyway, I forked the repositories so I could work on my own branch. Now though, my fork is outdated, and needs updating. So in order to remedy this, we add another remote.

From your local machine’s cloned repo, you simply say:

git remote add upstream https://github.com/joindin/joindin-web2.git
git checkout master
git pull upstream master
git push origin master

Thanks to Derick Rethans of XDebug fame for this info 😀

Fixing the Shellshock Vulnerability

While I was on holiday in Andalucia (Olé!) a vulnerability was found for the Bash shell, called Shellshock (or BashDoor).
http://en.wikipedia.org/wiki/Shellshock_%28software_bug%29
So you’ll be wanting to secure yourself up then. First up, lets see if you are vulnerable:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

If the output contains ‘vulnerable’, then you need to fix it. If not, you’re all good. To fix it:

sudo apt-get update
sudo apt-get -s upgrade
sudo apt-get  upgrade

Now get back on with your work! 😉

If you’re here, that’s probably because you just put a datepicker into a bootstrap modal, but realised that the Year dropdown isn’t working properly, and when you click it, nothing appears to happen.

Luckily, it’s quite easy to fix. After initialising your element with

$('#mytextbox').datepicker({//options here});

All that is required is to paste this line of code, which does something regarding javascript’s dom focus :

$.fn.modal.Constructor.prototype.enforceFocus = function() {}

Job done! You can get back on with your work now! 🙂

About time we can do this! Check it out! In the example below my file input is called #evidence. The dataType option sets what jQuery can expect to receive back in the response, in this case, I send back JSON.

                var jform = new FormData();
                jform.append('supply_id',supply_id);
                jform.append('fuel_usage',$('#fuel_usage').val());
                jform.append('cost',$('#cost').val());
                jform.append('currency',$('#currency').val());
                jform.append('reading',$('#reading').val());
                jform.append('data_source',$('#data_source').val());
                jform.append('date_from',$('#date_from').val());
                jform.append('date_to',$('#date_to').val());
                jform.append('evidence',$('#evidence').get(0).files[0]);
                jform.append('comments',$('#comments').val());
                
                $.ajax({
                    url: '/your-form-processing-page-url-here',
                    type: 'POST',
                    data: jform,
                    dataType: 'json',
                    mimeType: 'multipart/form-data',
                    contentType: false,
                    cache: false,
                    processData: false,
                    success: function(data, status, jqXHR){
                        alert('Hooray! All is well.');
                        console.log(data);
                        console.log(status);
                        console.log(jqXHR);
                        
                    },
                    error: function(jqXHR,status,error){
                        // Hopefully we should never reach here
                        console.log(jqXHR);
                        console.log(status);
                        console.log(error);
                    }
                });

Here’s one you might have had. “Lost connection to MySQL server at ‘reading initial communication packet’ “.

If  you get this, then I assume that you are connecting to another machine on the network, a virtual machine, or a remote server.

It’s a pretty simple fix. Edit your /etc/mysql/my.cnf (path may differ depending on your setup), and change the line that says bind-address = 127.0.0.1 to:

bind-address = 0.0.0.0

Save it, then restart mysql.

sudo service mysql restart

Job done!

PuPHPet and Vagrant are awesome. If you develop on Windoze, you are either off your head, or have no choice in the workplace. Right now I fall into the latter category. I noticed XAMPP installed. Yeah right. No chance. Anyway, using PuPHPet and Vagrant is a far better way of doing things regardless of your OS, as it means you can move your entire development environment anywhere without having to reconfigure anything! See my post https://delboy1978uk.wordpress.com/2014/08/18/using-puphpet-and-vagrant/ for info on getting set up and running.

Anyway, it turns out that the files and directories for your sites are all owned by www-data, and are in the www-data group. I was trying to run a PHP CLI command, however, as the logged in user is vagrant and the permissions were only executable for the owner, I tried running chmod, and chgroup, and chown, with no success. Because these are mounted folders and not actually in the VM, altering the permissions the normal way is impossible.

The solution is to go into your VagrantFile, and add the following:

config.vm.synced_folder "./mysite/scripts", "/var/www/mysite/scripts",
        owner: "www-data",
        group: "www-data",
        mount_options: ["dmode=775,fmode=775"]

The first path given is relative to your host OS directory with your site folders inside, the second path is the path on the VM. dmode I’m guessing is the directory permissions, fmode is the file permissions. I keyed this in just before the ‘end’  line at the bottom of the VagrantFile.

To make the changes, you can type vagrant up (if you havent started yet), or vagrant reload. Permissions have now been changed!

One last thing. Once I was able to execute, I ran my script and got

: No such file or directory

This again is a stupid character encoding issue due to windows, and the way I sorted it was to cat the file in Putty, and select the text, nano a new file, paste it in, delete the original, and rename the new file. I didnt have to chmod anything, all files in here now default to 775.

Anyway, now that problem has been solved I can get back on with my work! Cheers! 😀

UPDATE

It appears that the Vagrant file has been broken up into smaller more specific parts. In a recent puPHPet Vagrant box, I had to paste it in the puphpet/vagrant/vagrantfile-local file,  right before the very last line (which just says end).