Posted on Leave a comment

Create WooCommerce Products Search Input For Your Plugins

binocular search for product

As I develop more and more plugins for WooCommerce, a need for WooCommerce product search emerges. You know, this kind of product search:

If you ever need the full source code of this plugin, please visit this github repo

Let’s learn how to create a field like that so you can use in your plugin.

How to create WooCommerce products search select box

Let’s go through the steps to create a product search input for you plugin:

  • Enqueue select2 library
  • Create HTML structure
  • Write the needed Javascript to enable search

Enqueue select2 library

Select2 is a jQuery plugin that does many amazing things including enable search for traditional select box. It also supports getting list from ajax (which is exactly what we are going to do).

Enqueuing select2 is simple. Let’s create a class for our plugin and put the following code

<?php
/**
 * Plugin Name: BC AJAX Product Search
 * Plugin URI: https://www.binarycarpenter.com/
 * Description: Enable ajax product search
 * Version: 1.0.0
 * Author: BinaryCarpenter.com
 * Author URI: https://www.binarycarpenter.com
 * License: GPL2
 * Text Domain: bc-ajax-product-search
 * WC requires at least: 3.0.0
 * WC tested up to: 3.6.3
 */


class BC_AJAX_Product_Search
{
	public function __construct() {

		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin'));
		add_action('admin_menu', array($this, 'add_to_menu'));

	}


	public function add_to_menu()
	{
		add_menu_page(
			'BC Product Search',
			'BC Product Search',
			'manage_options',
			'bc-product-search',
			array($this,'plugin_ui')
		);
	}

	public function plugin_ui()
	{

	}


	public function enqueue_admin() {
		wp_register_style('my-plugin-select2-style', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css');
		wp_enqueue_style('my-plugin-select2-style');

		wp_register_script('my-plugin-select2-script', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js', array('jquery'));
		wp_register_script('my-plugin-script', plugins_url('static/scripts.js', __FILE__), array('jquery'));
		wp_enqueue_script('my-plugin-select2-script');
		wp_enqueue_script('my-plugin-script');
	}


}

new BC_AJAX_Product_Search();

As you can see, I have enqueue select2 from a CDN. In addition, I also enqueued a Javascript file called scripts.js. This is where we put all our Javascript code.

Finally, I have added a blank function for displaying the UI: plugin_ui. This is the function that output the HTML for the plugin. Let’s do that next.

Create HTML structure

HTML code for this plugin is very simple. We only need a blank select with class. Let’s add that:

public function plugin_ui()
	{ ?>
		<h1>Select your products</h1>
		<select data-security="<?php echo wp_create_nonce( 'search-products' ); ?>" multiple style="width: 300px;" class="bc-product-search"></select>
	 <?php }

As you can see, I enabled multiple setting for this select box. You can disable that if you don’t want to.

This is what we have so far:

Create WooCommerce Products Search Input For Your Plugins 1

That’s all we need to add for our HTML. Let’s make the product search works with Javascript.Write the needed Javascript to enable search.

Write the needed Javascript to enable search

Let’s put the following code in scripts.js

(function ($) {
    $(function(){
        $('.bc-product-search').select2({
            ajax: {
                url: ajaxurl,
                data: function (params) {
                    return {
                        term         : params.term,
                        action       : 'woocommerce_json_search_products_and_variations',
                        security: $(this).attr('data-security'),
                    };
                },
                processResults: function( data ) {
                    var terms = [];
                    if ( data ) {
                        $.each( data, function( id, text ) {
                            terms.push( { id: id, text: text } );
                        });
                    }
                    return {
                        results: terms
                    };
                },
                cache: true
            }
        });
    });

})(jQuery)




Save the file and check the plugin. The product search is now working.

How to get data from the select box

If you have used select2 before, getting value from select2 select boxes shouldn’t be alien to you. For those who don’t know, it’s very simple.

Let’s add a button to log the values of the select box:

<button class="show-selected-results">Show select results</button>
$('.show-selected-results').on('click', function(){
       console.log($('.bc-product-search').val());
});

Now we have the button:

Create WooCommerce Products Search Input For Your Plugins 2

When you click on that button, open the console of your browser, you should see the values:

product search result

As you can see, they are an array of product ids.

Conclusion

As you can see, it is quite simple to add product search function in your plugin. Hopefully this post is valuable to you. If you have any questions, please let me know.

Posted on 2 Comments

Finally A Browser Without Cache – Web Developer Dream!

Finally A Browser Without Cache - Web Developer Dream! 3

If you are reading this post (not by accident), I can safely assume that you share with me the frustration with browser cache. For normal users, browser cache is great since it speeds up website loading, save bandwidth…

But for web developers, it’s something different:

Finally A Browser Without Cache - Web Developer Dream! 4

Well, imagine you have changed some CSS to your button, you reload your browser, nothing changed!

Despite the fact that you have:

  • Open developer tools, check clear browser cache
  • Installed the best cache browsing addon/extensions you can find and clicked the clear cache button hundred times

Still, your new style doesn’t show.

Browser cache is to blame.

If you feel the pain, read on.

I understand why browser makers implement caching. But, I wondered if there was a browser that doesn’t  have cache so I don’t have to spend hours working on my code, wonder why it isn’t working only to realize that there is nothing wrong with my code but browser’s cache?

The browser without cache didn’t exist, until now

I tried to find that browser but it didn’t exists (during my search). So, accidentally, I think of selenium. It’s a browser automation tool that let us do a lot of cool things with browsers. (SEO guys are more familiar with this concept). It turned out, selenium is the solution to my problem.

I ended up creating a small javafx app to let me spawn browsers without cache to load my development websites.

And it worked perfectly.

Let me show you how it works.

How does the browser without cache work

This is the application:

Main interface

Finally A Browser Without Cache - Web Developer Dream! 5

Settings interface

Finally A Browser Without Cache - Web Developer Dream! 6

As you can see that, on the main interface, you can enter your URL, select the browser you want to spawn and click on start browser. You have two choices of browser, Chrome or Firefox.

On the settings panel, you need to set the path to Chrome driver and Firefox driver. What are they? You can download Chrome driver here:

Download Chrome driver

And Gecko driver (Firefox) here:

Download gecko driver

Make sure you select the right version for your OS.

The favorite URL box is where you can enter list of URLs that you want to appear on the box on the left. Later, you can just double click on those URLs to open the browser.

Where to download the app

You can download the app here:

Download no browser cache app

If you want to develop further, feel free to get the source code here:

https://github.com/datmt/NO-FUCKING-CACHE-BROWSER

Questions and suggestions are welcome.

Posted on 2 Comments

The Ultimate Nginx Configuration For WordPress Website

The Ultimate Nginx Configuration For WordPress Website 7

So recently I decided to move my server from HostGator to DigitalOcean droplets. In comparison, DigitalOcean has so many benefits over HostGator, especially for developer. The most notable are:

  1. Full root access
  2. You can install anything you want on DigitalOcean
  3. Free SSL (Let’s encrypt)
  4. Cheaper
  5. More powerful server (2GB of RAM, 50GB SSD, 2TB transfer for just $10/month)

My website was running on Apache server at HostGator. As I’ve heard so many good things about Nginx, I decided to make the change. Installing Nginx was easy. However, as I’m not familiar with Nginx, I spent more than a day to solve these two issues:

  1. Website is not accessible. I got 502 Bad Gateway error every time I try to access my site.
  2. When I was able to access my site. All pages/posts are 404 except the home page.

So, to save you time, I’m going to share my configurations so you can follow and get your site up and running fast on Nginx.

Configure PHP FPM

First, let’s edit you php-fpm www.conf file. I’m running php7.2 so the file is located here:

/etc/php/7.2/fpm/pool.d/www.conf

However, if you are running a different php version, you may have different path. The trick is to cd from /etc the ls to see the list of folders. For example, if you have php 7.3, the path would be:

/etc/php/7.3/fpm/pool.d/www.conf

Edit the file using your favorite editor. I’m using vim so I type:

vim /etc/php/7.2/fpm/pool.d/www.conf

Let’s navigate to the line says:

listen = /run/php/php7.2-fpm.sock

Comment that line by placing a ; at line start and type the following line below:

listen = 127.0.0.1:9000

Now it will look like this:

 

configure php-fpm www.conf

Save your file and restart php fpm. I’m on ubuntu 18.04 so my command to restart php fpm is this:

systemctl restart php7.2-fpm

However, if you are on a different server, the command could be different. You can google for the exact command for your system.

Configure your site’s server block

Let’s go to:

/etc/nginx/sites-available/

And create a file match your domain name. For example, my site is excelautocomplete.com, I’ll create file called excelautocomplete.com

vim excelautocomplete.com

then enter the following content to the file:

# WordPress single site rules.
# Designed to be included in any server {} block.
# Upstream to abstract backend connection(s) for php
upstream php {
        server unix:/tmp/php-cgi.socket;
        server 127.0.0.1:9000;
}

server {
        ## Your website name goes here.
        server_name domain.tld;
        ## Your only path reference.
        root /var/www/wordpress;
        ## This should be in your http block and if it is, it's not needed here.
        index index.php;

        location = /favicon.ico {
                log_not_found off;
                access_log off;
                expires max;
        }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location / {
                # This is cool because no php is touched for static content.
                # include the "$is_args$args" so non-default permalinks doesn't break when using query string
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include fastcgi.conf;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
                fastcgi_buffers 16 16k;
                fastcgi_buffer_size 32k;
        }

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                access_log off;
                log_not_found off;
        }
}

You need to pay close attention to two fields:

  • server_name
  • root

in server_name, type in your website address (without http or https). In the root field, enter the location of your site’s file (the folder that contains wp-content, wp-admin…)

Save the file and reload nginx.

systemctl reload nginx

Now, your site should be up and running without an error.

Conclusion

Moving my website from Apache to Nginx was a challenging but exciting experience for me. I lost a sales due to my customer cannot get to the download page of the product. However, I’ve learned a lot from this experience and next time when I need to move other sites, the whole process would be much faster and easier.

Hopefully, the post has been helpful to you. If you have questions, don’t hesitate to ask.

Posted on Leave a comment

Create and verify password in PHP with new hashing functions

Previously, when creating a login system, I usually take users’ password input and md5 it and store in the database. Doing so seemed to be sufficient enough. However, no one can be sure that their system is not vulnerable to attacks. In the worst case when your site gets hacked, your database is stolen, using weak hashing algorithm on users’ passwords may enable hackers to easily decode such fields. Thus, since PHP 5.5, there are new functions available to help you create an verify password hash easily. Let’s learn what are they and how to use them.

Creating a password hash with password_hash

Creating a password hash in PHP > 5.5 is very simple.

$hash = password_hash('easy-password', PASSWORD_DEFAULT, ['cost' => 12]);

and if you echo the hash, you’ll see something similar to this:

echo "hash is: {$hash}";

Create and verify password in PHP with new hashing functions 8

If you run the script again (reload the browser in my case), you’ll get a new hash string (still same password input!):

Create and verify password in PHP with new hashing functions 9

This is quite strange for people who are familiar to md5. In md5, for one input, there is one output. In this case, one input generates multiple outputs. This makes the effort to create a dictionary to map easily-to-guess passwords and their hashes become worthless.

password_hash takes 3 parameters:

  1. The raw password. This is what the users enter along with their email/id to login to your application
  2. The hashing algorithms. There are a few of them you can find out here.
  3. Additional options. Additional options which most of the time consists of the cost option. In the example, I used cost = 12. Higher cost provides higher security but takes more time.

Verify the password with password_verify

To verify the validity of a password hash, we’ll use password_verify. Consider the case of user login, they will provide the raw password (without hashing). Our application will get the hash password in the database and verify if the raw password and the hash match.

If you used md5 before, the code may look like this:

if ( md5($raw_user_input) == $password_hash_in_database )
{
//ok to login
}

However, if you hash the password using password_hash, you’ll use password_verify to verify.

 

if (password_verify($raw_user_input, $password_hash_in_database )
{
//ok to login
}

For example, in my case:

$verified = password_verify('easy-password', '$2y$12$06uHkyogkUveLLLVIFhvsOFzpBrYkZ8XIegVdwj0RtE/zI/dzfHnq');

echo "verify is: {$verified}";

The output is:

Create and verify password in PHP with new hashing functions 10

You can see that the hash was successfully verified.

That’s what I learned today. This is a part of 7 days challenges to learn one topic every day. Thanks for reading

Posted on Leave a comment

Quick Composer Tutorial – Learn Composer PHP in 10 Minutes

I’ve been writing code in PHP for more than 5 years and it’s a shame to admit that I didn’t know composer until recently. I’ve read some tutorials but couldn’t get my head around it. I  have to admin that since I code mostly small web projects (WordPress plugins…) I don’t find the need for a package manager. However, to call myself a PHP developer, I have to know its most popular package manager. In this post, I’m going to share my understanding with composer, how to get started with it so you might benefit from my experience too.

What is composer?

Composer is a package manager tool that helps you deal with PHP dependencies. Previously, when I didn’t use Composer, I mostly use include_once to include the libraries. In addition, I had to download the libraries and put to my project all by myself. It’s no longer the case with composer.

Let’s see how it works.

Installing Composer

Installing composer is simple for all environment. If you are on Windows, you can download the installation file and go through the process in just a minute. I’m not going too much into details here since there directions on https://getcomposer.org is detailed enough.

Using composer

Using composer is a very straightforward process. We first tell composer what library to include and it will get that library for us.

Start a fresh project with composer
Now we have composer installed, let’s get started and create an empty folder and type in

composer init

The console will walk you through various steps to get information about the project you want to create. I use the default option for most of the question. After finishing all the steps, composer will create a composer.json file. Open this up and you’ll see the content you’ve just entered.

Here is the content of the composer.json

{
    "name": "myn/lab",
    "description": "This is a test composer project",
    "license": "MIT",
    "require": {}
}

As you can see, the “require” element is just an empty object. When we include dependencies, all of them will be listed here.

Adding libraries to composer

Now, we have a composer project. Let’s add a library and use it. I’m going to include a logging library called monolog in the project. You can find details about that project here.

To get the monolog library, simply run:

composer require monolog/monolog

Composer will go ahead and get monolog and also its dependencies (if any) for us.

If you check the composer.json, you’ll see it is updated:

{
    "name": "myn/lab",
    "description": "This is a test composer project",
    "license": "MIT",
    "require": {
        "monolog/monolog": "^1.24"
    }
}

Now, let’s write some code to use monolog.

Include the autoload.php file

If you notice, composer also created a folder called vendor. Inside it lies the libraries and one file called autoload.php. When creating php script, you simply include the autoload.php file to have access to all dependencies you installed.

I’m going to create an index.php in the root folder and include the autoload.php file.

<?php

require 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;


$log = new Logger('test-logger');
$log->pushHandler(new StreamHandler('C:\\xampp\\htdocs\\lab\\log.txt', Logger::WARNING));

$log->warning("Testing monolog");

If I run the file now, there will be a log.txt file created at C:\xampp\htdocs\lab with the below content:

 

[2018-12-10 09:55:15] test-logger.WARNING: I do some test [] []

You may wonder how do I know to type in the code in the php file? Well, the maker of monolog provides example code on the library page on packagist.

Conclusion

Now I have a basic understanding of composer, the PHP package manger. I hope this post can help you understand composer a bit better. I still have a lot to learn and I’ll share all my findings here with you.