Blog.

Using Gulp.js to check your code quality

MF

Marco Franssen /

7 min read1255 words

Cover Image for Using Gulp.js to check your code quality

In this blog post I want to show you how you can use Gulp.js to automate some tasks to check the quality of your code. Before we deep dive into the subject and the coding examples I first want to give you a short introduction on what Gulp.js actually is. So if you already know what Gulp.js is about you can move on to the next chapter.

Easy to use By preferring code over configuration, gulp keeps things simple and makes complex tasks manageable. Efficient Using the power of node streams, gulp gives you fast builds that don't write intermediary files to disk.

Previous statements are quoted from the Gulp.js homepage. Gulp.js is just like Grunt.js a task runner build on Node.js aka io.js. Where you define your tasks in Grunt.js in a configuration based style, you will be defining your tasks in Gulp.js more in a code based style. For both task runner there is a wide variety of plugins available.

So what is the real power of Gulp.js?

In my opinion that is the utilization of the Node.js streams, which makes Gulp.js a very fast and memory efficient task runner. The difference between Gulp.js and Grunt.js can especially be noticed when working on larger projects, with huge amounts of files.

In many cases developers are limiting the usage of both task runners to only their javascript projects. As I showed you last time Grunt.js can also be used to automate some of your .Net/c# tasks I want to show you today you can also use it on php projects. So here is my call for action. Stop limiting yourself and try to apply it on any project you're working on, no matter the language!

In one of my previous blogposts I showed you how to use Grunt.js to automate some of your development tasks. Today we gonna have a look at Gulp.js, so lets get started. The minimum requirement to have Gulp.js is to have the node package installed and having the gulpfile.js in place in the root of your project folder.

npm install -g gulp
npm install --save-dev gulp
"use strict";

var gulp = require("gulp");

Similar as Grunt.js, Gulp.js also has a lot of plugins available. Lets zoom in on some of the plugins you can apply on php.

Some of the tasks I will be showing you may look a little bit silly at first sight, but keep on reading, in the Gulp-watch paragraph you will understand.

Php lint

npm install --save-dev phplint

In your gulpfile.js you can add the following lines of code to use it. As you can see you can use a globbing pattern to match the files you want to have phplint executed on and you can also ignore folders from being included.

var phplint = require("phplint").lint;

gulp.task("phplint", function (cb) {
  phplint(
    ["./**/*.php", "!node_modules/**/*", "!vendor/**/*"],
    { limit: 10 },
    function (err, stdout, stderr) {
      if (err) {
        cb(err);
      } else {
        cb();
      }
    }
  );
});

Above task executes all phplint on all files matching your globbing pattern.

Php Unit

npm install --save-dev gulp-phpunit
composer require --dev "phpunit/phpunit"

In your gulpfile.js you can add the following lines of code to use it.

var phpunit = require("gulp-phpunit");

gulp.task("phpunit", function () {
  return gulp
    .src("phpunit.xml")
    .pipe(phpunit("vendor/bin/phpunit"))
    .on("error", console.error("TESTS FAILED:\nYou killed someones baby!"))
    .pipe(function () {
      console.log("TESTS PASSED:\nAwesome you rock!");
    });
});

Based on the settings defined in your phpunit.xml file you will execute phpunit using those settings.

Php CS

npm install --save-dev gulp-phpcs gulp-shell
composer require --dev "squizlabs/php_codesniffer"

In your gulpfile.js you can add the following lines of code to use it.

var phpcs = require("gulp-phpcs");

gulp.task("phpcs", function () {
  return gulp
    .src(["./**/*.php", "!node_modules/", "!vendor/**/*"])
    .pipe(
      phpcs({
        bin: "vendor/bin/phpcs",
        standard: "PSR2",
        warningSeverity: 0,
      })
    )
    .pipe(phpcs.reporter("log"));
});

gulp.task(
  "phpcbf",
  shell.task([
    "vendor/bin/phpcbf --standard=PSR2 --ignore=vendor/,some/other/folder folder/to/include another/folder/to/include somefiletoinclude.php server.php",
  ])
);

As you may see phpcs also ships with a tool phpcbf which can be used to autofix many of those phpcs issues. Unfortunatily there is no Gulp.js plugin for this tool, but we can leverage from the gulp-shell plugin to execute phpcbf. As you can see we are using the PSR2 standard for both tools.

Php Doc

npm install --save-dev gulp-shell
composer require --dev "phpdocumentor/phpdocumentor"

In your gulpfile.js you can add the following lines of code to use it.

var shell = require("gulp-shell");

gulp.task(
  "phpdoc",
  shell.task([
    "vendor/bin/phpdoc -d . -t docs/phpdoc -i vendor/,node_modules/,server.php",
  ])
);

Also for phpdoc it's a similar story. We have the gulp-shell plugin execute phpdoc on the root folder of our project and we exclude the vendor, node_modules and server.php from being included in the docs.

Php MD

npm install --save-dev gulp-shell
composer require --dev "phpmd/phpmd"

In your gulpfile.js you can add the following lines of code to use it.

var shell = require("gulp-shell");

gulp.task(
  "phpmd",
  shell.task([
    "vendor/bin/phpmd . codesize,unusedcode,naming,design,cleancode,controversial --reportfile docs/phpmd.html --exclude vendor/,node_modules/ --suffixes php",
  ])
);

Also for PhpMD there is no Gulp.js plugin available, however no worries also here we just leverage from the gulp-shell plugin. We configured phpmd to make checks on codesize, unusedcode, naming, design, cleancode and some controversial checks.

Php depend

npm install --save-dev gulp-shell
composer require --dev "pdepend/pdepend"

In your gulpfile.js you can add the following lines of code to use it.

var shell = require("gulp-shell"),
  pdependDocs = "docs/pdepend";

gulp.task(
  "pdepend",
  shell.task([
    "mkdir -p " + pdependDocs,
    "vendor/bin/pdepend --summary-xml=" +
      pdependDocs +
      "/summary.xml --jdepend-chart=" +
      pdependDocs +
      "/chart.svg --overview-pyramid=" +
      pdependDocs +
      "/pyramid.svg --ignore=vendor,node_modules --suffix=php .",
  ])
);

For pdepend we also use the shell plugin. As you can see we define multiple elements in the array. So the first command we execute is to create a folder to store the output of pdepend. The second command executes pdepend and writes the summary.xml, chart.svg and pyramid.svg to the docs/pdepend folder.

Gulp.js Watch

Unlike Grunt.js you don't have to install another plugin to watch your directories/files for changes. Gulp.js has this feature builtin.

Using Gulp.js watch we will be continuously watching our project files for changes, and based on which files have changed we can have Gulp.js automatically execute our tasks. So lets use gulp watch to have some of our tasks being executed automatically on changes to files matching the globbing patterns.

gulp.task('watch', function () {
    gulp.watch(['composer.json', 'phpunit.xml', './**/*.php', '!vendor/**/*', !node_modules/**/*'], function (event) {
        console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
    });
    gulp.watch('composer.json', ['dump-autoload']);
    gulp.watch(['phpunit.xml', './**/*.php', '!vendor/**/*', !node_modules/**/*'], ['phplint', 'phpcs', 'phpunit']);
});

gulp.task('default', ['phplint', 'phpcs', 'phpunit', 'watch']);

The above task shows a small message in the console that something has changed and that the configured tasks will be executed. We also defined the default tasks which initially runs all our "quality" tasks and then starts the watch task. Now each time you change a php file the tasks phplint, phpcs and phpunit will be executed and give you immediate feedback on the changes you made.

The things I showed you in this blogpost are just the beginning of what you can achieve with this. You could also be using git hooks to have some of these tasks being executed prior to a push. I would love to get your feedback on how you are applying it on your projects.

You have disabled cookies. To leave me a comment please allow cookies at functionality level.

More Stories

Cover Image for Jasmine vs. Mocha

Jasmine vs. Mocha

MF

Marco Franssen /

In this blog post I want to highlight the similarities and the differences between Jasmine and Mocha. In this comparison I will focus on the latest versions of both libraries. As of this writing Jasmine 2.4 and Mocha 2.3. When comparing both libraries at NPMCompare you notice that Mocha is the more popular framework today. Mocha has more frequent updates, more downloads and more forks on Github. Although both frameworks are pretty popular and do have a lot of similarities. Lets go have a look a…

Cover Image for Put your ssh experience in Windows on Steroids

Put your ssh experience in Windows on Steroids

MF

Marco Franssen /

In this blogpost I want to show you how you can make your life easier to work with Linux VM's and Git by configuring SSH on your Windows Machine in a secure but convenient way. Let me first elaborate a little further why you would want to apply the tips and tricks from this blog post. Git has become the de-facto standard of vcs over the past few years. You are probably using it for all your software development projects, and maybe even for your web blog, when you are blogging in markdown using…

Cover Image for Packer.io machine building and provisioning part 2

Packer.io machine building and provisioning part 2

MF

Marco Franssen /

In the previous part of this series we had a look on building a bare Debian VM with the bare minimum packages installed to run a web server. In this part we will have a look on how we can improve our packer script with user variables and how to use the file and shell provisioner. User variables Variables can be easily added to the packer script by adding following JSON. Best practice is to put your variables as the first property in your JSON, before your builders. This way you have all the c…

Cover Image for Packer.io machine building and provisioning part 1

Packer.io machine building and provisioning part 1

MF

Marco Franssen /

Large development teams are often coping with the "It works on my machine" syndrome. One solution to solve these kind of issues is by give each single developer the same VM, which is most preferably the same as your production server. So imagine your company is building a web application. The web application is hosted on a Debian server using Apache, MySQL and PHP. So considering these preconditions I will give you a simple example to get your machines scripted and fully provisioned. In this fir…