May 22, 2015

Simple Image Gallery CRUD with CodeIgniter 3

Go into folder application/config/ and open file routes.php where you can find the default controller. Change it to:
$route['default_controller'] = 'gallery';

Database Structure

CREATE TABLE IF NOT EXISTS `images` (
  `id` int(10) NOT NULL,
  `file` text NOT NULL,
  `caption` text NOT NULL,
  `description` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

The Model

To interact with data in the database, we should first create a model for our gallery. Now go into folder application/models/ then create a new file Gallery_model.php. Our model structure should be designed like this:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Gallery_model extends CI_Model {

 public function all() {}

 public function find($id) {}

 public function create($data) {}

 public function update($id, $data) {}

 public function delete($id) {}

}

To create a new record storing our uploaded image, we write a function called create($data). The parameter should be in associative array format containing our image data. And if something goes wrong while inserting, we should echo out the errors.
   public function create($data)
   {
      try{
         $this->db->insert('images', $data);
         return true;
      }catch(Exception $e){
         echo $e->getMessage();
      }
   }
To retrieve all records from our table, we write a function called all() and it should be as simple as this:
   public function all()
   {
      $result = $this->db->get('images');
      return $result;
   }
To retrieve a specific record identified by it's ID, we can write a function called find($id). The parameter is an integer identifying the record we are looking for.
   public function find($id)
   {
      $row = $this->db->where('id',$id)->limit(1)->get('images');
      return $row;
   }
To update a record, we need to know the ID of record and also the new data to replace the old ones. In this case, we can write a function called update($id, $data). The first parameter is an integer and the second one should be a variable representing an associative array format.
   public function update($id, $data)
   {
      try{
         $this->db->where('id',$id)->limit(1)->update('images', $data);
         return true;
      }catch(Exception $e){
         echo $e->getMessage();
      }
   }
Lastly in our model, is the delete($id) function. The only parameter we need is an integer defining ID of the record we want to delete.
   public function delete($id)
   {
      try {
         $this->db->where('id',$id)->delete('images');
         return true;
      }

      //catch exception
      catch(Exception $e) {
        echo $e->getMessage();
      }
   }
That's it! We have just finished the model. Next we are going to design three HTML files for the views.

The Views

The first HTML file will be a list of all uploaded images on the gallery. Create a new file under the application/views/gallery/ directory and name it index.php.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?><!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>CodeIgniter Image Gallery</title>

   <link href='http://fonts.googleapis.com/css?family=Oxygen' rel='stylesheet' type='text/css'>
   <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
   <style type="text/css">

   ::selection { background-color: #E13300; color: white; }
   ::-moz-selection { background-color: #E13300; color: white; }

   body {
      background-color: #fff;
      margin: 40px;
      font: 16px/24px normal 'Oxygen', sans-serif;
      color: #4F5155;
   }

   a {
      color: #003399;
      background-color: transparent;
      font-weight: normal;
   }

   h1 {
      color: #444;
      background-color: transparent;
      border-bottom: 1px solid #D0D0D0;
      font-size: 19px;
      font-weight: normal;
      margin: 0 0 14px 0;
      padding: 14px 15px 10px 15px;
   }

   code {
      font-family: Consolas, Monaco, Courier New, Courier, monospace;
      font-size: 12px;
      background-color: #f9f9f9;
      border: 1px solid #D0D0D0;
      color: #002166;
      display: block;
      margin: 14px 0 14px 0;
      padding: 12px 10px 12px 10px;
   }

   #body {
      margin: 0 15px 0 15px;
   }

   p.footer {
      text-align: right;
      font-size: 11px;
      border-top: 1px solid #D0D0D0;
      line-height: 32px;
      padding: 0 10px 0 10px;
      margin: 20px 0 0 0;
   }

   #container {
      margin: 10px;
      border: 1px solid #D0D0D0;
      box-shadow: 0 0 8px #D0D0D0;
   }
   </style>
</head>
<body>

<div id="container">
   <h1>CodeIgniter Image Gallery</h1>

   <div id="body">
      <?php if($images->num_rows() > 0) : ?>
         
         <?php if($this->session->flashdata('message')) : ?>
            <div class="alert alert-success" role="alert" align="center">
               <?=$this->session->flashdata('message')?>
            </div>
         <?php endif; ?>

         <div align="center"><?=anchor('gallery/add','Add a new image',['class'=>'btn btn-primary'])?></div>
         <hr />   
         <div class="row">
            <?php foreach($images->result() as $img) : ?>
            <div class="col-md-3">
               <div class="thumbnail">
                  <?=img($img->file)?>
                  <div class="caption">
                     <h3><?=$img->caption?></h3>
                     <p><?=substr($img->description, 0,100)?>...</p>
                     <p>
                        <?=anchor('gallery/edit/'.$img->id,'Edit',['class'=>'btn btn-warning', 'role'=>'button'])?>
                        <?=anchor('gallery/delete/'.$img->id,'Delete',['class'=>'btn btn-danger', 'role'=>'button','onclick'=>'return confirm(\'Are you sure?\')'])?>
                     </p>
                  </div>
               </div>
            </div>
            <?php endforeach; ?>
         </div>
      <?php else : ?>
         <div align="center">We don't have any image yet, go ahead and <?=anchor('gallery/add','add a new one')?>.</div>
      <?php endif; ?>
   </div>

   <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo  (ENVIRONMENT === 'development') ?  'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p>
</div>

</body>
</html>
The second HTML file is the add new image form page. Create a new file under application/views/gallery/ directoy and name it add_image.php.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?><!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>Add New Image</title>

   <link href='http://fonts.googleapis.com/css?family=Oxygen' rel='stylesheet' type='text/css'>
   <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
   <style type="text/css">

   ::selection { background-color: #E13300; color: white; }
   ::-moz-selection { background-color: #E13300; color: white; }

   body {
      background-color: #fff;
      margin: 40px;
      font: 16px/24px normal 'Oxygen', sans-serif;
      color: #4F5155;
   }

   a {
      color: #003399;
      background-color: transparent;
      font-weight: normal;
   }

   h1 {
      color: #444;
      background-color: transparent;
      border-bottom: 1px solid #D0D0D0;
      font-size: 19px;
      font-weight: normal;
      margin: 0 0 14px 0;
      padding: 14px 15px 10px 15px;
   }

   code {
      font-family: Consolas, Monaco, Courier New, Courier, monospace;
      font-size: 12px;
      background-color: #f9f9f9;
      border: 1px solid #D0D0D0;
      color: #002166;
      display: block;
      margin: 14px 0 14px 0;
      padding: 12px 10px 12px 10px;
   }

   #body {
      margin: 0 15px 0 15px;
   }

   p.footer {
      text-align: right;
      font-size: 11px;
      border-top: 1px solid #D0D0D0;
      line-height: 32px;
      padding: 0 10px 0 10px;
      margin: 20px 0 0 0;
   }

   #container {
      margin: 10px;
      border: 1px solid #D0D0D0;
      box-shadow: 0 0 8px #D0D0D0;
   }
   </style>
</head>
<body>

<div id="container">
   <h1>Add New Image</h1>

   <div id="body">
      <?php if(validation_errors() || isset($error)) : ?>
         <div class="alert alert-danger" role="alert" align="center">
            <?=validation_errors()?>
            <?=(isset($error)?$error:'')?>
         </div>
      <?php endif; ?>
      <?=form_open_multipart('gallery/add')?>

        <div class="form-group">
          <label for="userfile">Image File</label>
          <input type="file" class="form-control" name="userfile">
        </div>

        <div class="form-group">
          <label for="caption">Caption</label>
          <input type="text" class="form-control" name="caption" value="">
        </div>

        <div class="form-group">
          <label for="description">Description</label>
          <textarea class="form-control" name="description"></textarea>
        </div>

        <button type="submit" class="btn btn-primary">Upload</button>
        <?=anchor('gallery','Cancel',['class'=>'btn btn-warning'])?>

      </form>
   </div>

   <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo  (ENVIRONMENT === 'development') ?  'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p>
</div>

</body>
</html>
And the third HTML file is the edit form for uploaded image. Create a new file under application/views/gallery/ directory and name it edit_image.php.
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
if($this->input->post()){
   $caption       = set_value('caption');
   $description    = set_value('description');
} else {
   $caption       = $image->caption;
   $description    = $image->description;
}
?><!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="utf-8">
   <title>Update Existing Image</title>

   <link href='http://fonts.googleapis.com/css?family=Oxygen' rel='stylesheet' type='text/css'>
   <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
   <style type="text/css">

   ::selection { background-color: #E13300; color: white; }
   ::-moz-selection { background-color: #E13300; color: white; }

   body {
      background-color: #fff;
      margin: 40px;
      font: 16px/24px normal 'Oxygen', sans-serif;
      color: #4F5155;
   }

   a {
      color: #003399;
      background-color: transparent;
      font-weight: normal;
   }

   h1 {
      color: #444;
      background-color: transparent;
      border-bottom: 1px solid #D0D0D0;
      font-size: 19px;
      font-weight: normal;
      margin: 0 0 14px 0;
      padding: 14px 15px 10px 15px;
   }

   code {
      font-family: Consolas, Monaco, Courier New, Courier, monospace;
      font-size: 12px;
      background-color: #f9f9f9;
      border: 1px solid #D0D0D0;
      color: #002166;
      display: block;
      margin: 14px 0 14px 0;
      padding: 12px 10px 12px 10px;
   }

   #body {
      margin: 0 15px 0 15px;
   }

   p.footer {
      text-align: right;
      font-size: 11px;
      border-top: 1px solid #D0D0D0;
      line-height: 32px;
      padding: 0 10px 0 10px;
      margin: 20px 0 0 0;
   }

   #container {
      margin: 10px;
      border: 1px solid #D0D0D0;
      box-shadow: 0 0 8px #D0D0D0;
   }
   </style>
</head>
<body>

<div id="container">
   <h1>Update Image</h1>

   <div id="body">
      <?php if(validation_errors() || isset($error)) : ?>
         <div class="alert alert-danger" role="alert" align="center">
            <?=validation_errors()?>
            <?=(isset($error)?$error:'')?>
         </div>
      <?php endif; ?>
      <?=form_open_multipart('gallery/edit/'.$image->id)?>

        <div class="form-group">
          <label for="userfile">Image File</label>
          <div class="row" style="margin-bottom:5px"><div class="col-xs-12 col-sm-6 col-md-3"><?=img(['src'=>$image->file,'width'=>'100%'])?></div></div>
          <input type="file" class="form-control" name="userfile">
        </div>

        <div class="form-group">
          <label for="caption">Caption</label>
          <input type="text" class="form-control" name="caption" value="<?=$caption?>">
        </div>

        <div class="form-group">
          <label for="description">Description</label>
          <textarea class="form-control" name="description"><?=$description?></textarea>
        </div>

        <button type="submit" class="btn btn-primary">Save</button>
        <?=anchor('gallery','Cancel',['class'=>'btn btn-warning'])?>

      </form>
   </div>

   <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo  (ENVIRONMENT === 'development') ?  'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p>
</div>

</body>
</html>
Of course it is your homework to make the three files more compact by separating the header and footer part ffrom the middle main content. Next we are going to write the controller.

The Controller

Start by creating a new file under the application/controllers/ directory and name it Gallery.php. Here is the global structure of our gallery controller:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Gallery extends CI_Controller {
   public function __construct()
   {
      parent::__construct();
      $this->load->model('Gallery_model');
      $this->load->helper(['url','html','form']);
      $this->load->database();
      $this->load->library(['form_validation','session']);
   }

   public function index() {}

   public function add() {}

   public function edit($id) {}

   public function delete($id) {}
}
The index() method will call the all() method from Gallery_model class. The result of the all() method then will be passed into the application/views/gallery/index.php view file to be displayed. 
   public function index()
   {
      $data = [
         'images'   => $this->Gallery_model->all()
      ];
      $this->load->view('gallery/index', $data);
   }
The add() method will validate our form inputs, upload the selected image, and then store the image location into the database by calling the create() method from Gallery_model class.
   public function add(){
      $rules =    [
                    [
                            'field' => 'caption',
                            'label' => 'Caption',
                            'rules' => 'required'
                    ],
                    [
                            'field' => 'description',
                            'label' => 'Description',
                            'rules' => 'required'
                    ]
               ];

      $this->form_validation->set_rules($rules);

      if ($this->form_validation->run() == FALSE)
      {
         $this->load->view('gallery/add_image');
      }
      else
      {

         /* Start Uploading File */
         $config =   [
                     'upload_path'   => './uploads/',
                        'allowed_types' => 'gif|jpg|png',
                        'max_size'      => 100,
                        'max_width'     => 1024,
                        'max_height'    => 768
                     ];

            $this->load->library('upload', $config);

            if ( ! $this->upload->do_upload())
            {
                    $error = array('error' => $this->upload->display_errors());

                    $this->load->view('gallery/add_image', $error);
            }
            else
            {
                    $file = $this->upload->data();
                    //print_r($file);
                    $data = [
                             'file'          => 'uploads/' . $file['file_name'],
                             'caption'      => set_value('caption'),
                             'description'   => set_value('description')
                          ];
                    $this->Gallery_model->create($data);
               $this->session->set_flashdata('message','New image has been added..');
               redirect('gallery');
            }
      }
   }
Similar to the add() method, The edit() method will display a selected recor on a form. Then after the form is submitted, the edit() method validate our form inputs, upload the selected image, and then replace the updated image data on the database by calling the update() method from Gallery_model class.
   public function edit($id){
      $rules =    [
                    [
                            'field' => 'caption',
                            'label' => 'Caption',
                            'rules' => 'required'
                    ],
                    [
                            'field' => 'description',
                            'label' => 'Description',
                            'rules' => 'required'
                    ]
               ];

      $this->form_validation->set_rules($rules);
      $image = $this->Gallery_model->find($id)->row();

      if ($this->form_validation->run() == FALSE)
      {
         $this->load->view('gallery/edit_image',['image'=>$image]);
      }
      else
      {
         if(isset($_FILES["userfile"]["name"]))
         {
            /* Start Uploading File */
            $config =   [
                        'upload_path'   => './uploads/',
                           'allowed_types' => 'gif|jpg|png',
                           'max_size'      => 100,
                           'max_width'     => 1024,
                           'max_height'    => 768
                        ];

               $this->load->library('upload', $config);

               if ( ! $this->upload->do_upload())
               {
                       $error = array('error' => $this->upload->display_errors());
                  $this->load->view('gallery/edit_image',['image'=>$image,'error'=>$error]);
               }
               else
               {
                       $file = $this->upload->data();
                       $data['file'] = 'uploads/' . $file['file_name'];
                  unlink($image->file);
               }
         }

         $data['caption']      = set_value('caption');
         $data['description']   = set_value('description');
         
         $this->Gallery_model->update($id,$data);
         $this->session->set_flashdata('message','New image has been updated..');
         redirect('gallery');
      }
   }
The last method is the delete() method. Simply it calls the  edit() method from Gallery_model class.
   public function delete($id)
   {
      $this->Gallery_model->delete($id);
      $this->session->set_flashdata('message','Image has been deleted..');
      redirect('gallery');
   }
That's it, we just write our own Image Gallery Application.. Yeaay. Don't forget to make the uploads/ directory and give it a write permission. Here's the source code if you want to take a peek.

May 12, 2015

Sending Email from CodeIgniter with Mandrill

The last time I used CodeIgniter in my project was about two years ago. It was an online property marketplace where people can collectively buy expensive houses by sharing ownership of the house and, of course, sharing the mortgage. There was these times when I had my dead-end building an application module to send email to customers, some sort of news letter. The dead-end was actually due to google SMTP limitation on relaying email from my application. If you are on a project that still rely on Google's SMTP to send email, I suggest you migrate to Mandrill.

Mandrill

/ˈmændrəl/ | noun | is a transactional email platform from MailChimp. By definition Mandrill is a transactional email platform, which can use to relay emails from our application. Of course there is a price for their services, but as long as we are sending less than 12,000 emails per month we are eligible for free services. It is easy though to scale up if we need to send more than 12,000 emails in a month. Just upgrade your package without re-signing-up your account.

CodeIgniter Mail Library

As our favorite PHP framework, CodeIgniter has the ability to connect to Mandrill as a relay to our mailing module. Check inside folder application/config/ and if you cannot find a file named email.php, create one right now. Now we have to write the CodeIgniter-Mandrill configuration like this:

<?php
$config['protocol'] = 'smtp';
$config['charset']  = 'iso-8859-1'; //Change this you your preferred charset 
$config['wordwrap'] = TRUE;
$config['mailtype'] = 'html'; //Use 'text' if you don't need html tags and images

$config['smtp_host'] = '#';
$config['smtp_user'] = '#';
$config['smtp_pass'] = '#';
$config['smtp_port'] = '#';
For now, we keep the email configuration as above. But we will come back later to fill in the hash-tags after I show you how to get them from Mandrill. Meanwhile, let's go write some code to send emails. Open up any controller file and add this function at the end of the controller.
public function send_now()
{
    $this->load->library('email');

    $this->email->from('my-original@email.com', 'Your Name');
    $this->email->to('your-destination@email.com');
    $this->email->cc('another-destination@email.com');
    $this->email->bcc('blinded-destination@email.com');

    $this->email->subject('Sending Email from CodeIgniter with Mandrill');
    $this->email->message('If you forgot how to do this, go ahead and refer to: <a href="http://the-amazing-php.blogspot.com/2015/05/codeigniter-send-email-with-mandrill.html">The Amazing PHP</a>.');

    $this->email->send();
}
That simple, right!

Now, Back to Mandrill!

In order to get our mailing module work, we need to register to mandrill to get our SMTP credentials. To do so, go ahead and open your favorite browser (mine is Chrome) and enter http://www.mandrill.com at the address bar.
Click the Sign Up button to create a new account on Mandrill. This is very easy because all you need to fill is just your email address and your Mandrill password. Note that your mandrill password is not your SMTP password.
After signing up, there is going to be an optional profile form that you may or may not fill. I will skip this form for now by clicking the No, Thanks button on the left bottom of the form.
Next step is to click the Get SMTP Credentials button.
And then type in your Mandrill password when prompted.
Mandrill will create and display your SMTP account detail afterward. Now, to get your SMTP password, click on the + Add API Key button below your SMTP credentials.
Up to this point you should see a new API key. This key (or one of these keys, if you have more than one) can be your SMTP password.
Go on and replace those hash-tags on our email configuration. Go to directory application/config/ and open file email.php, then edit the file matching your Mandrill SMTP credentials.
$config['smtp_host'] = 'smtp.mandrillapp.com';
$config['smtp_user'] = 'my-email@address.com';
$config['smtp_pass'] = 'th1s-1s-y0ur-p4ssw0rd!';
$config['smtp_port'] = '587';

That's it!
Now try to run your script on your browser, and give a comment below if you're having trouble. By the way, to prove you that this tutorial works (even from http://localhost setup on your computer), this what it looks like when I checked my email:
You can also download my sample source code by clicking here.

May 07, 2015

Using Lumen Micro-framework with AngularJS

About three weeks ago we have a surprisingly good news from the creator of Laravel framework, Taylor Otwell, that he was releasing a new micro-framework built on top of Laravel and he named it "Lumen". As I was guessing, and turns out to be proven right, that this micro-framework will have the same cozy syntax as Laravel was. Benchmarks was done and resulting in Lumen being faster than micro-frameworks such as Slim and Silex (http://taylorotwell.com/how-lumen-is-benchmarked/).

So...

Today we are going to occupy Lumen as a web-service to our CRUD application built with AngularJS.

Step 1: Prepare the initial data

Before diving into lumen, we are going to create some fake data to play with. In this tutorial, we are going to use MySQL database and I have prepared you a MySQL data dump file for "users" table that will be used for our CRUD application in this tutorial. You can download the dump file, just open open this URL and click on the download link.

Now, let's create a new database called "db_lumen".
Continue by clicking on the database name to select it, then click on the import menu button. Choose the file we have dowloaded earlier and click the "Go" button to begin importing the data.
And there we have the data imported.




Step 2: Build the web-service with Lumen

Assuming that you have already install composer on your computer, let's open your favorite shell (command prompt on windows machine) and update your composer if you haven't got the latest version.
composer self-update
Next, go to your project directory (or any other directory you usually build your project in) and create a new lumen project using composer, these are the commands:
cd ~/Projects
composer create-project laravel/lumen --prefer-dist
Get in to lumen directory and run the lumen service using the artisan command like this:
cd lumen
php artisan serve
Open up your browser and go to page http://localhost:8000, where the lumen service is running, you should see something like this:
Inside the lumen directory you will find a ".env.example" file. Duplicate the file and rename the duplicate as ".env". Modify some settings inside the ".env" file according to your project environment, for example, mine looks like this:
APP_ENV=local
APP_DEBUG=true
APP_KEY=w3h84fFfrwpKExMXimYom810303FNb64

APP_LOCALE=en
APP_FALLBACK_LOCALE=en

DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=db_lumen
DB_USERNAME=root
DB_PASSWORD=

CACHE_DRIVER=memcached
SESSION_DRIVER=memcached
QUEUE_DRIVER=database
Note that you should set APP_DEBUG=false when APP_ENV=production (your application is on live production state). Next you have to open the app.php file inside folder bootstrap, find these lines:
Line-5  : // Dotenv::load(__DIR__.'/../');
Line-22 : // $app->withFacades();
Line-24 : // $app->withEloquent();
and un-comment these lines, so that it becomes like this:
Dotenv::load(__DIR__.'/../');
$app->withFacades();
$app->withEloquent();
Ok, that's done for the settings. Now let's go down to business and code our CRUD services. Open the routes.php file inside folder app/Http/ and modify the existing code so that is will look like this:
<?php
$app->get('/', function() use ($app) {
    return view('index'); 
});

$app->post('/create-user',      'App\Http\Controllers\UserController@store');
$app->get('/read-users',        'App\Http\Controllers\UserController@index');
$app->get('/read-user/{id}',    'App\Http\Controllers\UserController@show');
$app->post('/edit-user/{id}', 'App\Http\Controllers\UserController@update');
$app->post('/delete-user/{id}', 'App\Http\Controllers\UserController@destroy');
Next, we are going to code the controller. Get into folder app/Http/Controllers, create a new file called UserController.php, and write these basic function declarations to start with:
<?php 
namespace App\Http\Controllers;

use Laravel\Lumen\Routing\Controller as BaseController;
use App\User; //loads the User model
use Illuminate\Http\Request; //loads the Request class for retrieving inputs
use Illuminate\Support\Facades\Hash; //load this to use the Hash::make method

class UserController extends BaseController
{
    public function index(){}
    public function show(){}
    public function store(){}
    public function update(){}
    public function destroy(){}
}
Next we should fill up those functions to make a full CRUD application, let's do it part by part.

The -C- Part
/* The -C- Part */
public function store(Request $request){ //Insert new record to users table
    $this->validate($request, [
        'email'  => 'required|unique:users',
        'password' => 'sometimes',
        'name'  => 'required',
        'address' => 'required',
        'phone'  => 'required'
    ]); 
    $user   = new User;
    $user->email  = $request->input('email');
    $user->password  = Hash::make( $request->input('password') );
    $user->name  = $request->input('name');
    $user->address  = $request->input('address');
    $user->phone  = $request->input('phone');
    $user->save();
}
The -R- Part
public function index(){ //Get all records from users table
    return User::all();
}

public function show($id){ //Get a single record by ID
    return User::find($id); 
}
The -U- Part
public function update(Request $request, $id){ //Update a record
    $this->validate($request, [
        'email'  => 'required',
        'password' => 'sometimes',
        'name'  => 'required',
        'address' => 'required',
        'phone'  => 'required'
    ]); 
    $user    = User::find($id);
    $user->email   = $request->input('email');
    if($request->has('password')){
        $user->password = Hash::make( $request->input('password') );
    }
    $user->name   = $request->input('name');
    $user->address   = $request->input('address');
    $user->phone   = $request->input('phone');
    $user->save();
}
The -D- Part
public function destroy(Request $request){
    $this->validate($request, [
        'id' => 'required|exists:users'
    ]);
    $user = User::find($request->input('id'));
    $user->delete();
}
Okay, now that we have done building our Lumen services, lets build a user interface with AngularJS

Step 3: Build the AngularJS application

First, we are going to create an index.php file inside the resource/views folder. We are not using blade in this case, because we are only use lumen for the background service for AngularJS application.
<!DOCTYPE html>
<html lang="en-US">
<head>
   <title>The Amazing PHP - AngularJS Single-page Application with Lumen CRUD Services</title>
 
   <!-- Load Bootstrap CSS -->
   <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

   <div ng-app="myApp" ng-controller="usersCtrl">
      
      <!-- There will be a table, to dispay the data, here -->

      <!-- There will be a modal to pop-up a Form (One form used as a create and edit form) -->
  
   </div>

   <!-- Load Javascript Libraries (AngularJS, JQuery, Bootstrap) -->
   <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
   <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>

   <!-- There will be our javascript Application here -->

</body>
</html>
Notice that the above script is not complete yet. There are some missing parts need to be filled just to show you the big picture of the application. Now, let's fill those blank scripts starting from the table part as below:
<!-- Table-to-load-the-data Part -->
   <table class="table">
      <thead>
         <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Email</th>
            <th>Phone</th>
            <th>Date Created</th>
            <th><button id="btn-add" class="btn btn-primary btn-xs" ng-click="toggle('add',0)">Add New User</button></th>
         </tr>
      </thead>
      <tbody>
         <tr ng-repeat="user in users">
            <td>{{ $index + 1 }}</td>
            <td>{{ user.name }}</td>
            <td>{{ user.email }}</td>
            <td>{{ user.phone }}</td>
            <td>{{ user.created_at }}</td>
            <td>
               <button class="btn btn-default btn-xs btn-detail" ng-click="toggle('edit',user.id)">Edit</button>
               <button class="btn btn-danger btn-xs btn-delete" ng-click="confirmDelete(user.id)">Delete</button>
            </td>
         </tr>
      </tbody>
   </table>
<!-- End of Table-to-load-the-data Part -->
Next, we are going to put the modal, which actually contains the Add New User and Edit User form. Just one modal for both Add and Edit usage.
<!-- Modal (Pop up when detail button clicked) -->
   <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog">
         <div class="modal-content">
            <div class="modal-header">
               <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
               <h4 class="modal-title" id="myModalLabel">{{state}}</h4>
            </div>
            <div class="modal-body">
               <form class="form-horizontal">

                  <div class="form-group">
                     <label for="inputEmail3" class="col-sm-3 control-label">Name</label>
                     <div class="col-sm-9">
                        <input type="text" class="form-control" id="inputEmail3" placeholder="Fullname" value="{{name}}" ng-model="formData.name">
                     </div>
                  </div>

                  <div class="form-group">
                     <label for="inputEmail3" class="col-sm-3 control-label">Email</label>
                     <div class="col-sm-9">
                        <input type="text" class="form-control" id="inputEmail3" placeholder="Email Address" value="{{email}}" ng-model="formData.email">
                     </div>
                  </div>

                  <div class="form-group">
                     <label for="inputPassword3" class="col-sm-3 control-label">Password</label>
                     <div class="col-sm-9">
                        <input type="password" class="form-control" id="inputPassword3" placeholder="Leave empty to unchange" ng-model="formData.password">
                     </div>
                  </div>

                  <div class="form-group">
                     <label for="inputEmail3" class="col-sm-3 control-label">Phone</label>
                     <div class="col-sm-9">
                        <input type="text" class="form-control" id="inputEmail3" placeholder="Phone Number" value="{{phone}}" ng-model="formData.phone">
                     </div>
                  </div>

                  <div class="form-group">
                     <label for="inputEmail3" class="col-sm-3 control-label">Address</label>
                     <div class="col-sm-9">
                        <textarea class="form-control" placeholder="Full Address" ng-model="formData.address">{{address}}</textarea>
                     </div>
                  </div>

               </form>
            </div>
            <div class="modal-footer">
               <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
               <button type="button" class="btn btn-primary" id="btn-save" ng-click="save(modalstate,user_id)">Save changes</button>
            </div>
         </div>
      </div>
   </div>
<!-- End of Modal -->
Lastly, the angularjs application will be coded before the </body> tag as below: 
<!-- AngularJS Application Script Part -->
<script>
   var app = angular.module('myApp', []);
   app.controller('usersCtrl', function($scope, $http) {

      /* The -R- part */
      $http.get("http://localhost:8000/read-users")
      .success(function(response) {
         $scope.users = response;
      });
      /* End of the -R- part */
         
      /* The -C- and -U- part */
         $scope.save = function(modalstate,user_id){
            switch(modalstate){
               case 'add': var url = "http://localhost:8000/create-user"; break;
               case 'edit': var url = "http://localhost:8000/edit-user/"+user_id; break;
               default: break;
            }
            $http({
               method  : 'POST',
               url     : url,
               data    : $.param($scope.formData),  // pass in data as strings
               headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
            }).
            success(function(response){
               location.reload();
            }).
            error(function(response){
               console.log(response);
               alert('Incomplete Form');
            });
         }
      /* End of the -C- and -U- part */

      /* The -D- Part */
         $scope.confirmDelete = function(id){
            var isOkDelete = confirm('Is it ok to delete this?');
            if(isOkDelete){
               $http.post('http://localhost:8000/delete-user', {id:id}).
               success(function(data){
                  location.reload();
               }).
               error(function(data) {
                  console.log(data);
                  alert('Unable to delete');
               });
            } else {
               return false;
            }
         }
      /* End of the -D- Part */

      /* Show the modal */
      $scope.toggle = function(modalstate,id) {
            $scope.modalstate = modalstate;
            switch(modalstate){
               case 'add':
                           $scope.state = "Add New User";
                           $scope.user_id = 0;
                           $scope.name = '';
                           $scope.email = '';
                           $scope.phone = '';
                           $scope.address = '';
                           break;
               case 'edit':
                           $scope.state = "User Detail";
                           $scope.user_id = id;
                           $http.get("http://localhost:8000/read-user/" + id)
                           .success(function(response) {
                              console.log(response);
                              $scope.formData = response;
                           });
                           break;
               default: break;
            }
            
            //console.log(id);
            $('#myModal').modal('show');
         }
   });
</script>
<!-- End of AngularJS Application Script Part -->
The application would be like the screenshot picture shown below:

And tadaa, we have just build an AngularJS application with Lumen running as services. Feel free to improve the code from this tutorial, and please let me know if you build something amazing with it. Have fun ^_^

Download source code here