Doctrine convention adherence leads to much simpler entity classes, no picky join column specification. A standard bi-directional one-to-many join becomes simply:

<?php
use Doctrine\Common\Collections\ArrayCollection;

/** @Entity **/
class Product
{
    /**
     * @OneToMany(targetEntity="Feature", mappedBy="product")
     **/
    private $features;

    public function __construct() {
        $this->features = new ArrayCollection();
    }
}

/** @Entity **/
class Feature
{
    /**
     * @ManyToOne(targetEntity="Product", inversedBy="features")
     **/
    private $product;
}

Nice and straight forward.

Of course, if you do want to specify the join column manually, it would be:

/** @Entity **/
class Feature
{
    /**
     * @ManyToOne(targetEntity="Product", inversedBy="features")
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
     **/
    private $product;
}

The getters & setters can be auto-generated with the following calls from the server’s command line:

app/console doctrine:generate:entities AppBundle:Product
app/console doctrine:generate:entities AppBundle:Feature

Alternatively, modern IDE tools like PHPStorm can also generate the standard for you. Chaining is a great feature to encourage on setter methods, simply return $this after setting an entity property.

Advertisements

Using Twig’s default() filter to avoid “Variable some_var does not exist”

References to undefined variables are a common cause of web pages not displaying when using Twig. A simple mention of an undefined variable can cause 500 errors:

{{ some_var }}

Variable some_var does not exist in..

Whilst turning strict_variables off in the twig config will obviously hide the error and is best for production, during development hiding errors can ultimately making spotting bugs harder. A better solution is using Twig’s default() filter like so:

{{ some_var|default("") }}

This will print the variable if it exists or nothing if it is not defined.
For if statements and loops, there are 3 choices:

  1. The default() filter:
  2. {% if some_var|default(false) %}some text{% endif %}
  3. The fine grain but hideously verbose control of defined:
  4. {% if some_var is defined and some_var %}some text{% endif %}
  5. The empty filter:
  6. {% if some_var is not empty %}some text{% endif %}

There are also lots of other useful tests, filters and functions that Twig provides out of the box, check out their documentation pages for more info. Hope this helps. Please like and share if it does ūüôā

AngularJS IE11- (ONLY) SyntaxError on ng-view div when opening WebSockets socketHelper

A strange error cropped up today. The Angular 1 JS WebSocket() based application worked fine on all browser exception Internet Explorer 11. The error reported was as such:

SyntaxError <div class="ng-scope" ng-view="">
{
 ABORT_ERR: 20,
 code: <Permission denied>,
 constructor: { },
 ...

Far from actually being a syntax error, the actual cause turned out to be a missing / (forward slash) in the WebSocket connection creation call to:

conn = new WebSocket('ws:/localhost:3001');

This of course should have been:

conn = new WebSocket('ws://localhost:3001');

Only Internet Explorer 8 – 11 experienced this error. Whilst there is a definite syntax error in specifying a websocket url,¬†it’s hard to tell if the error is¬†perhaps bubbling up or causing an¬†unrelated issue further along¬†the command sequence.

Which Symfony Version number?

The Symfony console provides a -V option. This can be handy for quickly finding out which version of Symfony¬†a system is¬†running but it has moved location a bit over the years (note the¬†uppercase -V or use –version):

$ php bin/console -V
Symfony version 3.1.2 - app/dev/debug

If this produces a bunch of errors about autoload.php then you need to run composer install to install other required parts of Symfony. Whilst if you receive a command not found error then try:

$ php app/console -V
Symfony version 2.7.10 - app/dev/debug

If still a command not found error then try:

$ php lib/vendor/symfony/data/bin/symfony -V
Symfony version 1.4.20

In all versions, running console without -V will produce a long list of all the commands available, along with the version info. This is very useful and really good regular learning exercise, the options really show how Symfony works.

As we can see, the console command moved to the project folder’s bin/ folder as of¬†version 3.0 in Symfony2 versions the console command lived in the project’s app/ directory, whilst¬†if only lib/vendor/symfony/data/bin/symfony exists then you’re using Symfony version 1 (now an obsolete legacy platform)!

Modify XML files using XSLT

XSLT can be great for transforming XML files, especially where information is stored in attributes thanks to the @ operator.

If you have a xml file like:

The elements can be combined into one with multiple attributes, ie:

<collection>
<field row0=”Value0″ row1=”Value1″ row2=”Value2″ row3=”Value3″ row4=”Value4″ row5=”Value5″ row6=”Value6″ row7=”Value7″ row8=”Value8″ row9=‚ÄúValue9‚ÄĚ></field>
</collection>

using the following XSLT:

A web search will reveal many handy online testing tools, such as:
http://xslt.online-toolz.com/tools/xslt-transformation.php

Additionally, many IDEs now come with tools and verifiers build in to facilitate XSLT translation of XML files. As much as we prefer using JSON where possible these days, XSLT can adds an extraordinary amount of functionality and flexibility to XML files.

General directions in online learning

Since its beginnings, e-learning has always been an area where technology can thrive and improve upon an already progressive area of learning. With the help of laptops, tablets and smartphones, the area of e-learning has never looked so promising, so before the new school year begins, let’s look at the top 3 new structure and ideas to look out for in e-learning platforms this semester.

  1. Cloud based technologies
    As Cloud based technologies become more and more popular, many businesses and organisations are starting to see the benefits of using this technology to train their students and employees. Thanks to its accessibility, security and cost-saving properties, the Cloud is the obvious choice for businesses looking to remotely transfer content and collaborate with colleagues online.
  1. Mobile learning
    With the ability to learn from absolutely anywhere, mobile learning or mLearning, is probably the fastest growing area of e-learning out there. Aside from the capacity to use your smartphone or mobile device to browse educational websites and use educational software, the mLearning platform is quickly beginning to encompass interactive aspects such as the phone’s accelerometer, compass, gps, camera and audio to make learning even more interesting and accessible.
  2. Gamification
    Having been on the e-learning horizon for a few years now, this year is proving to be bigger than ever when it comes to the gamification of learning. Making it much more fun to learn, and distancing itself from a more traditional style of lecture, gamification turns boring old tests into exciting new challenges that the learner can solve at their own pace.


E-learning is an exciting and innovative way for students of all types and abilities to learn, and in the coming years it is likely to become totally unrecognizable from what it is today, but until then, these are the key trends to look out for in the e-learning world.

Changing the default keyboard shortcut of a Chrome Extension

Changing the keyboard shortcuts of some Chrome web browser extensions can be a pain when the preferences option is non-editable in chrome://settings. A some-what longwinded workaround is to edit the source code of the extension directly. Often this is available on somewhere like GitHub.

To change a Chrome extension keyboard shortcut via its source code, the steps are as follows:

  1. Clone the extension source code to your computer
  2. Open the manifest.json file in the extension’s route directory. Edit or add this section:”omnibox”: { “keyword” : “key” }

Where “key” is the keyboard shortcut key itself. As an fyi, Chrome likes to calls its address bar the “omnibox”

  1. In chrome, go to: chrome://extensions/
  2. Delete the old extension (careful of deleting important data if relevant)
  3. Switch on developer mode in top right of page
  4. Select Load unpacked extension... and navigate to the cloned directory
  5. Verify the extension has loaded in Chrome and works correctly
  6. It is a security risk to browse the Internet with Chrome Extensions developer mode left on. Solve this by packing the extension into a single .crx file (a type of .zip file).
  7. Delete the newly created “unpacked” extension and click Pack extension... (you can sign the file with a .pem key but this is not necessary).
  8. Switch off developer mode in top right of page
  9. Nagivate to the directory above the cloned directory
  10. Drag the .crx file produced in the packing step onto the Chrome window
  11. The new extension should now appear on the chrome://extensions/ page
  12. Verify the correct result by navigating to chrome://settings/ -> Manage search engines...
  13. At bottom of page under “Search engines added by extensions” the keyboard shortcut should be updated and extension only appears once

 

You now have a modified keyboard shortcut for a Google Chrome extension. Some installations may experience problems with the browser disabling the extension unless it is officially released through the store (private repos are available). If the extension is disable then a restart of the web browser usually suffices in making the extension work again.

Checkout Specific Git Branches in Composer.json

Composer allows different branches of a Git repository to be checked out for use as a third party library. To do so first add the git repository to your composer.josn file:

 "repositories": [
     {
         "type": "vcs",
         "url": "git@bitbucket.org:org/repo.git"
     }
 ]

 

Now the repository is known, add the branch to the composer.json require section:

"require": {
    "org/repo": "dev-branch1"
}

 

You can even choose a specfic commit:

"require": {
    "org/repo": "dev-branch1#ec457d0a974c48d5685a7efa03d137dc8bbde7e3"
}

 

Examples

As explained on the getcomposer.org website, login details can be provided to access private repositories. For example, using ssh:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "ssh2.sftp://bitbucket.org",
            "options": {
                "ssh2": {
                    "username": "composer",
                    "pubkey_file": "/home/username/.ssh/id_rsa.pub",
                    "privkey_file": "/home/username/.ssh/id_rsa"
                }
            }
        }
    ]
}

 

Or using an SSL certificate key:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "vcs",
             "url": "https://bitbucket.org:org/repo.git",
            "options": {
                "ssl": {
                    "local_cert": "/home/username/.ssl/composer.pem"
                }
            }
        }
    ]
}

 

Or using HTTP Basic authentication:

{
    "require": {
        "org/repo": "dev-branch1"
    },
    "repositories": [
        {
            "type": "vcs",
            "url": "https://username:password@bitbucket.org/com/repo.git"
        }
    ]
}

 

This provides fairly good SSL encrypted security,¬†although it’s a good idea¬†to remove the username & password credentials from the Git repository and instead place them in a file named auth.json within the COMPOSER_HOME directory, as such:

{
    "https://bitbucket.org": {
        "http-basic": {
            "bitbucket.org": {
                "username": "username",
                "password": "password"
            }
        }
    }
}

 

You can also specify HTTP headers directly, which enables our preferred method for stateless authentication, JWT (Java Web Tokens):

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://bitbucket.org/com/repo.git",
            "options":  {
                "http": {
                    "header": [
                        "authorization: authenticated.jwt.token"
                    ]
                }
            }
        }
    ]
}

 

Conclusion

As can be seen from the above examples, Composer enables a flexible range of options in regards to the selection and integration of Git repositories along with their respective branches and versions.

Make mysql databases default to UTF8

By default MySQL databases are created with one of the latin charsets – as if globalization never happened – and just asking for future internationalization and charset issues. UTF8 is the generally accepted way forward (for now) and there are few occasions that it isn’t the best charset to use.

Ideally, some sort of framework config system will take care of this but otherwise for existing MySQL databases, you can find out their current charset by entering the MySQL terminal and typing:

SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = "myDatabase";

The problem is changing the character set of an in-use databases can be troublesome and you have to remember to specify UTF8 as the charset every time you create a new database. Also many database tools (e.g. PHP’s Doctrine) do not currently support creating a database with a non-default charset.

The best solution is to set the default charset to UTF8 straight after installing mysql and avoid the problems before the occur. This can be done simply by modifying /etc/mysql/my.cnf (note my.conf may be located elsewhere) and adding the following lines to the [mysqld] section:

collation-server = utf8_general_ci
character-set-server = utf8

Then restart the MySQL service:

sudo service mysql restart

Now new databases will now be created using the UTF8 character by default.