Tuesday, October 16, 2018

Do Not Use Cookies as The Way We Use Variables

How to Add Constants in Larvel 5

Considering the code as follows:

<?php
  setcookie("test", "1", time() + 3600);  // set cookie
  echo $_COOKIE["test"];
?>

The result shows ‘undefined index’ after execution:

Notice: Undefined index: test in /xxx/index.php on line 2

Why is this happened? Has cookie not been set?
No, it is because the browser hasn’t sent a HTTP request to the server, so the browser hasn’t got the request cookie yet.

According to the document rfc6252 from Internet Engineering Task Force (IETF), it explains how cookies work at the introduction:

Using the Set-Cookie header field, an HTTP server can pass name/value pairs and associated metadata (called cookies) to a user agent. When the user agent makes subsequent requests to the server, the user agent uses the metadata and other information to determine whether to return the name/value pairs in the Cookie header.

Hmm~~, what does that mean exactly?

Let’s open the Chrome Developer Tools and show you how cookies works.

I wrote three php programs as follows:

  1. set_cookie.php: to set cookie ‘test’ and value as 1.
<?php
  setcookie("test", "1", time() + 3600);
  echo $_COOKIE["test"];
?>
  1. show_cookie.php: show the value of cookie ‘test’.
<?php
  echo $_COOKIE["test"];
?>
  1. delete_cookie.php: delete the cookie 'test.
<?php
  setcookie("test", "", time() - 3600);
?>

Check the cookies in Chrome Devtools

  1. Now, let’s start to run set_cookie.php and see what will happen through Chrome devtools. In Chrome devtools windows, there is a Response Cookie ‘test’ as 1 shown in the ‘Cookies windows’. The cookie ‘test’ is not shown at the side of ‘Request Cookies’ meaning that the browser hasn’t received cookie data from server yet. So, it shows ‘undefined index’ message in the browser as expected.

run set_cookie.php
set_cookie

  1. Next, let’s run show_cookie.php to send a HTTP request to the server and show the cookie ‘test’. It shows cookie ‘test’ and value as 1 at the side of ‘Request Cookies’. As expected, the browser shows ‘1’, the value of cookie ‘test’.

run show_cookie.php
show_cookie

  1. let’s run delete_cookie.php to delete the cookie ‘test’. It shows a ‘delete’ value at the side of ‘Response Cookies’. The cookie ‘test’ and value 1 is still at the side of ‘Request Cookies’.

delete_cookie.php
delete_cookie

  1. Let’s run show_message.php again to send a HTTP request to the server. It also send the response cookies to the server and delete the cookie ‘test’. The cookie ‘test’ has disappeared at both sides of the ‘Cookies windows’. Therefore, it shows ‘undefined index’ in the browser again.

show_cookie again
show_cookie again

Use cookies for storing data while variables for calculation.

As shown above, the behavior of cookies are different from variables. We can not use cookies just as the way we use variables.

Do not make the calculation according to cookies values if a HTTP request hasn’t been sent to the server. Using variables to do so to make sure the correct calculation.

Friday, October 12, 2018

Four Ways to Show Message Bar After Redirecting to Another Page in PHP

How to Add Constants in Larvel 5

There are four ways to show a message bar up front of the web page when needed in PHP. As shown below, the main function of the message bar is to notify users a warning message.

Message Bar

Four ways to build up a message bar are as follows:

1. Passing message by assigning a smarty variable.

index.php

<?php    
         :
$msg = 'Please login!';
         :
$smarty->assign('msg', $msg);    
// redirect to index.html
$smarty->display('index.html'); 
  
?> 

index.html

{if (isset($msg)}
  {$msg}
{/if}

It works very good except one situation: program redirects to another page and exits the original one before Smarty variable has been assigned.

Considering a situation below:

<?php
         :
if !login() {
  $msg = 'Please login!';
  header("location:login.php");
  exit;
}
         :
$smarty->assign('msg', $msg);    
// redirect to index.html
$smarty->display('index.html'); 
?>

Normally, we put $smarty->assign('msg', $msg); at the end of index.php file. It will not work in the above example since a header() command redirects to the login page and exits index.php. $msg will not be assigned to a Smarty variable.

2. Query string parameters

ex.
shopping_cart.html

<a href="index.php?msg=Cart is empty!">Empty Cart</a>  

index.php

$msg = isset($_REQUEST['msg']) ? 
  filter_var($_REQUEST['msg'], 
  FILTER_SANITIZE_MAGIC_QUOTES) : '';
echo $msg;

It shows a long line of words in the url windows of the browser. I really don’t like it. It is not a good way to do it.

ex.
index.php

      :
setcookie('msg', 'Hello! New user!', time() + 365*86400);
      :
function show_message() {
  $msg = $_COOKIE['msg'];
  setcookie('msg', '', time() - 3600);
  return $msg;
} 

index.html

{if isset($smarty.cookies.msg)}
  {show_message()}
{/if}  

It seems to be a good solution, However, it resulted in some unexpected error while using cookie method. It was not stable when I tested it. The browser could not render the correct page. I recommend not to use it.

4. Using Session

ex.
index.php

<?php
session_start();
       :
       :
write_message('Hello! New user!');
header("location:{$_SERVER['HTTP_REFERER']}");
  
function write_message($msg = '') {
  $_SESSION['msg'] = $msg;
}

function show_message() {
  $msg = $_SESSION['msg'];
  unset($_SESSION['msg']);
  return $msg;
}
?> 

index.html

{if isset($smarty.session.msg)}
  <div class="alert alert-danger alert-dismissible show" role="alert">
    {show_message()}
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
{/if} 

The session method is the most recommended method to show a message bar at the redirected page. It’s quite easy, simple and no restriction at all. You can insert write_message('xxxxx') anywhere in code and it will show up in the redirected page. The only one drawback to criticize is that it consumes server’s resources since session runs on the server.

Tuesday, September 25, 2018

Few Notes about TCPDF - An Open Source PHP class for generating PDF documents

Few Notes about TCPDF - An Open Source PHP class for generating PDF documents

TCPDF is an open source PHP class for generating PDF documents. It is easy to install and setup as well as many options available. There are few things worth to be noticed in my experience of usage. Here are some:

1. Installation

To install TCPDF class is easy.

  1. Download all files from TCPDF’s github.
  2. Create a directory class under the main directory of the Site.
  3. Create a directory class/tcpdf.
  4. Copy all files to class/tcpdf.
  5. Add a line of code in the beginning of the php file:
    require_once "class/tcpdf/tcpdf.php";
  6. Have fun!

2. Traditional Chinese support

The default setting of TCPDF does not support Traditional Chinese character because it lacks of fonts in Traditional Chinese. We have to add the font files manually.

  1. Download font file ‘Droid Sans Fallback’ and ‘msungstdlight’.
  2. Add two font files to class/tcpdf/fonts.
  3. Open config/tcpdf_config.php and change two settings:
    define ('PDF_FONT_NAME_MAIN', 'helvetica');
       to
    define ('PDF_FONT_NAME_MAIN', 'msungstdlight');
    
    define ('PDF_FONT_NAME_DATA', 'helvetica');
    	to
    define ('PDF_FONT_NAME_DATA', 'msungstdlight');
    

p.s Here explains how to generate TrueTypeUnicode font files from DroidSansFallback.ttf font file.

3. A bug fixed while using PHP 7.2

When using PHP 7.2, TCPDF version 6.2.12 shows the error message:

Deprecated: The each() function is deprecated. 
This message will be suppressed on further calls in /Users/xxx/Sites/mini_shop/class/tcpdf/tcpdf.php on line 16544
  
TCPDF ERROR: Some data has already been output, 
can't send PDF file

Since each() function is deprecated after PHP version 7.2, the code must be modified in order to fit the new version. Fortunately, somebody has posted the solution. It works again just to replace three lines of code in tcpdf.php as follows:

-  while (list($key, $val) = each($prop)) {
+  foreach($prop as $key => $val) {
-  while (list($id, $name) = each($attr_array[1])) {
+  foreach($attr_array[1] as $id => $name) {
-  while (list($id, $name) = each($style_array[1])) {
+  foreach($style_array[1] as $id => $name) {

Replace each() function with foreach() function, and that’s it!

Sunday, September 23, 2018

A Simple CRUD App in PHP

A Simple CRUD App in PHP
The “CRUD” means Create, Read, Update, Delete and is the most frequent functions used in daily operation. Here shows a simple CRUD app in PHP for reference. Let’s follow the methods explained in the article of my blog “Building PHP Web Apps Without Framework” and start to build a product list web site.

Seven Basic Operations

There are seven operations need to identified. They are:
  1. list_products: get and show all products.
  2. show_product: get product data for a specific prod_id.
  3. new_product: get a new form to enter product data.
  4. create_product: create a product and save to database.
  5. edit_product: get and edit product data for a specific prod_id.
  6. update_product update product data of a specific prod_id to database.
  7. delete_product delete product for a specific prod_id.
The operations 3 and 4 are consecutive steps, which mean when a user creates a product by finishing product data entry (operation 3), the system save product data to database at once (operation 4).
Likewise, operation 5 and 6 have the same situation. The system gets and shows the product data on the screen (operation 5), then it saves the data back to database while data has been edited by a user (operation 6).

The Flow Control in “index.php”

Here shows the flow control in “index.php” which variable “$op” decides the program flow.
switch ($op) {
  case 'show_product':
    show_product($prod_id);
    break;
  case 'new_product':
    new_product();
    break;
  case 'create_product':
    $prod_id = create_product();
    header("Location:index.php?op=show_product&prod_id={$prod_id}");
    exit;
    break;
  case 'edit_product':
    edit_product($prod_id);
    break;
  case 'update_product':
    update_product($prod_id);
    header("Location:index.php?op=show_product&prod_id={$prod_id}");
    exit;
    break;
  case 'delete_product':
    delete_products($prod_id);
    header("Location:index.php");
    exit;
    break;
  default:
    list_products($keyword);
    break;
}

Monday, September 17, 2018

Building PHP Web Apps Without Framework

Building PHP Web Apps Without Framework
Building a PHP web app using a framework such as Laravel, Symfony and CakePHP is a straight-forward job. Just arrange functions according to the rules set by the framework, programmers usually can get the job done. However, learning the framework itself is not a very easy task. There are a lot of concepts, ideas, knowledge to learn. Learning time is quite long.
What if to build a PHP web app without using a framework? Just utilizing few basic tools such as template engine, and setting up some rules for passing parameters between web pages, a simple PHP web app is easy to build. Let’s find out!

Setup A Circulation Mechanism of Web Pages

Normally, the entry point of a web is index.html, it is index.php if programmed by PHP. So we can identify the direction is:
index.php -> index.html -> user interaction
   ^                               | 
    \----------------------------- /
Which means the system redirects to index.html at the end of index.php. Any operation triggered by pressing a button at index.html will start running from index.php with or without parameters again. The according operation is executed depends on the parameters POSTED by the former index.html. After the required operation executed, the system redirects to index.html with some other parameters passed. The index.html shows the pages accordingly again. Then the circulation mechanism is built.

Passing Parameters - Smarty Template Engine

How to passing parameters between pages? The answer is Smarty Template Engine. Here is how:
  1. Download Smarty and stored in a subdirectory /smarty/lib.
  2. Place these two lines of code at the beginning of index.php.
    require_once('smarty/libs/Smarty.class.php');
    $smarty = new  Smarty;
    
  3. place code as follows at the end of index.php.
    $smarty->assign('op', $op);
    $smarty->display('index.html');
    
Notice that ‘op’ means operation parameter. It is used to control the program flow in order to execute the required operation.
The last line is to display index.html. Therefore the program flow goes to the html rendering part.

Starting Web Page

We start from index.php with default (no) parameter passing to index.html. And html pages is rendered by default.
Imaging that there is a link shown as follows:
<a href="index.php?op=list_products">
If we press the link, it goes back to index.php with ‘op=product_display’ parameter.
That is the user interaction designed for user to decide to at the web page. Now the system goes back to index.php.

The ‘op’ Parameter and Flow Control

The flow control of index.php is decided by the ‘op’ parameter. $op variable is initialized and copy value from the session variable $_REQUEST[‘op’].
$op = isset($_REQUEST['op']) ? filter_var($_REQUEST['op'], FILTER_SANITIZE_MAGIC_QUOTES) : '';
A flow control built by switch to decide which operation is made.
switch ($op) {
  case 'list_products':
    $op = "list_products";
    list_products();
    break;
      :
      :
  default:
 show_default();  
    break;  
}
Also, a function list_products() in index.php is made:
function  list_products() {
  global  $mysqli, $smarty;

  $products = "";
  $sql = "SELECT  *  FROM products";
  $result = $mysqli->query($sql) or die($mysqli->connect_error);
  $products = $result->fetch_all(MYSQLI_ASSOC);
  $smarty->assign('products', $products);
}
A variable $products is passed to index.html for rendering web page.

Flow Control in the Web Page

The index.html is composed by at least three parts of html files. They are ‘head part’, ‘main part’ and ‘foot part’. The ‘main part’ is the place where flow control works. The following Smarty code acts as the control part. The system include list_products.html while $op == 'list_products', where shows all products.
<!DOCTYPE html>
<html lang="en">
  <head>
       :
  </head>
  <body>
    {if $op == 'list_products'}
   {include file = "list_products.html"}
    {elseif}
       :
    :
    {else}
       :  
    {/if}
       :
       :
  </body>
</html>
The sample code of list_products.html is as follows:
<div class="row">
  {foreach from=$products item=product}
    <img src="uploads/thumbs/{$product.prod_id}.png"  alt="{$product.prod_name}">
    <a href="index.php?prod_id={$product.prod_id}">{$product.prod_name}</a>
    price:{$product.prod_price}
    counter:{$product.prod_counter}
  {/foreach}
</div>
As shown above, the $op variable can be used as the key of the flow control. The system shows different web pages by composing different sub web pages in the main part according to $op. Now the flow stops at index.html again with new contents where allows user to trigger a new action again.

Friday, September 7, 2018

Reset AUTO_INCREMENT in MySQL

Reset AUTO_INCREMENT in MySQL

When creating a new record in MySQL server with a primary key, the “id” field (the primary key) is set to be auto incremented. Meaning the value of the primary key (“id” field) starts from 1, and the value of the primary key of the next record is increased by 1, which is 2. MySQL server takes cares of it without user interference.

What if the records have been deleted, and the primary key has to be reset to 1?

We can reset the counter with:

ALTER TABLE tablename AUTO_INCREMENT = 1

The primary key is reset to 1.

Thursday, August 16, 2018

RENAME DATABASE name in MySQL

RENAME DATABASE name in MySQL

1. “RENAME” command

Syntax:

RENAME DATABASE db_name TO new_db_name

There is the “rename database” command for the early MySQL version, but it was removed after version 5.1.23. It was because the possibility of data lost when using it.

p.s. There shows an error when using "“rename database”:

mysql> rename database shop to mini_shop;  
ERROR 1064 (42000): You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version 
for the right syntax to use 
near 'database shop to mini_shop' at line 1

2. Create a new database, rename all tables of old database to new one. Then drop the old database.

CREATE DATABASE new_db_name;  
RENAME TABLE db_name.table1 TO new_db_name.table1,  
db_name.table2 TO new_db_name.table2;  
DROP DATABASE db_name;

Using Docker to Install MySQL server

Using Docker to Install MySQL server
  1. Go to docker official site, download docker file and install in the local machine.

  2. Start docker, type in the following command to ensure docker is running.

    docker images

  3. Download MySQL image form docker hub with following commands.

    docker pull mysql/mysql-server

    docker pull mysql/mysql-server:5.7 (version 5.7)

  4. Start MySQL server in the container, forward the port out for host connection.

    docker run --name mysqld -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql/mysql-server

    or

    docker run --name mysql57 -e MYSQL_ROOT_PASSWORD=1234 -d -p 3306:3306 mysql/mysql-server:5.7

    -e: Set environment variables

  5. Host connects to MySQL server in docker.

    docker exec -it mysqld bash

    bash> mysql -u root -p (ask for password)

    Using sequel pro , a free GUI to manipulate MySQL server. MySQL Workbench is another good choice!

  6. Stop the container.

    docker stop mysqld

  7. Start the container.

    docker start mysqld

  8. List port mappings or a specific mapping for the container

    docker port mysqld

  9. Remove container.

    docker rm mysqld

  10. Local host client can not connect to the MySQL server since ‘root’ is limited to localhost connection (within the container).

mysql> select host, user from mysql.user;  
+-----------+---------------+  
| host      |      user     |  
+-----------+---------------+  
| localhost | healthchecker |  
| localhost | mysql.session |  
| localhost | mysql.sys     |  
| localhost | root          |  
+-----------+---------------+  
4 rows in set (0.00 sec)

Change root’s access right for all machines.

mysql> update mysql.user set host='%' where user='root';

mysql> select host, user from mysql.user;  
+-----------+---------------+  
|   host    |     user      |  
+-----------+---------------+  
|    %      |     root      |  
| localhost | healthchecker |  
| localhost | mysql.session |  
| localhost | mysql.sys     |  
+-----------+---------------+  
4 rows in set (0.00 sec)

Restart docker afterward.

docker restart mysql57

Tuesday, July 3, 2018

Enable the "Sites" to be "http://localhost/~username" on macOS

Enable the "Sites" to be "http://localhost/~username" on macOS

There are actually two places where macOS serves website by default:

However, the second one needs setups to activate.

To make http://localhost/~username/ work, just follow the procedures below to configure:

1. Add a user’s config file /etc/apache2/users/username.conf.

<Directory "/Users/username/Sites/">
    Options Indexes MultiViews
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

2. Turning on Modules in /etc/apache2/httpd.conf

First, copy a httpd.conf backup.

$ sudo cp httpd.conf httpd.conf.bak

Then edit the httpd.conf.

$ sudo vi httpd.conf

Uncomment the following lines:
( remove “#” at the beginning of the line.)

LoadModule authz_host_module libexec/apache2/mod_authz_host.so
LoadModule authz_core_module libexec/apache2/mod_authz_core.so
LoadModule userdir_module libexec/apache2/mod_userdir.so
LoadModule vhost_alias_module libexec/apache2/mod_vhost_alias.so

Include /private/etc/apache2/extra/httpd-userdir.conf
Include /private/etc/apache2/extra/httpd-vhosts.conf

Save and close vi while finished.

3. Edit /etc/apache2/extra/httpd-userdir.conf.

Go to /etc/apache2/extra/ folder and make a backup of httpd-userdir.conf.

$ sudo cp httpd-userdir.conf httpd-userdir.conf.bak

Then edit httpd-userdir.conf.

$ sudo vi httpd-userdir.conf

Uncomment the following line:
( remove “#” at the beginning of the line.)

Include /private/etc/apache2/users/*.conf

Save and close vi while finished.

4. Restart Apache

$ sudo apachectl restart

Type http://localhost/~username/index.html.en in the browser, it works! ( where username is the user’s name. )

Then type http://localhost/~username in the browser, it shows the index of the “Sites” and lists all files in the “Sites” directory. Now, I can put my web site in the “Sites” directory. Great!

Monday, July 2, 2018

Show username only without hostname in zsh agnoster theme

Show username only without hostname in zsh agnoster theme

Agnoster theme is a pretty good theme for my zsh terminal. However, the hostname is too long nearly over a half of the screen. I have found a way to reduce the length and show username without hostname. it’s very easy, just to remove the @%m to in the theme file.

1. Open the theme file.

~/.oh-my-zsh/themes/agnoster.zsh-theme

2. Search prompt_context.

# Context: user@hostname (who am I and where am I)
prompt_context() {  
  if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then
    prompt_segment black default "%(!.%{%F{yellow}%}.)$USER@%m"
  fi
}

3. Remove @%m after $USER, then save it.

# Context: user@hostname (who am I and where am I)
prompt_context() {  
  if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then
    prompt_segment black default "%(!.%{%F{yellow}%}.)$USER"
  fi
}

And That’s it!

Saturday, June 30, 2018

Upgrade PHP version from 5.6 to 7.2 on macOS Sierra (10.12)

Upgrade PHP version from 5.6 to 7.2 on macOS Sierra (10.12)

The PHP version 7.0.0 is released on 03 Dec 2015. It has been three years since then, however, the PHP version installed originally on macOS Sierra (10.12) is still 5.6. I would like to upgrade PHP version in my mac, here are the upgrade procedures to the version 7.2.

First, let’s find out the PHP version number.

$ php -v
PHP 5.6.30

Actually , There are two ways to upgrade PHP.

1. Homebrew

Homebrew is a famous package manager for macOS. It is very easy to use and very powerful.

First, let’s find out which PHP version is available in Homebrew’s package list.

$ brew search php7
==> Searching local taps...
php@7.0   php@7.1    php@7.2

Let’s install the latest version ‘7.2’. Just excute the following commands to install.

  • a. Update the brew package first.
$ brew update && brew upgrade
  • b. Error messages occurs with following commands. Actually, these commands are no longer needed. Therefore, they can be ignored.
$ brew tap homebrew/dupes
$ brew tap homebrew/versions
$ brew tap homebrew/homebrew-php

p.s. Error message: some of the taps are no longer needed.

$ brew tap homebrew/dupes
Error: homebrew/dupes was deprecated. This tap is now empty as all its formulae were migrated.
 $ brew tap homebrew/versions
Error: homebrew/versions was deprecated. This tap is now empty as all its formulae were migrated.
$ brew tap homebrew/homebrew-php
Error: homebrew/php was deprecated. This tap is now empty as all its formulae were migrated.
  • c. Unlink the old version of PHP if it was installed with Homebrew.
$ brew unlink php56 
  • d. Install the new version of PHP.
$ brew install php72

After installation, it shows:
To enable PHP in Apache add the following to httpd.conf (/etc/apache2) and restart Apache:

  • e. Using vim edit httpd.conf of apache2.
$ sudo vim /etc/apache2/httpd.conf

If you don’t like to edit using vim, go to Finder and type:

$ open /etc/apache2/

Search “php5_module” then commend out the statements as follows:

#Comment out the PHP5 module
#LoadModule php5_module libexec/apache2/libphp5.so

Add the commands as follows:

#Enable PHP 7 module
LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>
  • f. Finally, check DirectoryIndex includes index.php
    DirectoryIndex index.php index.html

The php.ini and php-fpm.ini file can be found in:
/usr/local/etc/php/7.2/

To have launchd start php now and restart at login:

$ brew services start php

Or, if you don’t want/need a background service you can just run:

$ php-fpm
==> Summary
 /usr/local/Cellar/php/7.2.7: 515 files, 78.9MB
  • g. Restart Apache service
$ sudo apachectl restart
  • h. check the php version:
$ php -v
PHP 7.2.7 (cli) (built: Jun 22 2018 06:29:00) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

Done!


Other brew commands for reference

  • brew tap: to list and update the repositories exist in local computer.
$ brew tap
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
No changes to formulae.
  • brew tap (user)/(repo): to download the 3rd party formula repositories (user)/(repo). If you want to install a package listed in a certain formula repository, the formula repository must be tapped first.

  • brew untap (user)/(repo): delete the 3rd party formula repositories (user)/(repo).

  • brew cleanup: a little tip, clean up old downloads and the files from the Homebrew download-cache are deleted.

$ brew cleanup
Removing: /Users/xxxx/Library/Caches/Homebrew/node-10.4.1.sierra.bottle.tar.gz... (16MB)
   :
   :
==> This operation has freed approximately 5.4GB of disk space.

5.4GB! It’s quite a lot of space.

  • brew doctor: fix your Homebrew repository.

2. CURL

Another option is to execute a curl command provided by php-osx.liip.ch which downloads the binary package from the website and installs it to my mac. This one-line installation is for PHP 7.2 (Current stable) and macOS 10.10 and later.

curl -s https://php-osx.liip.ch/install.sh | bash -s 7.2
  • One little problem mentioned on the php-osx.liip.ch website is: php -v echoes the old version number after installation. The explanation given by php-osx is:

php-osx doesn’t overwrite the php binaries installed by Apple, but installs everything in /usr/local/php5. The new php binary is therefore in /usr/local/php5/bin/php.

You can also adjust your PATH do include that directory, eg. write into your ~/.profile file the following

The solution is to add the path /usr/local/php5/bin to global variable $PATH.

export PATH=/usr/local/php5/bin:$PATH  

I choose the first method since it is really convenient to manage and install packages utilizing Homebrew.