John Main Logo

John Main

Code. Design. Hosting. Maintenance.

11
Apr '16

If you’re trying to install or update packages via yum on a RedHat /CentOS server and you keep getting ‘Multilib’ errors along the lines of:

Protected multilib versions: openssl-1.0.1e-42.el6_7.4.x86_64 != openssl-1.0.1e-42.el6.i686

Then this means that you already have a 32bit version of a package and you’re trying to install a 64bit version (either by direct installation or as a dependency), or vice-versa. Generally these days you will be operating on a 64bit system so this issue can be very easily fixed by running the following

yum remove *.i386 *.i486 *.i586 *.i686

And then installing the 64 bit versions (these should be the defaults) of the offending packages.

I encountered this when trying to use a 64 bit CentOS image as an AWS server due to 32 bit packages being pre-installed. Good grief it took me a while to figure out!

03
Jan '16

When building controllers I, along with many others I’m sure, generally create an abstract ‘base’ controller to contain some standard functionality, and which all the other controllers can extend. I use these for common pre/post processing functions, session management and all sorts of other stuff. This works well for a simple site, however there are many instances where controllers can’t all extend the same base class – for example if you want to setup shared CRUD functionality this will have to be different with normal vs nested resources. Where I have controllers that can’t all extend the same base class but still need to have some functionality in common I like to use a trait. A key example of this is when handling JSON responses I tend to use the following trait:

trait JSON {

    /**
     * Send success
     * @param string [$message='OK'] Message
     * @param integer [$response_code=200] Response code
     */
    protected function sendSuccess($message = 'OK', $response_code = 200) {
        return $this->sendResponse([], $message, $response_code);
    }

    /**
     * Send failure
     * @param string [$message='Error'] Message
     * @param integer [$response_code=404] Response code
     */
    protected function sendFailure($message = 'Error', $response_code = 404) {
        return $this->sendResponse([], $message, $response_code);
    }

    /**
     * Send error
     * @param array $data Data
     * @param string [$message='OK'] Message
     * @param integer [$response_code=200] Response code
     */
    protected function sendResponse($data, $message = 'OK', $response_code = 200) {
        $data = ['success' => ($response_code >= 200 && $response_code < 300), 'message' => $message, 'data' => $data];

        return response()->json($data, $response_code);
    }
}

This code is written for Laravel 5, but could easily be adapted to another framework.

10
Nov '15

I love most of the new features of Laravel 5, but it definitely has its drawbacks – a specific one as far as I’m concerned is the new way of managing configuration files. In Laravel 4 we all got very accustomed to being able to have a full set of configuration files for each environment, with any level of nesting and complexity we liked, but now everything we want to do on a per-environment basis has to be defined within flat .env files. Having said that I do completely accept that it is better in terms of safety to have a single, non-version-controlled environment config file, rather than a whole bunch which, lets be honest, we all ended up putting under version control, passwords and all!

So in an effort to embrace the new structure whilst maintaining some of the function of the old, I came up with a little script to allow some futher complexity to my .env files. When this is added to the ‘boot’ method of the ‘AppServiceProvider’ class it allows multiple pipe-separated values do be pre-processed into an array within the config structure:

if(env('MY_ENV_VALUE')) {
    config()->set('app.my_env_value', explode('|', env('MY_ENV_VALUE')));
}

Really really simple stuff but good grief does it make a difference!

23
Sep '15

This is a quick one for those who are attempting to transition over to Eloquent from another DAL where model ‘getter’ and ‘setter’ commands are the norm, rather than directly accessing the database field as a parameter, or indeed simply for those who prefer the ‘getter’ and ‘setter’ style of field access. e.g.

$table->setName('name');
return $table->getName();

rather than

$table->name = 'name';
return $table->name;

All you need to do is to include this in a base model which all your other models can extend, then it will transparently allow you to access your database fields in whatever fashion you like:

/**
 * Magic method to handle getThing() and setThing('value') calls automatically
 *
 * @param string $method Method
 * @param array $args Arguments
 * @return mixed
 */
public function __call($method, $args) {

    $action = strtolower(substr($method, 0, 3));

    if($action == 'get' || ($action == 'set' && $args)) {
        $lc_field_name = strtolower(substr($method, 3));

        //If you're using Laravel you can use the built-in snake_case() method here instead
        $snake_field_name = strtolower(preg_replace("/(?<=[a-z0-9])([A-Z])/", "_\$1", substr($method, 3)));

        $columns = array_keys(self::attributesToArray());

        if(in_array($lc_field_name, $columns)) {
            return $this->callHelper($action, $lc_field_name, $args);
        }
        elseif(in_array($snake_field_name, $columns)) {
            return $this->callHelper($action, $snake_field_name, $args);
        }
    }
    
    return parent::__call($method, $args);
}

/**
 * Call helper
 *
 * @param string $action Action
 * @param string $field_name Field name
 * @param array $args Arguments
 * @return mixed
 */
protected function callHelper($action, $field_name, $args) {
    if($action == 'get') {
        return $this->$field_name;
    }
    else {
        $this->$field_name = $args[0];
        return $this;
    }
}

You’ll notice that as a little flexibility bonus, it will look for matching field names that are either snake case or just simply lower-cased.
It’s also worth bearing in mind here that you will get a performance increase if you cache the column list, at least at object level, so that it doesn’t have to read them fresh for every call.

04
Jun '15

This all related to a bit of a quirk of the way javascript operates on click events. You would think that in order to triggering analytics on a download link you could just add a click handler to the link and it would be all good. Unfortunately this is not the case. As analytics triggers are pretty much universally ajax calls the script will continue before it gets a response, and if that continuation leads to a download (or indeed simply to navigation away from the current page) then the analytics trigger will fail. My solution involves forcing the browser to give analytics a couple of seconds to return before completing:

$(document).on('click', 'a.download-file', function() {
    var element = $(this);

    ga('send', 'event', 'File', 'Download', 'File Download');

    setTimeout(function() {
        window.location.href = element.attr('href');
    }, 2000);

    return false;
});

Of course it’s not bullet-proof but it’s my go-to solution for these situations.

08
Apr '15

There are a hundred and one tutorials on integrating with Twitter’s REST API, but to my mind there are few easy to follow tutorials that simply show you how to connect, authenticate with OAuth2 and pull down the latest tweets which, let’s face it, is what most people want to do at least as a starting point! So I thought I’d do a quick tutorial here and make it as simple as humanly possible.
I’ve used Abraham’s TwitterOAuth module for my tutorial, which I generally install via composer where the framework supports. You can flesh this out into a module, or customise your business logic any way you like, but this is the raw code that will do the job as simply as possible.

First you need to register your app with Twitter and get a consumer key and consumer secret, then you are ready to use the below:

$consumer_key = 'MYCONSUMERKEY';
$consumer_secret = 'MYCONSUMERSECRET';
$twitter_account = 'newscientist';

//Make initial connection (namespaced here as it arrives in its composer bundle - otherwise require/include as necessary)
$connection = new \Abraham\TwitterOAuth\TwitterOAuth($consumer_key, $consumer_secret);

//Request the access token
$token_data = $connection->oauth2('oauth2/token', array('grant_type' => 'client_credentials'))

//Check that we have definitely had the access token returned
if (!empty($token_data->access_token)) {
    //Reconnect with access token in place
    $connection = new \Abraham\TwitterOAuth\TwitterOAuth($consumer_key, $consumer_secret, null, $token_data->access_token);

    //Read the timeline for your selected account
    if ($tweets = $connection->get('statuses/user_timeline', array('screen_name' => $twitter_account, 'count' => 100) )) {
        foreach ($tweets as $tweet) {
            //You now have your tweets available as stdClass objects to do with as you wish
            echo $tweet->text . ' - ' . $tweet->created_at . "\n";
        }
    }
}

It’s generally worth storing the access token locally, or at least in the session, as Twitter will start rejecting your requests if you ask for a new token too many times in a row, but other than that you’re good to go.

Other Twitter REST API calls can be made in the same way, and are detailed at https://dev.twitter.com/rest/public

01
Mar '15

This will be a very short post but I’ve just discovered my favourite feature of CSS3 and I wanted to share in case any of you out there missed it. Ever find yourself with elements that, if populated, work really well in the page and give a lovely user experience but, if empty, just leave gaping holes in the page. I particularly get this situation with message bars in page headers, or in labels I create ready to receive validation error messages.

Now I know the true CSS ninjas will have a million and one ways to deal with this, but by far the simplest and most excellent approach I’ve found is the CSS3 :empty selector:

label.error:empty {
   display: none;
}

Just like that! Any empty labels with the ‘error’ class will be hidden. As soon as they are populated they will show. Easy.
It’s worth noting though that even a single space within the element will cause it to be viewed as not empty – be careful with your whitespace out there!

<Insert note about CSS3 not being supported by all browsers here>

15
Jan '15

For the benefit of those of you who haven’t heard of them, honeypots are a very cool alternative to captcha codes which protect your forms from spam-bots without requiring any additional interaction or effort from your real users. In a nutshell they exploit the stupidy of spam-bots, by having a special field that would not be filled in by a real user, but which a spam-bot will complete automatically, along with the rest of the form.
The process goes like this:

  • Create an additional field in your form
  • Hide that field from normal users
  • Put a catch in your backend script that checks for a value in this field
  • If the field has a value the script ignores the form submission but still returns the normal ‘thank you for submission’ type message, so the spam-bot assumes it was successful

Firstly to add the hidden field to your form DO NOT use an HTML ‘hidden’ input type as few spam-bots will attempt to give these a value. Instead give the input an innocent sounding class name (I like to use ‘hny’) and throw it off the side of the page using CSS like so:

input.hny {
    position: fixed;
    left: -1000000px;
}

Also make sure the input is named something equally innocent. I often have contact forms with separate first_name and last_name fields and so give my honeypot field the name of ‘name’, but really just pick anything that you’re not already using in your form.

On the server you then simply need to look for a value against this field, and redirect as though the submission was successful. For example (in Laravel):

if(\Input::get('name')) {
    \Session::flash('message', 'Thank you for your submission');
    return \Redirect::route('frontend.index');
}

And you’re done! Easy spam-protection with no extra hassle for your users. Good times!

04
Dec '14

Those of you who do much work in Laravel will know that dumping the last query performed can be rather a pain. The classic way is to insert the following after the query you want to inspect:

$queries = \DB::getQueryLog();
dd(end($queries));

However this is awkward, hard to remember, and gives you the bindings separately from the main query, leaving you to recombine them manually. After a little thought I decided the best thing was to write my own function that I could insert into /app/start/global.php and then have available to use from anywhere within my application:

/*
 * Dump last query and exit
 */
function dddb() {
    $queries = \DB::getQueryLog();
    $query_parts = end($queries);

    $query = $query_parts['query'];
    $bindings = $query_parts['bindings'];

    foreach($bindings as $binding) {
        if(is_numeric($binding))
            $query = preg_replace('/\?/', $binding, $query, 1);
        else
            $query = preg_replace('/\?/', "'" . $binding . "'", $query, 1);
    }

    dd($query);
}

Now all I have to do is call dddb(); from anywhere within my code to get the complete last executed query. No fuss, no pain :)

27
Oct '14

Many of you may have already noticed that PHP’s ‘class_exists’ and similar methods don’t give you any help when you’ve got Composer (or most other autoloader solutions for that matter) loading your classes.
I was looking for a way to check for the existence of a class that was a little more clever than simply trying to look for files in folders so I came up with this little function to extract the information directly from Composer’s class map.

/**
 * Check if a class is autoloaded
 * @param string $class_name Class name
 * @return boolean
 */
public static function isAutoloaded($class_name) {
    $class_loader = require(base_path() . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php');
    $class_map = $class_loader->getClassMap();

    //Remove any preceding slashes in the class name (they may be there due to namespacing but composer doesn't store them in the class map entries)
    $class_name = preg_replace('/^\\\\+/', '', $class_name);

    return isset($class_map[$class_name]);
}
´╗┐