Category Archives: PHP

Simple Captcha in PHP

This captcha is simple and can use for any website ^^

<?php
require_once BASE_PATH . '/Code/claviska/simple-php-captcha.php';
class Captcha {
    /**
     * Document: https://github.com/claviska/simple-php-captcha
     */
    public static function checkCaptcha () {
        $isSuccess = FALSE;
        if (
            empty($_POST['simple_captcha_client']) === FALSE &&
            empty($_SESSION['simpleCaptcha']['code']) === FALSE &&
            strtolower($_POST['simple_captcha_client']) == strtolower($_SESSION['simpleCaptcha']['code'])
        ) {
            $isSuccess = TRUE;
        }
        return $isSuccess;
    }
    public static function generateCaptcha () {
        $_SESSION['simpleCaptcha'] = simple_php_captcha([
            'min_length' => 6,
            'max_length' => 6,
            'characters' => '123456789'
        ]);
        return $_SESSION['simpleCaptcha']['image_src'];
    }
    public static function showCaptcha ($class = NULL) {
        return '<div class="captcha-holder ' . $class . '"><img src="' . Captcha::generateCaptcha() . '" class="captcha-img" /><input type="text" name="simple_captcha_client" placeholder="' . convertCase(trans('validation.enter_captcha'), 3) . '" /><a data-href="' . BASE_URL . '/captcha/reset" class="captcha-refresh"><i class="icons fi-refresh"></i></a></div>';
    }
}
class Default_CaptchaController {
    function resetAction() {
        require_once BASE_PATH . '/Code/Captcha.php';
        echo Captcha::generateCaptcha();
    }
}
$('.captcha-refresh').on('click', function () {
	var $me = $(this);
	$.ajax({
		url: $(this).data('href')
	})
	.done(function(src) {
		$me.closest('.captcha-holder').find('.captcha-img').attr('src', src);
	});
});
.captcha-holder {
    &> * {
        display: inline-block;
        width: auto;
        height: 39px;
    }
    &> input {
        width: 125px;
    }
    .captcha-refresh {
        cursor: pointer;
        .icons {
            @include font-size(22px);
            margin-left: 5px;
            position: relative;
            top: 3px;
        }
    }
}

Continue reading Simple Captcha in PHP

Login bằng php-jwt thay cho session, cookie truyền thống

install:

composer require firebase/php-jwt:dev-master
composer require zendframework/zend-config:~2.3
composer require zendframework/zend-http:~2.3

Tham khảo: sitepoint Continue reading Login bằng php-jwt thay cho session, cookie truyền thống

Gulp run as series of tasks

// task cleanDist
gulp.task('cleanDist', function(cb) {
  return del([
    './www/js/configuration.js'
  ]);
});
// task copy-local-files: require 'cleanDist' task
gulp.task('copy-local-files', ['cleanDist'], function(cb) {
  return gulp.src('./../config/local/**/*').pipe(gulp.dest('./www'));
});
// task lint: require 'copy-local-file' task
gulp.task('lint', ['copy-local-files'], function() {
  return gulp.src(paths.js)
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

Bonus: Ionic run task before server and after serve: config in ionic.project file

{
  "name": "songpham",
  "app_id": "20002005",
  "gulpDependantTasks": [ // before serve
    "lint"
  ],
  "gulpStartupTasks": [ // after serve
    "watch"
  ],
  "watchPatterns": [
    "www/**/*",
    "!www/lib/**/*"
  ]
}

Apache/Nginx/Xampp apache enable CORS Access-Control-Allow-Origin for Angular Js

More information, you should check here: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
How CORS works:
1
The browser sends the OPTIONS request with an Origin HTTP header. The value of this header is the domain that served the parent page. When a page from http://www.foo.com attempts to access a user’s data in bar.com, the following request header would be sent to bar.com:

Origin: http://www.foo.com

The server may respond with:
An Access-Control-Allow-Origin (ACAO) header in its response indicating which origin sites are allowed. For example:

Access-Control-Allow-Origin: http://www.foo.com

Preflight example
When performing certain types of cross-domain AJAX requests, modern browsers that support CORS will insert an extra “preflight” request to determine whether they have permission to perform the action.

OPTIONS /
Host: bar.com
Origin: http://foo.com

If bar.com is willing to accept the action, it may respond with the following headers:

Access-Control-Allow-Origin: http://foo.com
Access-Control-Allow-Methods: PUT, DELETE

Continue reading Apache/Nginx/Xampp apache enable CORS Access-Control-Allow-Origin for Angular Js

Set up browser-sync with Gulp

var gulp = require('gulp'),
    browserSync  = require('browser-sync').create(),
    gulpif       = require('gulp-if'),
    gutil        = require('gulp-util'),
    uglify       = require('gulp-uglify'),
    concat       = require('gulp-concat'),
    cssmin       = require('gulp-cssmin'),
    sass         = require('gulp-sass'),
    sourcemaps   = require('gulp-sourcemaps'),
    plumber      = require('gulp-plumber');
var errorHandle = function (error) {
    gutil.log(gutil.colors.red(error.message));
    this.emit('end');
};
var production = false;
/**
 * Copy any needed files
 * Do a 'gulp copyfiles' after bower updates
 **/
gulp.task("copyfiles", function() {
    ...
});
var paths = {};
paths.scripts_1 = [
    ...
];
paths.scripts_2 = [
    ...
];
paths.scripts_3 = [
    ...
];
paths.css_1 = [
    ...
];
paths.css_2 = [
    ...
];
gulp.task('buildVendorJs', function() {
  return gulp.src(paths.scripts_1)
      .pipe(plumber(errorHandle)) /* replaces pipe method and removes standard onerror handler on error event */
      .pipe(sourcemaps.init())
      .pipe(concat('vendors.js'))
      .pipe(gulpif(production, uglify({ mangle: false })))
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest('./public/assets/js'));
});
gulp.task('buildAppJs', function() {
  return ...;
});
gulp.task('buildLangJs', function() {
  return ...;
});
gulp.task('buildVendorCss', function() {
  return gulp.src(paths.css_1)
      .pipe(plumber(errorHandle)) /* replaces pipe method and removes standard onerror handler on error event */
      .pipe(sourcemaps.init())
      .pipe(concat('vendors.css'))
      .pipe(sass())
      .pipe(gulpif(production, cssmin()))
      .pipe(sourcemaps.write('./'))
      .pipe(gulp.dest('./public/assets/css'));
});
gulp.task('buildAppCss', function() {
  return ...;
});
gulp.task('default', ['buildVendorJs', 'buildAppJs', 'buildLangJs', 'buildVendorCss', 'buildAppCss'], function () {
  browserSync.init({
      proxy:      'my.app'
  });
  gulp.watch(paths.scripts_1, ['buildVendorJs', browserSync.reload]);
  gulp.watch(paths.scripts_2, ['buildAppJs', browserSync.reload]);
  gulp.watch(paths.scripts_3, ['buildLangJs', browserSync.reload]);
  gulp.watch(paths.css_1, ['buildVendorCss', browserSync.reload]);
  gulp.watch(paths.css_2, ['buildAppCss', browserSync.reload]);
  gulp.watch([
    'app/Http/**/*',
    'app/Library/**/*',
    'app/Models/**/*',
    'app/*',
    'resources/views/**/*'
  ], browserSync.reload);
});

Using Yield in PHP to generate the combobox values

Generators will allow you to load tiny amounts of the total data at once.

/**
 * input: prependItemToArrayCombobox(array('' => 'Select Value'), array(1 => 'US', 2 => 'VN'));
 * output: Object ('' => 'Select Value', 1 => 'US', 2 => 'VN' )
 */
function prependItemToArrayCombobox ($result, $array) {
  if (empty($array) === FALSE) { /* add new items to the first if have */
    foreach ($array as $key => $value) {
      if (array_key_exists($key, $result) === FALSE) {
        yield $key => $value;
      }
    }
    foreach ($result as $key => $value) {
      yield $key => $value;
    }
  } else {
    if (empty($result) === FALSE) {
      foreach ($result as $key => $value) {
        yield $key => $value;
      }
    }
  }
}

Basic Javascript App

Let’s start on adding some JavaScript to make the app:

var Gimmie = {
    $content: $('.content'),
    $form: $('form'),
    toggleLoading: function(){
        // Toggle loading indicator
        this.$content.toggleClass('content--loading');

        // Toggle the submit button so we don't get double submissions
        // http://stackoverflow.com/questions/4702000/toggle-input-disabled-attribute-using-jquery
        this.$form.find('button').prop('disabled', function(i, v) { return !v; });
    },
    userInput: '',
    userInputIsValid: false,
    appId: '',
    validate: function() {
        // Use regex to test if input is valid. It's valid if:
        // 1. It begins with 'http://itunes'
        // 2. It has '/id' followed by digits in the string somewhere
        var regUrl = /^(http|https):\/\/itunes/;
        var regId = /\/id(\d+)/i;
        if ( regUrl.test(this.userInput) && regId.test(this.userInput) ) {
            this.userInputIsValid = true;
            var id = regId.exec(this.userInput);
            this.appId = id[1];
        } else {
            this.userInputIsValid = false;
            this.appId = '';
        }
    },
    throwError: function(header, text){
        // Remove animation class
        this.$content.removeClass('content--error-pop');
        // Trigger reflow
        // https://css-tricks.com/restart-css-animation/
        this.$content[0].offsetWidth = this.$content[0].offsetWidth;
        // Add classes and content
        this.$content
            .html('<p><strong>' + header + '</strong> ' + text + '</p>')
            .addClass('content--error content--error-pop');
        this.toggleLoading();
    },
    render: function(response){
        var icon = new Image();
        icon.src = response.artworkUrl512;
        icon.onload = function() {
            Gimmie.$content
                .html(this)
                .append('<p><strong>' + response.trackName + '</strong> Actual icon dimensions: ' + this.naturalWidth + '×' + this.naturalHeight + '</p>')
                .removeClass('content--error');
            Gimmie.toggleLoading();
            // If it's an iOS icon, load the mask too
            if(response.kind != 'mac-software') {
                var mask = new Image();
                mask.src = 'assets/img/icon-mask.png';
                mask.onload = function() {
                    Gimmie.$content.prepend(this);
                }
            }
        }
    }
};
$(document).ready(function(){
    e.preventDefault();
    // On page load, execute this...
    Gimmie.toggleLoading(); // call the loading function
    Gimmie.userInput = $(this).find('input').val();
    Gimmie.validate();
    if( Gimmie.userInputIsValid ) {
        /* make API request */
        $.ajax({
            url: "https://itunes.apple.com/lookup?id=" + Gimmie.appId,
            dataType: 'JSONP'
        })
        .done(function(response) {
            // when finished
            var response = response.results[0];
            if(response && response.artworkUrl512 != null){
                Gimmie.render(response);
            } else {
                Gimmie.throwError(
                    'Invalid Response',
                    'The request you made appears to not have an associated icon. <br> Try a different URL.'
                );
            }
        })
        .fail(function(data) {
            // when request fails
            Gimmie.throwError(
                'iTunes API Error',
                'There was an error retrieving the info. Check the iTunes URL or try again later.'
            );
        });
    } else {
        /* throw an error */
        Gimmie.throwError(
            'Invalid Link',
            'You must submit a standard iTunes store link with an ID, i.e. <br> <a href="https://itunes.apple.com/us/app/twitter/id333903271?mt=8">https://itunes.apple.com/us/app/twitter/<em>id333903271</em>?mt=8</a>'
        );
    }
});

Sử dụng grunt

Grunt là 1 Javascript task runner. Tại sao phải dùng Javascript task runner? Vì ta cần automation code. Tức là khi làm việc trong 1 project, cứ mỗi sau khi sửa file sass, javascript… ta không thể nén file javascript (có hàng chục file), không thể ghép các file javascript lại với nhau (file nặng, ghép có thể gây ra lỗi)… Chỉ cần cài grunt vào, Grunt sẽ lo việc nén file, merge các file lại với nhau, ta không cần phải bận tâm vào việc đó mà chỉ cần tập trung vào build project sao cho tốt là được. Ngoài Grunt, bạn có thể chọn gulp để làm việc này. Nhìn chung bạn cần phải học cả grunt và gulp vì một số nơi dùng grunt, một số nơi dùng gulp, bạn sẽ dùng công nghệ nào tùy thuộc vào môi trường mà bạn làm việc.

Grunt

1) Update npm:

npm update -g npm

2) Install grunt CLI:

npm install -g grunt-cli

3) Tạo pakage.json:

{
  "name": "my-project",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-sass": "~0.9.2",
    "grunt-contrib-watch": "~0.6.1",
    "grunt-contrib-concat": "~0.5.1",
    "grunt-contrib-uglify": "~0.9.1"
  }
}

Continue reading Sử dụng grunt