Sunday 9 December 2012

PhpStorm, Symfony 2 and GIT

I've recently started a new job, and after 2 years of using Ubuntu I'd had enough and wanted to try out Windows 7. Basically, I got sick of running two operating systems, and as my macbook is getting a bit long in the tooth I decided to try and get everything working under Windows 7. These instructions worked for me.
  • Install wampserver2
  • Download and install Composer using the Windows Installer option.
  • Download and install GIT (only if you're using it, but at some point in your development life you will be, so you may as well install it now
  • When installing GIT, make sure to select the middle option, that allows GIT to be run from the command line (the cli in some documentation)
  • Download and install the trial version of PhpStorm. You may not like it so no point paying until you have trialled it.
At this point you should have a working version of everything you need. Here's how to test it, to make sure everything actually works. 
  1. Use Composer to install the Symfony 2 framework. I'd highly recommend that you do this in the wamp/www folder to save yourself time.
    • On the Symfony website, they say to use composer.phar . It should be updated to read "composer". Composer installed a .bat file that will do all the hard work for you.
    • The "path/" in the command is the folder to install it into. If you're in the www folder, use "symfony" or something similar.
    • The full command to run from the c:\wamp\www\ folder is now "php compose create-project symfony/framework-standard-edition symfony/ 2.1.4"
  2. If you have yet to install GIT, you won't be able to install Ascetic. If GIT is installed correctly, then we also know that GIT is installed and working correctly!
    • If it failed at this point, then go back and install GIT. Then from the command line, run "composer update" in the c:\wamp\www\symfony\ folder.
    • This will read the composer.json file and download/update components. Most importantly, it will add in the missing components such as Ascetic as the git command is now available.
    • If for some reason that didn't work, close the command prompt window and try this again in a new one.
  3. Open PhpStorm
  4. Create a project, from existing sources, where we just installed Symfony 2 to. Select the bottom option, as the files are local and we don't yet have a server set up. 
  5. You should get a few "error" messages, as this is the first time you've worked with PhpStorm. It'll prompt you to say you're using the Symfony 2 framework. Follow the prompts to fix this.
  6. It will probably also say GIT is not installed. It's wrong, but click fix button.
  7. In the dialog, you'll see it's looking for "git.cmd". Change that to "git". Click the test button to prove it worked.
  8. Now, open the .gitignore file in PhpStorm
  9. At the bottom, add the lines ".idea/*". This folder is where PhpStorm keeps a record of stuff about the project, and we do not want this committed.
  10. Right click the name of the project in the left hand panel, and select GIT -> Add. This should add our entire directory to GIT. I like to do this so I can always tell what files I have played around with whenever I'm doing anything.
  11. Next, right click again, GIT -> Commit Directory. Now that we've added the files to the list of files to be indexed by GIT, we need to commit the files to the repository. (note, that is a very simple explanation of what a VCS does)
  12. Double check the .idea folder is ignored (i.e. There are no files to be committed from that directory)
  13. Mouseover the commit button, and select commit.
  14. I tend to ignore the review option but you may want to have a look to see what errors/todo's have been left in the code.
One last thing that you may find useful. Run a "composer update" from the root directory of the project. Changes are the version of Symfony 2 you've downloaded is slightly out of date, and this will go through and check everything.

That's it. I've assumed you're comfortable with the command line. If you're not, well, there's no time like the present to learn!

Leave a comment if I've missed a step or something isn't clear :)

Wednesday 17 October 2012

LessCSS Auto-compile in PHP

I don't have the attributions for where this comes from but it works perfectly for me.

Include this code in your main template file, so it gets run every time.

PseudoCode: If we're on a development server, re-compile the css.


// Auto versioning using PHP, only when on localhost and debugging
if ($this->debug) {
    include($_SERVER['DOCUMENT_ROOT'].'/includes/autoCompileLess.php');  
    auto_compile_less($_SERVER['DOCUMENT_ROOT'].'/css/less/style.less', $_SERVER['DOCUMENT_ROOT'].'/css/styleCompiled.css');
}

This is the code for the autoCompileLess.php. It checks a cache file, and if that file is newer than my main LessCSS file it'll use the cache rather than re-compiling.

PseudoCode: Check the modified times of the cached compiled css, and if that is newer than the main less css file use the cache. Otherwise recompile all the less.


require 'lessc.inc.php';

function auto_compile_less($less_fname, $css_fname) {  
    $cache = $less_fname;
   
    // We may want to load from the cache
    $cache_fname = $less_fname.".cache";
    if (file_exists($cache_fname)) {      
        // Use the cache if the filetime is newer
        $cacheTime = filemtime($cache_fname);
        $fileTime = filemtime($less_fname);
        // If I managed to read both and the cache is still relevant, use it
        if ($cacheTime && $fileTime && $fileTime < $cacheTime) {
            $cache = unserialize(file_get_contents($cache_fname));
        }
    }

    $new_cache = lessc::cexecute($cache);
    if (!is_array($cache) || $new_cache['updated'] > $cache['updated']) {      
        file_put_contents($css_fname, $new_cache['compiled']);
        file_put_contents($cache_fname, serialize($new_cache));
    }
}

A bit of googling should get you all the necessary files you need. Perhaps this site, http://leafo.net/lessphp/, would be a good place to start.

Happy coding!

Friday 20 July 2012

Code Readability

Or why I use ternary operations but never single line if statements.

This is a massive issue on collaborative projects. And since virtually every single piece of code you use will need to be modified / understood by someone else in the future, in my opinion everything you write should emphasise the readability rather than functionality.

Of course there will always be projects where speed is important, and you want to use the data structure that is fastest / most efficient.

As a professional software engineer (even if it is "just" websites) I am constantly working with other people's code. And it frustrates the hell out of me that people write code that is just so hard to understand.

A ternary operation is fairly trivial for any professional to understand. Even there though, the use of a variable name that explains where it comes from would be so handy!

One thing that annoys me though is single line if statements. Most IDE's allow you to format everything properly according to your conventions (we use Zend), and if everyone follows those it makes it much easier to follow the code when you have to fix a bug. But scanning code by eye for a line (I'm lazy like that) is made so much harder with single line if statements. Especially when you're checking for a value like: $_SESSION['carhire.search.dropoff_location'] .

The number of studies that have been done on the width of columns for readability is astonishing. Made your code more readable by using the following format always:

if (statement) {
    then do this
}

And comment your bloody code or I will curse you forever.

Saturday 14 July 2012

Zend Form, and auto height of a textarea

Zend framework has it's uses. But gee it can be a pain at times.

If you don't have access to the decorators of the form, and you want to style your text areas better, this snippet should come in handy. Stupid scroll bars.

var textArea = "";
jQuery('textarea.info').each(function() {
                    textArea = jQuery(this);
                    textArea.removeAttr('rows');
                    textArea.removeAttr('cols');
                    textArea.css('height', this.scrollHeight + 'px');
                });

Pimcore, Helpers and Forms

It's taken me a while to get around to this, but I'm finally getting somewhere with this. Here's the code I've got. Underneath is an explanation of everything.

I've assumed you're using the formbuilder plugin for Pimcore with this code.
    
        
    public function init()
    {        
        parent::init();
        $this->_helper->addPath(PIMCORE_WEBSITE_PATH . '/views/helpers/cru', 'Website_Helper_Cru');
    }
    
    public function formpageAction()
    {
        // Make sure I want to display the form
        // the useForm property is a checkbox, so I always get true/false
        if ($this->document->getProperty('useForm') && !empty($this->document->getProperty('formName'))) {
            // Put everything in a try/catch statement, as there is some buggy code here
            try {
                $this->formHelper = $this->_helper->getHelper('Forms');
                $form = $this->formHelper->getForm($this->document->getProperty('formName'));  

                // Do I have a submitted form to worry about?
                if ($this->getRequest()->isPost()) {
                    if (!$form->isValid($_POST)) {
                    }
                }
                // We are going to display the form
                $this->formHelper->setDecorators($form, 'default');
                $this->view->form = $form;
            } catch (Exception $e) {
                // Log the error if I had one
                Logger::error($e->getMessage());
            }
        }
        $this->enableLayout();
    }


Ok. This is (hopefully) obviously all inside your controller.

When the controller is initialised, add an extra path to the helpers paths. Now, instead of just looking inside Zend, my controller will now look for helpers in the /website/views/helpers/cru/ folder.

Now, in my document that is using the formpage action, I look for 2 properties. A checkbox called useForm (ticked on) and a formName (I have to know which form to load!).

If both of those properties exist and have a value, add on a formHelper to the action so it can do things.

This class is called Website_Helper_Cru_Forms and the filename is Forms.php. I'm sure you can figure out which folder it's in.

I haven't fleshed out the validation of the form. I imagine I'll end up adding something in the formHelper class to do this.

I add on the decorators using my helper. I haven't yet got a good way of doing this, I plan on using .ini files but I'll get around to this later.

And finally, add the form to the view. In the view you simply call echo $this->form to print it out. If you've set up the decorators and validators correctly everything displays in a nice pretty format :)

I've also wrapped the whole thing in a try/catch statement. There are quite a few ways this could break at present as I don't do much error checking yet. That's another thing on the to do list.

Let me know of any obvious errors you can see with this code in the comments below. I hope this helps somebody!

Wednesday 21 March 2012

Beware easy shortcuts

If you need to replace a character, make sure you replace it with the correct character!

I recently made the mistake of replacing a comma (,) with &comma; That isn't the correct ascii character. &#44; is.

And because I do my IE testing last, I didn't pick it up. Just thought it'd be a good heads up for anyone who didn't realise it either.

Tuesday 6 March 2012

Validating an email address in PHP

Just a little post, because most of the top Google results point to old pages that aren't correct.

Basically, I wanted to validate some input to see if it was a valid email address. Rather than rely on a regular expression, I knew there was a better way of doing it. In PHP at least.

So, the function you're looking for is filter_var(). If you're doing it with $_POST or $_GET you can instead use filter_input().

In my case, it's verifying that an API is providing me with a valid email, as somebody at the other end likes to chuck in "unsubscribed" to the email field. So the code looks similar to this.

if (false === filter_var($valueToCheck, FILTER_VALIDATE_EMAIL) ) {
    // This is *not* an email address
} else {
   // This *is* an email address
}