To create migration, we can use this artisan command.

$ php artisan make:migration create_companies_table

Laravel will create a new migration file in database/migrations directory.

Generated file is like this:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCompaniesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
}

up() method is used to create a new tables or add new columns to table.
down() method is used to rollback.

We can use --create option when create migration to automatically generate base code.

$ php artisan make:migration create_companies_table --create=companies

Generated file is like this:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCompaniesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('companies', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('companies');
    }
}

When insert a new row to pivot table, we can use attach() method like this:

$company = Company::find(1);
$company->users()->attach(1);

But this will not update created_at and updated_at timestamps column in pivot table.

To update timestamps, use withTimestamps() method on the relationship method.

class Company extends Model
{
  public function users()
  {
    return $this->belongsToMany(User::class)->withTimestamps();
  }
}

1. Make .travis.yml file to root

language: node_js

node_js:
  - '4'

cache:
  directories:
  - node_modules
  - _assets/vendor

before_install:
  - rvm install 2.2
  - rvm use 2.2 --fuzzy
  - export GEMDIR=$(rvm gemdir)

before_script:
  - npm install -g gulp
  - npm install -g bower
  - gem install jekyll
  - gem install jekyll-paginate
  - gem install jekyll-sitemap
  - gem install jekyll-feed
  - gem install html-proofer
  - chmod +x ./build.sh

# execute this script on each commit
script: "./build.sh"

# only take into account 'master' branch
branches:
  only:
  - master

env:
  global:
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speed up installation of html-proofer

sudo: false # route your build to the container-based infrastructure for a faster build

2. Generate Personal access tokens from GitHub website

  1. Click settings menu
  2. Click Personal access tokens menu
  3. Click Generate new token button
    1. Input Token description like travis
    2. Check repo scope

Copy new token to bellow step.

3. Generate secure key to .travis.yml

Install Travis CLI.

$ gem install travis

Use encrypt command to encrypt data

$ travis encrypt GH_TOKEN=/*Paste new token here*/

This command will add secret item to .travis.yml file.

4. Make gulpfile.js file to root

I followed this article to generate gulpfile.js.

var gulp = require('gulp');
var path = require('path');
var debug = require('gulp-debug');
// CSS
var sass = require('gulp-ruby-sass');
var cleanCSS = require('gulp-clean-css');

// JS BUILD
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');

// HTML
var htmlmin = require('gulp-htmlmin');

// Browser sync
var browserSync = require('browser-sync');

// Import files
var pkg = require('./package.json');

// Images files
var imagemin = require('gulp-imagemin');

// Utils
var utils = require('gulp-util');
var options = require("minimist")(process.argv.slice(2));
var addsrc = require('gulp-add-src');
var spawn = require('child_process').spawn;

var dist              = 'public/';
var distAssets        = './assets/';
var distStylesheets   = distAssets + 'css/';
var distJavascripts   = distAssets + 'js/';
var distImages        = distAssets + 'img/';
var distFont          = distAssets + 'fonts/';
var deploy            = 'public/';
var src               = './';
var srcStylesheets    = src + '_assets/styles/';
var srcJavascripts    = src + '_assets/scripts/';
var srcInclude        = src + '_includes/';
var srcLayout         = src + '_layouts/';
var srcImg            = src + '_assets/images/';
var srcPost           = src + '_posts/';
var bowerDir          = src + '_assets/vendor/';

// -->
// Compass & SASS
// <--
gulp.task('compass', function() {
    return sass(srcStylesheets + '*.scss', {
            style: 'compressed'
        })
        .on('error', sass.logError)
        .pipe(debug())
        .pipe(options.production ? cleanCSS({compatibility: 'ie8'}) : utils.noop())
        .pipe(concat('style.min.css'))
        .pipe(gulp.dest(distStylesheets));
});

// -->
// HTML
// <--
gulp.task('html', ['jekyll'], function() {
    // --> Minhtml
    return gulp.src([
        path.join(deploy, '*.html'),
        path.join(deploy, '*/*/*.html'),
        path.join(deploy, '*/*/*/*.html')
    ])
        .pipe(options.production ? htmlmin({collapseWhitespace: true}) : utils.noop())
        .pipe(gulp.dest(deploy))
        .pipe( options.production ? utils.noop() : browserSync.reload({stream:true, once: true}) );
});

// -->
// Browser Sync
// <--
gulp.task('browser-sync', function() {
    return browserSync.init(null, {
        server: {
            baseDir: "./" + deploy
        }
    });
});

// Reload all Browsers
gulp.task('bs-reload', function () {
    return browserSync.reload();
});

// -->
// js
// Concatenate & JS build
// <--
gulp.task('js-modernizr',function(){
    return gulp.src([bowerDir + 'modernizr/dist/modernizr-build.js'])
        .pipe(concat('modernizr.js'))
        .pipe(gulp.dest(distJavascripts))
        .pipe(rename('modernizr.min.js'))
        .pipe(options.production ? uglify() : utils.noop())
        .pipe(gulp.dest(distJavascripts));
});

gulp.task('js',['js-modernizr'],function () {
    return gulp.src([
        bowerDir + 'fastclick/lib/fastclick.js',
        bowerDir + 'jquery/dist/jquery.min.js',
        bowerDir + 'simple-jekyll-search/dest/jekyll-search.js',
        bowerDir + 'bootstrap-sass/assets/javascripts/bootstrap.js',
        bowerDir + 'ekko-lightbox/dist/ekko-lightbox.js',
        bowerDir + 'moment/moment.js',
        srcJavascripts + 'modules/*.js',
        srcJavascripts + 'pages/*.js',
        srcJavascripts + 'blog.js'])
        .pipe(concat(pkg.name + '.min.js'))
        .pipe(options.production ? uglify() : utils.noop())
        .pipe(gulp.dest(distJavascripts));
});

// -->
// JEKYLL task
// <--
gulp.task('jekyll', ['images', 'js', 'compass'], function (gulpCallBack){
    var jekyllCmd = process.platform === "win32" ? "jekyll.bat" : "jekyll";
    // After build: cleanup HTML
    var jekyll = spawn(jekyllCmd, ['build'], {stdio: 'inherit'});

    jekyll.on('exit', function(code) {
        gulpCallBack(code === 0 ? null : 'ERROR: Jekyll process exited with code: '+code);
    });
});

// -->
// Icons task
// <--
gulp.task('icons', function() {
    return gulp.src(bowerDir + 'font-awesome/fonts/**.*')
        .pipe(gulp.dest(distFont));
});

// -->
// Images task
// <--
gulp.task('images', function() {
    return gulp.src(srcImg + '**')
        .pipe(options.production ? imagemin({
            progressive: true,
            optimizationLevel : 3
        }) : utils.noop())
        .pipe(gulp.dest(distImages));
});

gulp.task('generate',['compass', 'js', 'icons', 'images', 'html']);

// -->
// Default task
// <--
gulp.task('default', ['compass', 'js', 'icons', 'images', 'html', 'browser-sync'], function (event) {
    // --> CSS
    gulp.watch(srcStylesheets+"**", ['html']);
    gulp.watch([
        srcInclude + '*.html',
        srcLayout + '*.html',
        srcPost + '**',
        src + '*.{md,html}'
    ], ['html']);
    // --> Ruby
    gulp.watch(path.join(dist, '*/*.rb'), ['html']);
    // --> JS
    gulp.watch([srcJavascripts+"**/*.js"], ['html']);
});

5. Make build.sh file to root

This will execute npm run build, gulp generate --production and htmlproofer ./public --disable-external --allow-hash-ref command step by step and commits result to gh-pages branch.

#!/bin/bash
#
## only process script when started not by pull request (PR)
if [ $TRAVIS_PULL_REQUEST == "true" ]; then
  echo "this is PR, exiting"
  exit 0
fi

# enable error reporting to the console
set -e

# build site with jekyll, by default to 'public' folder
npm run build
gulp generate --production
htmlproofer ./public --disable-external --allow-hash-href

# cleanup
rm -rf ../blog.zemna.net.gh-pages

# clone 'gh-pages' branch of the repository using encrypted GH_TOKEN for authentification
git clone -b gh-pages https://${GH_TOKEN}@github.com/zemna/blog.git ../blog.zemna.net.gh-pages

# copy generated HTML site to 'gh-pages' branch
cp -R public/* ../blog.zemna.net.gh-pages

# commit and push generated content to 'gh-pages' branch
# since repository was cloned in write mode with token auth - we can push there
cd ../blog.zemna.net.gh-pages
git config user.email "zemna@zemna.net"
git config user.name "zemna"
git add -A .
git commit -a -m "Travis #$TRAVIS_BUILD_NUMBER"
git push --quiet origin gh-pages > /dev/null 2>&1

6. Exclude file(s) or folder(s) from Jekyll build process

Add necessary file(s) or folder(s) to _config.yml file like bellow. Those files will not be built by Jekyll.

exclude:
  - lib
  - Gemfile
  - Gemfile.lock
  - node_modules
  - bower.json
  - "*.sh"
  - README.md
  - gulffile.js
  - package.json

7. Conclusion

You can see running example by https://github.com/zemna/blog repository.

Error 1

Maximum call stack size exceeded error

Solution

Update npm using sudo npm i npm -g command.

Error 2

ENOENT: no such file or directory, scandir '/home/vagrant/app-name/node_modules/node-sass/vendor' error

Solution

Execute npm rebuild node-sass --no-bin-links command. (Reference)

I got the problem when using bican/roles Role module in my Laravel project.

There is an error when I check permission.

So I decided to move zizaco/entrust and tested all features working normal.

How to install Entrust

Install use composer

$ composer require zizaco/entrust:5.2.x-dev

Setting to config/app.php

Add bellow line to providers array in config/app.php.

    Zizaco\Entrust\EntrustServiceProvider::class,

Add bellow line to aliases array in config/app.php.

    'Entrust' => Zizaco\Entrust\EntrustFacade::class,

Setting to app/Http/Kernal.php

Add bellow lines to routeMiddleware array in app/Http/Kernal.php.

    'role' => \Zizaco\Entrust\Middleware\EntrustRole::class,
    'permission' => \Zizaco\Entrust\Middleware\EntrustPermission::class,
    'ability' => \Zizaco\Entrust\Middleware\EntrustAbility::class,

Publish entrust.php file

$ php artisan vendor:publish

Database Setup

Generate Entrust migration

$ php artisan entrust:migration

It will generate the <timestamp>_entrust_setup_tables.php migration.

Execute migration

$ php artisan migrate

Trouble shootings

Error when execute migration

After create <timestamp>_entrust_setup_tables.php, you have to write your users table in this file. Open <timestamp>_entrust_setup_tables.php file and write name of users table to 28 line.

    $table->foreign('user_id')->references('id')->on('users')
        ->onUpdate('cascade')->onDelete('cascade');

This cache store does not support tagging

Set CACHE_DRIVER=array in .env file.

Error when delete role

In Laravel 5.2, error is occured when delete role. Because Entrust get User class using Config::get('auth.model').

EntrustRoleTrait.php file

    /**
     * Many-to-Many relations with the user model.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function users()
    {
        return $this->belongsToMany(Config::get('auth.model'), Config::get('entrust.role_user_table'),Config::get('entrust.role_foreign_key'),Config::get('entrust.user_foreign_key'));
       // return $this->belongsToMany(Config::get('auth.model'), Config::get('entrust.role_user_table'));
    }

So We have to return right user model by that position. There are two solutions for this.

1. Change EntrustRoleTrait.php file to use correct configuration value.

We can change Config::get('auth.model') to Config::get('auth.providers.users.model'). Laravel 5.2 already have users model information in that position.

2. Add auth.model value to config/auth.php file

We can also add new value to config/auth.php file to allow Entrust get rights value.

return [
  ...

  /**
   * Add this configuration for Entrust
   */
  'model' => App\User::class,
];

If you got bellow error when use memcached in Laravel, please check following steps.

exception 'Symfony\Component\Debug\Exception\FatalErrorException' with message 'Class 'Memcached' not found' in /var/www/gw/vendor/laravel/framework/src/Illuminate/Cache/MemcachedConnector.php:51

Install memcached

$ sudo apt-get install php5-memcached memcached

Enabled php5-memcached

sudo php5enmod memcached

Restart apache web server

$ sudo service apache2 restart

Check memcached service status

$ sudo service memcached status
* memcached is running

Clear cache

$ php artisan cache:clear

When I run composer update command in shell, composer displays warning like bellow.

You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug

And takes too long time to process.

I already go to https://getcomposer.org/xdebug reference and tried to disable xdebug option in php.ini file. But I couldn't found it.

This is the real reference to disable xdebug option in php.ini file.

Get what php.ini file is used

First, check what kind of php.ini file is used.

php -i | grep "php.ini"

Comment xdebug option

Search zend_extension option and comment it using ';(semicolon)'.

;zend_extension = "/path/to/my/xdebug.so"

If you can't find this option in php.ini file, maybe it is in conf.d folder. File name is like '20-xdebug.ini'. Open this file and comment it.

References

Clone laravel source to server

$ git clone https://github.com/zemna/groupware.git

Install necessary modules

$ npm install

$ composer install --no-dev -o --prefer-dist

$ bower install

Make .env

$ cp .env.example .env

Generate key to .env

$ php artisan key:generate

Execute gulp if necessary

$ gulp --production

Migrate database

$ php artisan migrate

Give owner to web server

$ chown -R www-data:www-data *

Set write permission

$ chmod -R 775 bootstrap/cache
$ chmod -R 775 storage

FreeTDS is a set of libraries for Unix and Linux that allows your programs to natively talk to Microsoft SQL Server and Sybase datbases.

When I attach social buttons to my blog, Facebook button moves bottom almost 5 pixels from other social buttons like Twitter, Google+.

This is because facebook button has vertical-align: bottom; style inside of widget;

We can solve this problem adding bellow style to css.

.fb_iframe_widget span {
    vertical-align: baseline !important;
}
Copyright zemna. All right reserved.