Using WordPress efficiently with Capistrano

Hi everybody,

In the previous article here How to use WordPress with Git efficiently , I showed you the best practices when you have to deal with Git and WordPress.

It’s good, but what if you have to deal with multiple environments like “local, staging and prod”? What would be the best deployment procedure?

WordPress is a cms managed essentially through the database, partially with files, and plugins don’t have a repository system like Packagist with Composer or NPM, so hard to deal with third parties properly in all environments, you’ll have to put all the plugins in your vcs (Versioning Control System) or install them manually in all your environments.
And, about the database, it is very difficult (impossible) to manage it through a vcs.

If you didn’t managed yet to work with Git and wp-cli in your WordPress project, please refer to my previous article How to use WordPress with Git efficiently.

To deal with deployments best practices under WordPress, we will use the most famous “Capistrano” adapted for WordPress, link here https://github.com/Mixd/wp-deploy. It’s not really good explained, let me save you some time.

Let’s start:

  1. If Ruby, gem, bundler and wp-cli are not installed in your machine, install them
    apt-get install ruby gem
    rvm gemset use global && gem install bundler
    
    #Now install wp-cli
    curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    chmod +x wp-cli.phar
    sudo mv wp-cli.phar /usr/local/bin/wp
    
  2. Download the github repository on your machine

    git clone https://github.com/Mixd/wp-deploy <YOUR_FOLDER_NAME>
    

  3. Be sure that the owner of the last created folder is not “root”, it will cause you issues with Capistrano and wp-cli. If the folder owner is “root”, change it to any other profile you have.

  4. Install the ruby gems dependencies

    cd YOUR_FOLDER_NAME && bundle install
    

  5. Write your wordpress repository config (with the right branch, mainly development) inside prepare.sh file

    nano config/prepare.sh
    

  6. Automatically pull your WordPress repository inside our main repository, it will be pulled inside a wordpress directory

    bash config/prepare.sh
    

  7. Check that your repository has been pulled inside the “WordPress” directory with the correct branch name

    cd wordpress && ls -al
    git checkout
    

  8. Perfect ! Now let’s configure general settings

    cd ../config && ls -al
    
    #You can look at all the files inside. For general settings we will only use the deploy.rb file
    nano deploy.rb
    
    #wp_user: The username of your WordPress administration user.
    #wp_email: The email address of your administration user.
    #wp_sitename: The site title of your WordPress installation.
    #wp_localurl: The local URL of your site.
    #application: The name of the temporary folder used by Capistrano when deploying the website.
    #repo_url: The SSH URL of the remote repository. Capistrano uses this to clone the repository onto the server.
    

  9. Now let’s fill in database details for all of our environments

    #First duplicate the database.example.yml file and edit it
    cp database.example.yml database.yml
    nano database.yml
    

  10. Alright ! Now let’s configure our deployment environments

    cd /deploy && ls -al
    
    #You must see two files, production.rb and staging.rb, open them and fill in correct informations
    #stage_url: This is the URL of what the website will be under in that environment. This should always have the HTTP protocol (http://site.com, https://site.com, etc etc). You'll need to make sure your vhosts on the server are setup for this URL.
    #server: The IP address of the server to connect to via SSH. Each environment can be on a different server, think staging server vs production server, keeping things nice and compartmentalized.
    #user: The SSH server you'll be using to connect.
    #deploy_to: The folder on your server where the site will reside.
    

You are almost done. You are now on your development branch inside the staging environment, be sure that you have a working production environment.

If you already have a database for your project, install it manually, if not, you can deploy your project locally.

bundle exec cap staging wp:setup:local

#Then check your database

Your purpose now is from staging to push modifications on production and rollback immediately if something is going wrong. Never push directly from local environment to production, and, like it is done for WordPress, you can easily push/pull/backup your database from any environment to any other.

These are the list of all commands available.

deploy                   # Deploy the project to a given environment
deploy:rollback          # Rollback to a previous deployment.
wp:setup:local           # Setup your project locally
wp:setup:remote          # Setup your project on a remote environment
wp:setup:both            # Setup your project locally and on remote environment
wp:set_permissions       # Set 666 permission for `.htaccess` and 777 for `uploads` on remote environment
wp:core:update           # Update WordPress submodule (core) locally.
db:push                  # Override the remote environment's database with your local copy. Will also do a 'search and replace' for the site URLs.
db:pull                  # Override the local database with your remote environment's copy. Will also do a 'search and replace' for the site URLs.
db:backup                # Take an sqldump of the remote environment's database and store it in a folder of your local repository called db_backups (its ignored in Git)
uploads:push             # Override the remote environment's uploads folder with your local copy.
uploads:pull             # Override your local uploads folder with the environment's copy.
cache:repo:purge         # Remove the repo folder on the environment in question.

If you need more informations about capistrano and this tutorial, this is a useful link:
http://capistranorb.com/
https://github.com/Mixd/wp-deploy

Using WordPress efficiently with Capistrano

How to use WordPress with Git efficiently

I use to work with frameworks like Symfony, Angular, Laravel and more.

When it comes to VCS (Version Control System), we need to remind some facts.

WHAT ARE THE ADVANTAGES OF VCS
1. Keep track of changes by owners, time…
2. Easily roll back changes when necessary
3. Easier to collaborate with other developers

WHAT IS NOT VCS MADE FOR
1. Replacement for scheduled backups, VCS !== BACKUP !!!
2. Debugging. Since every little change is tracked, it’s not its purpose.
3. Committing untested or broken code to the repository… Just a matter of sense !
4. Committing generated content (from user or otherwise)
5. Uploads & thumbnails => heavy repo with absolutely no benefit, use a cdn for media content !

WHAT IS THE GOAL OF VCS WITH WORDPRESS (Like another framework or cms)
1. Keep sensitive information out of the repository
2. Avoid wordpress core and upload files

Ok. You will surely tell me that this way, it will be a pain to retrieve the full project for a new developer, because there will be no wordpress core files, nor wp-config.php file.

Sure you’re right. But remember, VCS !== BACKUP, keep third parties you are not allowed to touch apart of your repository.
ANND, I will show an easier way to bypass this simple issue.

  • It is not a good way to modify wordpress core (what about future updates)? Don’t keep core files inside your repository.
  • Config file is personal to each user, never shared it on vcs, keep database datas secret.

NOW, LET’S START !!!!

Let’s start with the .gitignore file content

# Ignore everything in the root except the "wp-content" directory.
/*
!.gitignore
!wp-content/
!.htaccess

# Ignore everything in the "wp-content" directory, except the based themes and the "tmp" directory.
wp-content/themes/twenty*
wp-content/tmp/

#Do this essentially if you store your media content inside a cdn
wp-content/uploads/ 

# Hidden files
*.DS_Store
*Thumbs.db
*.sass-cache*
*~imageoptim*

Now, let’s grab the wordpress core and config files. For that we will need “wp-cli” extension, you can download it here: https://www.howtoforge.com/tutorial/getting-started-with-wp-cli/

Once, you have “wp-cli” enabled in your cli environment, we can start the fun:

  1. Install WordPress core files with a specific version
    wp core download --version=x.x.x --allow-root
    
  2. Install config file with database datas

    wp core config --dbname=mysite --dbuser=root --dbpass=password --dbhost=127.0.0.1
    

And here we go, quite simple, enjoy🙂

How to use WordPress with Git efficiently

Git issue with WordPress some folders are ignored

Hi everyone,

It’s been a while I didn’t wrote here and I’m glad to see that I make more and more visits, thank you.
It feels good to be back and share with you my issues.

So today I faced a strange problem with WordPress.

Our wordpress project uses Retouch theme with Unyson plugins.

After some updates on the project, I created a git repository and put my changes in, inside a branch.
Everything was ok, expected that if you pull the git repository, even if you re-upload the database, it seems that instead of displaying the normal content from the database, it was a hash that was shown, something like “{length: xxx, hash: xxx}”.

After many hours, I noticed that the problem was a plugin issue with Unyson Builder extension that was missing in my repository.

I can’t actually figure why, but in BitBucket when I access this directory “wp-content/plugins/unyson/framework/extensions/shortcodes/”, the next folder seems to be two folders attached like this “extensions/page-builder”.

So git was ignoring this folder no matter what I could do.

To solve this kind of problem, you always have to check that git doesn’t ignore accidentally some folders. After your “git add” and before any “git commit”, use this command:

git status --ignored

Thank you for reading me.

Git issue with WordPress some folders are ignored

Click event over flash object – full browser compatibility (IE, Firefox, Chrome, Safari)

Hi everybody,

It’s been a long time I’ve posted here, and it is a great pleasure to come back in the coding game.

Last week, I needed to put a flash ad in my website, a custom ad that must be redirected to the announcer website.
The flash animation doesn’t contain a link, so, I’ve naturally inserted a link that wraps my html object, but my link got none effects on browsers expected Chrome.

This is because click events (detection) over flash object are not well supported by all the browsers.

This is what I’ve written:

<a href="http://www.xxx.com/redirect.php?utm_source=xxxxx&utm_medium=display&utm_content=mega&utm_campaign=ST-20151012&url=http://www.xxx.fr" target="_blank">
    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="728" height="90" id="movie_name" align="middle">
        <param name="movie" value="/sites/default/files/pub/banniere_landscape.swf"/>
        <param name="quality" value="high" />
        <param name="bgcolor" value="#ffffff" />
        <param name="play" value="true" />
        <param name="loop" value="true" />
        <param name="scale" value="showall" />
        <param name="menu" value="true" />
        <param name="devicefont" value="false" />
        <param name="salign" value="" />
        <param name="allowScriptAccess" value="sameDomain" />
        <!--[if !IE]>-->
        <object type="application/x-shockwave-flash" data="/sites/default/files/pub/banniere_seapiax_landscape.swf" width="728" height="90">
            <param name="movie" value="/sites/default/files/pub/banniere_landscape.swf"/>
            <param name="quality" value="high" />
            <param name="bgcolor" value="#ffffff" />
            <param name="play" value="true" />
            <param name="loop" value="true" />
            <param name="scale" value="showall" />
            <param name="menu" value="true" />
            <param name="devicefont" value="false" />
            <param name="salign" value="" />
            <param name="allowScriptAccess" value="sameDomain" />
            <!--<![endif]-->
                <a href="http://www.adobe.com/go/getflash">
                    <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"/>
                </a>
            <!--[if !IE]>-->
        </object>
        <!--<![endif]-->
    </object>
</a>

To solve this, the better and easier way is to disbale the CSS point-events attribute, put the object element in the back with negative z-index, put the “a” link to the front, and set the object element with wmode parameter to transparent, juste like this:

<a ... style="display: block; z-index: 1;">
<object ... style="z-index: -1; pointer-events: none;">*
    <param name="wmode" value="transparent" />
</object>
</a>

This fix will work fine on Chrome and Firefox, but not in old Internet Explorer versions.
The hack for the full browser compatibility is to set a transparent html tag in front of the flash element, that will listen to the click event.
It’s as simple as this:

    <i style="display:block; height: 90px; width: 728px;  position: relative; z-index: 9; margin-top: -90px;"></i>
</a>

Now, you can click on any html object element with full browsers compatibility, including Safari.

See the full code below:

<a href="http://www.xxx.com/redirect.php?utm_source=xxxx&utm_medium=display&utm_content=pave&utm_campaign=ST-20151012&url=http://www.xxxx.fr" target="_blank" style="display: inline-block; z-index: 1; position: relative;">
    <span>
        <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="728" height="90" id="movie_name" align="middle" style="z-index: -1; pointer-events: none;" allownetworking="internal">
            <param name="quality" value="high" />
            <param name="bgcolor" value="#ffffff" />
            <param name="play" value="true" />
            <param name="loop" value="true" />
            <param name="scale" value="showall" />
            <param name="menu" value="true" />
            <param name="devicefont" value="false" />
            <param name="salign" value="" />
            <param name="wmode" value="transparent" />
            <param name="allowScriptAccess" value="sameDomain" />
            <param name="movie" value="/sites/default/files/pub/banniere_square.swf"/>
            <!--[if !IE]>-->
            <object type="application/x-shockwave-flash" data="/sites/default/files/pub/banniere_square.swf" width="728" height="90" style="z-index: -1; pointer-events: none;" allownetworking="internal">
                <param name="movie" value="/sites/default/files/pub/banniere_landscape.swf"/>
                <param name="quality" value="high" />
                <param name="bgcolor" value="#ffffff" />
                <param name="play" value="true" />
                <param name="loop" value="true" />
                <param name="scale" value="showall" />
                <param name="menu" value="true" />
                <param name="devicefont" value="false" />
                <param name="salign" value="" />
                <param name="wmode" value="transparent" />
                <param name="allowScriptAccess" value="sameDomain" />
                <!--<![endif]-->
                    <a href="http://www.adobe.com/go/getflash">
                        <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"/>
                    </a>
                    <!--[if !IE]>-->
            </object>
            <!--<![endif]-->
        </object>
    </span>
        <i style="display:block; height: 90px; width: 728px;  position: relative; z-index: 9; margin-top: -90px;"></i>
</a>
Click event over flash object – full browser compatibility (IE, Firefox, Chrome, Safari)

Doctrine Symfony2 – EntityManager Closed – Always enclose flush inside a try catch block and log exceptions

Hi,

This is not a tutorial but a good practice advice, about flush of objects in Doctrine with Symfony2.
A few days ago, we have encountered a strange error: “Entity Manager Closed”.

After several minutes of research, we found the problem.

We were trying to save a NULL value inside a NOT NULL field in our database, making the flush of objects failing.
When flush fails, it creates an exception like this:

 Doctrine\ORM\Exception "The EntityManager is closed".

When this error occurs, then entityManager is voluntarily closed, and following “flush” will not work.

The good practice is to systematically enclose all flush, inside a try catch block, and log the exception message and trace.
Let’s see an example.

    try {
        $em->flush();
    } catch (\Exception $e) {
        $msg = '### Message ### \n'.$e->getMessage().'\n### Trace ### \n'.$e->getTraceAsString();
        $this->container->get('logger')->critical($msg);
        // Here put you logic now you now that the flush has failed and all subsequent flush will fail as well
    }

This is a good practice that you’ll have to use in your further codes.

Doctrine Symfony2 – EntityManager Closed – Always enclose flush inside a try catch block and log exceptions

Why type casting of values is important in php?

What is the difference between:

$var = (string) "a";
//And
$var = "a";

I sometimes come into debate with some developers, on the need to cast php variables values.

There are no clear documentations on this subject, so this is my interpretation.

1. Can php cast variables?
First of all, you have to know that php can not cast variables, but only values.

2. Is php an interpreted or compiled language?
Php is a on the fly compiled language, and not interpreted like many developers tell it.

It then becomes important to learn how are saved variables inside your computer.

3. How do variables are saved inside our computers?

  • When a variable is declared, in reality, we’re asking to the computer, the permission to create some space in the RAM (Random Access Memory), for this variable.
    (One space for the variable name called address, one space for its value).
  • Without RAM, our program will be unable to memorize our variables.

  • Depending on the type of declared variable, thus, a more or less memory space is allocated for the value (remember that php can’t cast a variable, just its value).

4. Then, what benefits to cast values?

  • Save time for variables assignment in memory (although negligible with our latest machines).
  • Better code clarity and readability, let me explain.

  • $varA = 'a';
    $varB = 0;
    var_dump($varA == $varB); //equals true, this is not what we expected
    

    Php first analyzes variables values and then casts them. for this comparison, it will convert ‘a’ string into integer. This will result to 0.

    One solution would be to first check the $varB type before comparison like this:

    $varA = 'a';
    $varB = 0;
    if (is_string($varB)) {
       var_dump($varA == $varB);
    }
    

    But, the best practice is to cast the values, upstream.

    $varA = (string) 'a';
    $varB = (string) 0;
    var_dump($var1 == $varB); //equals false, what we expected
    

    I see you coming!!! Of course, we could also write:

    $varA = 'a';
    $varB = '0';
    

    But in my opinion, it’s less readable.

    Everyone has its method. The main important is to test variables before using them.
    There are many other examples, but it is not the purpose of this post, if you have your opinion, you are invited to share it.

    Why type casting of values is important in php?

    Call php scripts from AngularJs running under NodeJs with express

    Hi everyone,

    Last night I’ve broken my head trying to run a php script from an Angular application running under Nodejs with the excellent “express” http server.

    First, let’s go back to the basics, what is NodeJs?
    Node.js® is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications” Source: (http://nodejs.org/).

    NodeJs is not directly a server, but a platform that can implements a lot of modules, like an http server.
    For my project I’m using expressJs web application framework. More documentation about expressJs here: http://nodejs.org/

    With expressJs, you can use an http server without having to use an external software like Apache, Lighttpd or Nginx.
    it will offer you the opportunity to serve static files (html, js, css…), but not dynamic files like php files.
    Give it a try by calling a php file within your angular application only running under NodeJs, you will get a 404 (forbidden error).

    To solve this problem, you have multiple issues:
    – Try to customize a module that will enable php parsing inside NodeJs
    – Use an additional php server like Apache or Nginx

    For simplicity reasons, we will choose the second option, it was my case after hours of research.
    So, turn on your external http server (if it’s not already the case).

    Right, now you have two servers running on different ports (Apache or Nginx, or anything else on port 80, and Node on port 8080 or another).

    The solution will be:
    1. To call your php files on port 80 served by your php server, inside your ajax call, just like this:

    $http({
        method  : 'POST',
        url     : 'http://localhost:80/process.php',
        data    : $.param($scope.formData),
        headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
    })
    .success(function(data) {
        console.log(data);
    }).error(function(data) {
        console.log(data);
    });
    
    1. Allow CORS within your server side application, as we’re making ajax requests
      header("Access-Control-Allow-Origin: *");
      

    And voilà, the job is done.

    Call php scripts from AngularJs running under NodeJs with express