Category: PHP

  • AWS EC2 PHP7 upgrade

    Goal: Upgrade AWS EC2 to PHP7
    Secondary Goals: Learn Docker

    After the dust had settled from the birth of our 2nd child, I decided it was time to revisit my to-do list. Top of that list was to upgrade my AWS EC2 instance to PHP7. Those braver than myself may have simply just upgraded and hoped for the best. My doomsday mindset wouldn’t allow me to do this. Although, as it turned out the more gun-ho approach would have probably been fine.

    My existing production environment is a LAMP stack with all dependencies installed on the same AWS AMI EC2 instance. I use this WordPress blog as a service so this is also hosted on the same box. I also have several side projects each with its own VHOST entries. My dev environment is using Zend server community edition which is still using PHP5. This dev environment is what I’m hoping I can replace with Docker.

    Preparation

    Ok, first up I created a new directory that would contain all files I would need on the box.

    /container
    /container/configs/apache — an vhost conf file for each domain
    /container/mysql/ – SQL dump files to import tables
    /container/sites/nickbennett/ – all files for main site
    /container/sites/blog/ – all files for the blog

    A point to note regarding the SQL files is because the DB is blank you will need to set up your initial user e.g.

    /container/mysql/user.sql

    SET PASSWORD FOR 'root'@'localhost' = PASSWORD('mypassword');

    /container/mysql/databases.sql

    CREATE DATABASE IF NOT EXISTS nickbennett;

    The Dockerfile

    FROM amazonlinux:2017.03
    RUN yum update -y
    RUN yum install -y php70 php70-mysqlnd httpd24 mysql56-server nano.x86_64
    ADD sites/nickbennett/ /var/www/site/nickbennett
    ADD sites/blog/ /var/www/site/blog
    ADD configs/apache/ /etc/httpd/conf.d/
    ADD mysql/ tmp/
    EXPOSE 80
    CMD service httpd start
    CMD chkconfig mysqld on
    CMD service mysqld start
    CMD mysql < /tmp/users.sql
    CMD mysql --password=mypassword < /tmp/databases.sql
    CMD mysql --password=mypassword < /tmp/nickbennett.sql
    CMD mysql --password=mypassword < /tmp/blog_nickbennett.sql

    Then to build

    docker build -t nbsite .
    docker run nbsite

    wait something happened…there were no errors…but I can’t access anything on port 80!

    I run docker ps and there is no container listed. I tried without much luck to find the answer. My assumption was that the httpd service running would be enough to keep the container running. I even raised a stack overflow question…

    Stack Overflow

    Luckily, an old colleague came to the rescue with this command…

    docker run -it -p 8080:80 --rm nbsite bash

    This runs bash within the container so as long as I remain logged into bash the container would remain open. The only downside is all of the ‘CMD’ calls made in the Dockerfile would no longer be run. These would have to be run manually. To save running these each time I created a new directory /container/Bash and inside it, I made an executable shell file with the same commands as the docker file. I simply copied this onto the container and ran it from the command line. Hey presto my local AWS AMI PHP7 box is up and running! I can access the site via port 8080 i.e. nickbennett.dev:8080 (remember to update your local /etc/hosts).

    To use the container as a dev environment I need the ability to edit the local files on the container. Docker has a simple -v command which allows you to map a local directory to the one on your container. I can edit the files locally and see the change immediately in the browser.

    docker run -it -p 8080:80 -v /LOCAL_PATH_TO_CONTAINER_DIR/container/sites/nickbennett:/var/www/site --rm nbsite bash

  • Silence is broken

    It’s been over a year since my last blog. I’d like to say that this is down to something interesting. Perhaps due to a period of deep meditation. Or maybe having to be ‘off the grid’ due to government agencies being after me. Sadly it’s none of these things. I’ve been working on the new site you see before you, so Ta-Da! Welcome to the new Nickbennett.co.uk!

    I made some pretty big decisions last year…

    1. No more My full English
    Having given up the fried delicacy due to the extreme Dad bod I’m already rocking. It seemed to me the idea had run its course. Google already do a great job with the map and review service. Also, I’ve come to the conclusion that if I want to learn something new I should push for it in the 8 hours at work, and not in the exhausting hour after work. Starting another green field project is just too much commitment.

    2. Migrate nickbennett.co.UK away from WordPress
    Decision one means that I need a better platform to demonstrate my skills as a developer. I needed a more flexible framework that allows me complete control of the site. The new site is a Symfony project that uses WordPress as a service.

    The new site is up and includes everything I wanted. I have ported everything from the old site over with some extra additions.

    The past year had some interesting life events. I got married, I became a front-end developer and my boy started school. Now the silence is over I’ll tell you more about it in the up and coming months.

  • New Look NickBennett.co.uk

    I recently decided to sit down with my site and see what needed doing. I scrolled to the bottom and realised the theme hasn’t changed since 2010!! Despite some sniffiness from some of my colleagues at the fact my portfolio site is a WordPress blog, I decided to stick with it. It’s done me well this far and why reinvent the wheel.

    Key features of the new site

    • Responsiveness
    • Updated music player
    • Content update

    I’ve managed to get the 3 main objectives achieved in a quick time. And that’s why I love WordPress. Hope you enjoy the new layout and I promise not to leave it so long next time.

  • Deploying to AWS with Phing

    Deploying to AWS with Phing

    After a recent switch to Amazon Web Services, I thought updating my Phing build XML would be a straightforward task. It wasn’t. There weren’t a lot of resources out there for this particular scenario so I decided to write this blog piece.

    AWS comes with good security out of the box. This is obviously a good thing but it does require a bit more thought when setting up your Phing build file.

    Filesync
    During the process of setting up your micro instance, you will be prompted to create an SSH private key which you can download. Put this file somewhere safe and ensure you update the permissions.

    chmod 644 mykey.pem
    All deployment will be done using the ec2-user user. So to save frustration ensure that this user has the write permissions on your target directory (on your target box).

    Where my file sync previously prompted for a password the identityfile parameter automatically connects to instance.

    <filesync
    sourcedir="${source.path}"
    destinationdir="${target.user}@${target.host}:${target.path}"
    verbose="true"
    checksum="true"
    excludeFile="${exclude.file}"
    identityfile="${source.identityFile}" />
    SCP/SSH
    You would think this would be the same as filesync. Unfortunately not. This requires you to create a public key using your private key. From the private key location run the following.

    ssh-keygen -f mykey.pem -y > mykey.pub
    Now in your build XML add these parameters

    <scp
    username="${target.user}"
    privkeyfile="${source.identityFile}"
    pubkeyfile="${source.pubIdentityFile}"
    host="${target.host}"
    todir="${target.path}/mytargetpath"
    autocreate="true"
    file="${source.path}/local.txt" />
    You should be good to go. Hope this is useful.

  • My Full English – A new beginning

    My Full English – A new beginning

    Making the leap into a complete rewrite can be a difficult one. If you can afford the time it takes and the pros out way the cons then go for it. I’ve been busy working on the latest version of my full English. In my next few blog posts I’m going to go through the process I went through from conception to delivery.

    The latest version of MFE3 is now available. Although nothing special to look at, it does at least allow the same functionality on mobile as it does on desktop devices. Just writing the previous sentence justifies to me all the work I’ve put in to completely re-writing the previous version.

    So what was wrong with the previous version?

    As a developer, you build things with the knowledge you have at the time. When we kicked off version 2, a fully functioning site on mobile was only really ever a side thought. The site was built on a custom framework I had built from scratch which I called Mastersolution. Despite the cool name, the framework was very unloved. It was basically a bespoke MVC framework using Smarty as the template engine. When we completed the desktop version we thought ‘oh we had better do a mobile version’. A quick redirect with device detection took you to the ‘mobile’ version. All you could do is find venues near you and get directions to those venues. The functionality to add new venues and reviews just wasn’t available? This sucked.

    So what did the new version have to do?

    I set out clear goals and objectives with the new version of my full English.

    1. I would use the new version as a vehicle to learn as many new technologies as possible
    2. I would concentrate on MFE until I have at least 100 reviews added (hopefully not just by me although 100 full English breakfasts do sound tempting)
    3. The same functionality should exist on the desktop and mobile versions of the site

    What were the initial decisions?

    Framework

    I decided that it was time to move with the times and move to either Zend 2 or Symphony. A similar debate was happening at work at the time. And Zend 2 was decided as the way to go.

    Responsiveness

    I had decided that Twitter bootstrap was the best way to go. I had used it before, and as a ‘backend’ guy I loved how easy it was to make things look nice.

    What next?

    So I was all set for my journey into the unknown. See how I get on in the next blog piece!

  • PHPUnit Dramas

    A frail PHPUnit suite is one thing, but one that completely crashes MySQL is something else entirely!

    I wanted to do a quick blog as this problem isn’t well documented and I want to save people the same pain I went through.

    The problem manifested on a rather large suite of tests with a dedicated MySQL instance. When running the suite we were getting ‘database gone away’ errors in our DB unit tests. Our first thoughts were that it was potentially an issue with our out-of-date version of MySQL. Upon investigation, though it appeared the problem could be replicated and indeed fixed.

    The problem seemed to be a number of things.

    1. Multiple table creation scripts for the same table (I know)
    2. Mixing up engine types for tables within the same database
    3. Having MySQL comment blocks in the table creation statements
    4. The use of set foreign constraints statement

    After much pain, the suite was eventually restored to working order. The lesson learnt was to centralise all of the DB unit table creation scripts. This ensures 1 point of entry for changes and debugging.

  • Innovation

    Innovation

    How do I innovate? Do I need to invent something new? How do I measure success?

    As a developer, I’m often looked upon to use technology to improve processes. This to a degree is innovation but you don’t necessarily need IT solutions to innovate something. You just need a good imagination.

    “Imagination is more important than knowledge. For knowledge is limited to all we now know and understand, while imagination embraces the entire world, and all there ever will be to know and understand.”
    Albert Einstein

    Often when I oversee a process it’s easy for me to offer suggested improvements mainly because I’m neutral about it. I bring an outsider’s perspective. Becoming too close to any system can lead to not seeing the wood for the trees. I’ve compiled a simple suggested list of things to do which could help define your next project. By looking at something that needs improving you can follow the list and hopefully identify how to innovate it.

    1. Issues with the current process
    Make a list of every single bugbear you have with the existing process. Anything that is causing the process to be slow or inefficient. Every small thing no matter how trivial is worth noting down. Sometimes the small things are the quickest things to fix and have a larger positive impact than you may think.

    2. Goals of the new process
    What are the ultimate measurable goals that can be used to assess the success of the new process? Some examples may be the time to process a record, the number of people required for the process and the cost to run the process. Make sure you mark down the values of the current system so have something to measure against.

    3. Forget everything you know
    If you were to start again today, how would you set up the process? Think in terms of ultimate solutions. Don’t think about any constraints, just consider a perfect world and a perfect system. Does the new system avoid the issues listed in part 1? Good, then you’re ready for step 4.

    4. Feasibility
    Carry out a feasibility study to see how much of the ultimate solution is possible. Looks at budget and time restraints. Think about the downtime of existing systems and how you can deploy the new solution.

    5. Build
    I would recommend using an Agile approach in delivering the solution. Aiming to get quick wins out there into the real world ASAP. Look at 3rd party solutions to hit the ground running. Don’t try to reinvent the wheel. By introducing these changes quickly you can get buy-in from the users.

    6. Assess
    Once you’ve completed the changes that budget and resource has allowed, take a look at your initial goals. Did you hit most of them? Yes, then it was a success. Cross-reference your ‘perfect solution’. Maybe you already have an idea about your next project may be.

    Processes, technology and requirements are always in constant flux. You should look to re-assess any system at regular intervals to see if you can make further improvements. Remember 3rd parties may be able to help in the future if they can’t at the moment.

    I hope you find this useful.

  • Essential LAMP tools

    Essential LAMP tools

    For the last time am I going to utter the words ‘I wish I’d found this earlier’. There are so many great tools out there for developers that it can become overwhelming. I used to just accept the flaws in my text editor or database client. Often telling myself ‘it’s better the devil you know’. Recently, however, certain frustrations have caused me to reassess the tools I am using. At this current point in time, I have reached a state of LAMP developer nirvana! This article is to help you reach the same higher state of consciousness!

    OK, few points to know before we kick off. I am very tight with my cash. Despite this, I am a keen Apple advocate (maybe the two traits aren’t entirely unrelated). The tools I’ll talk about will be for OSx but I’ll try to mention some Windows tools along the way.

    MySQL
    Free GUIs for MySQL have come a long way since the free ones provided by MySQL. The latest incarnation is Workbench. The killer functionality here is the ERR modelling creation tool. You create your database, tables, initial inserts and relationships. Hit forward engineer and hey presto! Your schema is all up and running. And you also have a fully documented schema. As a habit, I try to add comments to all tables and some columns. This diagram process is one of my first tasks for any new project. The query editor for Workbench doesn’t include a decent auto-complete functionality. An essential feature if you ask me. For this try Sequel Pro. It’s snappy, free and highly intuitive.

    Text editor
    OK, the most delicate of subjects. I’ve never really used a full IDE to develop but I hear Eclipse is the front-runner on this. I had been recently using Komodo edit which is a great free text editor. My highlight feature on this is the scanning of other PHP DocBlock comments. Within your current file, it sees you’re calling a method from another class (in another file) and tells you what parameters the class expects. Pure black magic. My only gripe with the editor was that the shortcuts weren’t intuitive and some just didn’t work. I’d found Textmate was better for this so gave Textmate 2 a try. They’ve really dropped the ball on this. Textmate 2 is awful! That’s when I found Sublime Text. Sublime Text will cost you around £45 but it’s worth every penny. Once package control is installed you have a world of useful plugins at your fingertips! For Windows, I always find Notepad++ a decent free editor.

    Source control
    I’ve used CVS and Subversion. Both of which are quite similar. Recently, I’ve made the switch to GIT and I am amazed by it! I’ve implemented a GIT flow approach which means I have a solid workflow which doesn’t interfere with other feature branches on the same code base. Switching to different features is so easy and still makes me go ‘wow’ when I do it.

    Linux/Apache
    I work on the mac mainly as it’s a UNIX-based operating system. This allows me to use a lot of the Pre-built commands available with my personal/work Linux servers. The terminal app is very good on the Mac and likewise Putty on Windows is also very good. For package installation on the Mac Macports is essential and for Linux Yum is superb!

    I guess that’s it for the time being! To take the pain out of setting up your LAMP environment on your mac I would highly recommend Zend’s community server.

    Next time I’ll discuss my project process methodology.

  • My Full English Launched!

    My Full English Launched!

    Last Saturday was a momentous day. It marked the launch of My Full English. The site aimed at the connoisseurs of the decent fry up.

    The idea came about after a recent away trip to Southampton where we needed a greasy hang over cure. We had to actually interact with a human being to find out where we could get one! Can you believe that!

    This is a joint venture between myself and Shane Exley. It uses Google maps to allow users to add their venues which can be anything from a restaurant to your local Cafe. Once a venue is added people can add their personal breakfast reviews along with uploading a photo. The mobile version of the site even allows users to find directions to a venue of their choice.

    We are hoping to get a 100 reviews by the end of next year so please get eating.

    Please let us know your thoughts by adding a comment on the site. Enjoy!

  • RoR Active Records in PHP

    As a developer, you can become a little complacent with the framework and language you’re using. You’ve invested a lot of time in getting yourself up and running so why look at other solutions to problems you’ve already solved? Well, there is more than 1 way to skin a cat, and the other methods out there may mean you can skin 10 cats for every 1 of yours. OK, I’m going to stop with this horrible analogy. This post has come about because I was inspired by the Active Record methodology involved in Ruby on Rails and I wanted to create a PHP version.

    Let’s start with a few examples of active records in RoR.

    
    user = User.find_user_by_email('myemail@gmail.com');
    
    user.name; # Me
    user.age; # Thirty (Just)
    
    user.new(:name => "David", :surname => "Hasselhoff" : occupation => "Life Guard");
    
    

    If you’re not familiar with RoR you will probably be impressed with how easy it is to create new records and generate the setters and getters. If you are familiar with RoR please excuse any syntax errors as I don’t actually write in Ruby.

    My current framework is a custom setup very similar to the CodeIgniter framework. All the data access is done via 2 files, the data access object, and the access object. I have a script which is an automatic code generator that can create both of these files using the database and table names. The data access object is the parent of the access object, this allows any custom queries to be managed by the access object and direct table access to be carried out by the data access object. Therefore for each table in the database, we need both of these files, this can start to add up fairly quickly. Just to highlight this setup…

    Data Access Object

    
    <?php
    
    class DAO_User {
    
     // Private properties
     protected $db;
     protected $db_name = "my_database";
     protected $table_name = "user";
    
     // Table specific
     protected $first_name;
     protected $last_name;
    
     /*
     * Constructor
     */
     public function __construct () {
         $this->db = new Database();
     }
    
     /*
     * Getters
     */
     public function getFirstName(){
        return $this->first_name;
     }
    
     public function getLastName(){
        return $this->last_name;
     }
    
     /*
     * Setters
     */
     public function setFirstName($val=''){
        $this->first_name = $val;
     }
     public function setLastName($val=''){
        $this->last_name = $val;
     }
    
     /*
     * Processes
     */
     public function createRow () {
    
     # Insert code
    
     }
    
     public function updateRow () {
    
     # Update code
    
     }
    
     public function deleteRow() {
    
     # Delete code
    
     }
    
    }
    
    ?>
    
    

    Access Object

    
    <?php
    
    require_once('class.DAO.my_database.user.php');
    
    class AO_User extends DAO_User {
    
     /*
     * Return a list of values
     */
     public function findUserByName ($name="dave") {
    
     # Query code here
    
     }
    
    }
    
    ?>
    
    

    These classes are used by the Models for the framework to interact directly with the database. This is a very clean way of dealing with access to the database but the number of files can get quite large and the code in the model is quite clunky. Issues can also arise when the database is changed or when variables aren’t passed for certain fields (Do we set it to blank or keep the existing value for this field?). I decided to try and create a new PHP class based on the RoR active records approach.

    A strange approach to some maybe, but I decided to write the code to use the class first and then tried to get the class functioning around it. Here is the code…

    
    <?php
    
    class data_access_test {
    
     public function index() {
      $ao = new DataAccess('my_database','user');
      print $ao->find('1')->first_name(); # Expected output dave
     }
    
    }
    
    ?>
    
    

    OK, so in case you are not clear on what we are saying here. We start by initialising the class with 2 variables. The first is the name of the database and the second is the table we wish to access. We then call the find method and pass a specific id of a row in the table. By chaining the methods we are also able to call the first_name method which without a variable assumes we wish to get (if we passed a variable it would assume we wish to set). OK, so now it’s time to get started on the class itself.

    
    private $_dbl; # Your database class to actually talk to the DB
    private $_database; # User defined var for the DB we need to look at
    private $_table; # User defined var for the table we need to look at
    private $_internal_errors = array(); # Store any errors in setting up object
    private $_primary_key_fields = array(); # Primary key holder for $database.$table
    private $_set_primary_key = false; # False by default, if 2 fields create key then we set to true
    private $_fields; # Holder of the available fields in our table
    private $_type; # As above, see desc query on your table for example of values
    private $_null; # See Above
    private $_key; # See Above
    private $_default; # See Above
    private $_extra; # See Above
    private $_row_data; # Holder of all of this row's data
    
    

    To start with we define all of the variables that our class will need to function correctly. Read the comments for more detail on what each variable will be used for. Now, for the nitty-gritty of the object which will happen at the point of initialisation.

    
    /*
     * Set globals to define host user and password
     */
    public function __construct($database = '', $table = '') {
      $this->dbl = new Database;
    
      if ($database != '' && $table != '') {
        $this->_database = $database;
        $this->_table = $table;
    
        if (!$this->setTableData()) {
          $this->_internal_errors[] = 'Database and table not recognised';
        }
      } else {
        $this->_internal_errors[] = 'Require database and table at initialisation';
      }
    }
    
    /*
     * General
     */
    private function setTableData() {
      $sql = "SHOW COLUMNS FROM " . $this->dbl->mysqlEscape($this->_database) . "." . $this->dbl->mysqlEscape($this->_table);
    
      list(
        $this->_fields,
        $this->_type,
        $this->_null,
        $this->_key,
        $this->_default,
        $this->_extra
      ) = $this->dbl->returnRows($sql);
    
      if ($this->_fields) {
        $primary_count = 0;
    
        // Set the primary keys
        foreach ($this->_fields as $key => $value) {
          if ($this->_key[$key] == 'PRI') {
            $this->_primary_key_fields[] = $value;
            $primary_count++;
          }
        }
    
        if ($primary_count > 2 || !in_array('auto_increment', $this->_extra)) {
          $this->_set_primary_key = true;
        }
    
        return 1;
      }
    }
    
    

    The construct of the class sets up our database object so that we can talk to the database. We check that the user has passed the 2 required variables, if they haven’t we assign an error message to our internal errors variable. I find it useful to have an internal errors variable that way if there are any issues you can simply check this variable to diagnose the problem. If we have both the database and table we can go about setting up our object, this is all done in the setTableData method.

    This method begins by doing a DESC query on the table. We use the return variables to set our fields, type, null, key, default, and extra properties. The final thing this method does is check the primary keys. I had a number of problems with my original DAO files when I tried to generate the files for a table with multiple primary keys. By setting our primary_key_fields variable we can make a decision as to whether to allow the user to set and get this variable. The decision I’ve made is you cannot set the primary field if there is only 1 primary key. If there are more primary keys then I set my set_primary_key flag to true to indicate that we can allow this field setting.

    So how do we set and get variables on the fly when we don’t have the methods already set? Well, we can do this by using the __call method.

    
    /*
     * Use name to check what field we are setting or getting
     */
    public function __call($name = '', $arguments = '') {
      // Only proceed if there are no internal errors
      if (count($this->_internal_errors) == 0) {
        // Check that this is a valid field
        if (in_array($name, $this->_fields)) {
          // We have an argument so set, otherwise get
          if (!empty($arguments[0])) {
            if (!in_array($name, $this->_primary_key_fields) || $this->_set_primary_key === true) {
              if ($this->checkFieldDateType($name, $arguments[0]) == 1) {
                $this->setData($name, $arguments[0]);
              } else {
                $this->_internal_errors[] = $name . ' cannot be set as it fails the type check';
              }
            } else {
              $this->_internal_errors[] = $name . ' cannot be set as it\'s a primary key';
            }
          } else {
            return $this->getData($name);
          }
        } else {
          $this->_internal_errors[] = $name . ' is not a recognised field in this table';
        }
      }
    }
    
    

    I’ll now talk you through this method and then show you the get and set methods. The first thing this method does is to check the internal_errors property, we don’t want to try and set something if we’ve had a problem setting up the object. We then check to see if an argument has been passed, if it has then we can assume the user wants to set a variable. We check whether the method name is a primary key and whether we can set it. If allowed we finally check the argument against the data type set for this field (I won’t go into detail about this method but it’s a good way to ensure data integrity by ensuring it matches the type of data acceptable for that field) and then pass to our set method. If there are no arguments then we simply send it to the get method.

    
    private function getData($key = '') {
      return $this->_row_data[$key];
    }
    
    /*
     * Setters
     */
    private function setData($key = '', $value = '') {
      $this->_row_data[$key] = $value;
      return $this;
    }
    
    

    Fairly straightforward forward huh? Our set method simply uses the name passed to the __call method (aka table field) as the key for our internal variable _row_data. The return $this allows us to chain methods in this object. The get method is even more straightforward and just returns the value currently assigned to this key (aka table field). Ok, so if we look back at our original code we still need to define our find method.

    
    /*
     * Find record using unique id
     */
    public function find($record_id = '') {
      if ($record_id != '' && count($this->_primary_key_fields) == 1) {
        $sql = "SELECT * 
            FROM " . $this->dbl->mysqlEscape($this->_database) . "." . $this->dbl->mysqlEscape($this->_table) . " 
            WHERE " . $this->_primary_key_fields[0] . " = '" . $record_id . "'";
    
        $results = $this->dbl->returnRows($sql, 'non_list');
    
        foreach ($results[0] as $key => $value) {
          if (!is_numeric($key)) {
            $this->_row_data[$key] = $value;
          }
        }
      }
      return $this;
    }
    
    

    Our find method checks that the record id is available and that there is only 1 primary key. A query is then generated to return all of the information in that table row. The columns of the rows are used as keys in our internal _row_data variable and the value is the cell data. When we now call a get on any of the columns we will get the data we require…bingo!

    My class also has methods for creating new rows and updating rows. If you’ve come this far I’m sure you can figure these out for yourself. This class is far from perfect but it’s a good start. One of the problems you may have already noted is what if we want to set an empty value? Also what if we want to return multiple rows? If you have any ideas on it please share them with me 🙂