laravel4 Eloquent ORM Model, Blade View & Simple Controller

Standard

So far we have completed four blog posts for the series on development of thisdayinbangladesh, a simple laravel4 live application. Those are following:

1. Creating virtual host
2. Installing laravel4
3. laravel4 migrations & seeding
4. laravel4 routing

In this post we will learn, how we can have Object Relational Mapping for our data model using Eloquent ORM that is built in with laravel4. Also we will render our view using Blade templating system. Finally we will create few very simple controllers that will do our basic tasks.

Model:

Laravel ships with a superb ORM: Eloquent. If you have used the Ruby on Rails framework, you will find Eloquent familiar, as it follows the ActiveRecord ORM style of database interaction.

At this current stage (state before merging with any other branch on github) of our application we need such a relationship among our database tables (days, facts, types, fact_type) so that;

i. A Day has many Facts: That means there would be a relation from “days” table to “facts” table that is One to Many. N. B. Currently “days” table contains 366 days in separate rows.
ii. A Fact belongs to a Day: That means in a certain case, one Or more Fact(s) will belong to a single Day. That is a reverse of One to Many relation from “facts” table to “days” table.
iii. A Type has many Facts & a Fact has many Types: For example a fact type named “politics” could have several facts for a certain day. On the other hand a fact titled “Independence day of Bangladesh” could have several types like “politics”, “good”, “revolutionary” etc. So, there would be a Many To Many relationship between “types” table & “facts” table.

Lets create our first Model called “Day.php” for our “days” table inside “app/models” directory with the following code.

<?php
 
class Day extends Eloquent {
    /**
     * The database table used by the model.
     * If the name of your days table is some thing other than days, 
     * then define it below. Other wise it will assume a table name
     * that is a plural of the model class name.
     *
     * @var string
     */
    
    // protected $table = 'dates';
    
    public $timestamps = false;
    
    /*
     * A Day has many Facts
     */
    public function facts()
    {
        return $this->hasMany('Fact');
    }
     
}


First check the comments on line 5-10. Hope you’ve understood what is said there.
Note that we did not tell Eloquent which table to use for our Day model.The lower-case, plural name of the class will be used as the table name unless another name is explicitly specified. Then by the definition of the function “facts()” we are defining a One to Many relationship between Day & Fact model.

Now lets create another Model named “Fact.php” for the “facts” table in same directory with the following code.

<?php
 
class Fact extends Eloquent {
    /**
     * The database table used by the model.
     * If the name of your facts table is some thing other than facts, 
     * then define it below. Other wise it will assume a table name
     * that is a plural of the model class name.
     *
     * @var string
     */
    
    // protected $table = 'incidents';
    
    /*
     * A Fact belongs to a Day
     */
    public function day()
    {
        return $this->belongsTo('Day');
    } 
     
}

Here we are defining a reverse of One to Many relationship between Fact model & Day model by the “day()” function.

As we discussed above that we have to manage “fact types” for our application. “type” table will contain some popular fact types like “birth”, “death”, “sport”, “politics” etc in it. Lets create another Model named “Type.php” for the “types” table with following code.

<?php
 
class Type extends Eloquent {
    /**
     * The database table used by the model.
     * If the name of your facts types table is some thing other than types, 
     * then define it below. Other wise it will assume a table name
     * that is a plural of the model class name.
     *
     * @var string
     */

    // protected $table = 'facttypes';
    
    public $timestamps = false;
    
    /**
     * A Type belongs to many Facts
     */
    public function facts()
    {
      return $this->belongsToMany('Fact');
    }    
     
}

Since, a Type belongs to many Facts, we created a, Many to Many relationship from Type model to Fact model by the “facts()” method. Now we will have to put a same kind of relationship on the Fact model. So, update the “Fact.php” model like the following code.

<?php
 
class Fact extends Eloquent {
    /**
     * The database table used by the model.
     * If the name of your facts table is some thing other than facts, 
     * then define it below. Other wise it will assume a table name
     * that is a plural of the model class name.
     *
     * @var string
     */
    
    // protected $table = 'incidents';
    
    /*
     * A Fact belongs to a Day
     */
    public function day()
    {
        return $this->belongsTo('Day');
    }
    
    /**
     * A Fact belongs to many Types
     */
    public function types()
    {
      return $this->belongsToMany('Type');
    }        
     
}

Here on the bottom, we defined the relationship of Fact inside the “types()” method that it belongs to many types.

Finally we will obviously have to store Type ID & Fact ID relation mapping in a pivot table. We will name it “fact_type” in our database. We maintained the convention that is needed by this ORM & laravel that is; singular name of the alphabetically first table AND singular name of the alphabetically second table joining with an underscore. So, we don’t need to define a custom pivot table name to the ORM by passing any additional parameter while creating/defining relationship.
So, lets make another model for this “fact_type” table named “FactType.php” with nothing special code in it.

<?php
 
class FactType extends Eloquent {
    /**
     * The database table used by the model.
     * If the name of your facts types relation holder table is some thing 
     * other than fact_type, then define it below.
     *
     * @var string
     */
    
    // protected $table = 'facttypes';
    
    public $timestamps = false;
         
}

Views:

One method of using templates in Laravel is via controller layouts. By specifying the layout property on the controller, the view specified will be created for you and will be the assumed response that should be returned from actions.

But in our developing app, we are going to use Blade Templating. Its a great templating engine that comes with laravel4. Unlike controller layouts, Blade is driven by template inheritance and sections. All Blade templates should use the “.blade.php” extension.

First of all, we need a master layout which would contain all the sub views (header logo, navigations, sidebar, top section, body, footer etc) in a sectional structure in it. Lets create our master view named “layoutfront.blade.php” inside “app/views” directory.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>This day in history of Bangladesh :: আজকের দিনে বাংলাদেশ</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="This day in Bangladesh. What happened in this day with Bangladesh. Today in Bangladesh. This day in history of Bangladesh." />
    <meta name="keywords" content="This day in Bangladesh, Today in Bangladesh, History of Bangladesh, Time line of Bangladesh" />
    <meta name="author" content="Nuhil Mehdy"/>     

    <!-- Loading Bootstrap -->
    <link href="{{ URL::asset('assets/bootstrap/css/bootstrap.css') }}" rel="stylesheet">
    <link href="{{ URL::asset('assets/bootstrap/css/custom.css') }}" rel="stylesheet">

    <!-- Loading Flat UI -->
    <link href="{{ URL::asset('assets/css/flat-ui.css') }}" rel="stylesheet">

    <link rel="shortcut icon" href="{{ URL::asset('assets/images/favicon.ico') }}">
    <script src="{{ URL::asset('assets/js/jquery-1.8.3.min.js') }}"></script>
    <script src="{{ URL::asset('assets/js/jquery-ui-1.10.3.custom.min.js') }}"></script>
    <script src="{{ URL::asset('assets/js/bootstrap.min.js') }}"></script>
    <script src="{{ URL::asset('assets/js/bootstrap-select.js') }}"></script>
    <script src="{{ URL::asset('assets/js/bootstrap-switch.js') }}"></script>
    <script src="{{ URL::asset('assets/js/flatui-checkbox.js') }}"></script>
    <script src="{{ URL::asset('assets/js/jquery.tagsinput.js') }}"></script>
    <script src="{{ URL::asset('assets/js/jquery.placeholder.js') }}"></script>
    <script src="{{ URL::asset('assets/js/application.js') }}"></script>

    <!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
    <!--[if lt IE 9]>
      <script src="{{ URL::asset('assets/js/html5shiv.js') }}"></script>
    <![endif]-->
  </head>
  <body>
    <div class="container">
      <h1 class="demo-panel-title">This day in <span class="green">Bangladesh</span></h1>
      <div class="row demo-row">
        <div class="span12">
          <div class="navbar navbar-inverse">
            <div class="navbar-inner">
              <div class="container">
                <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target="#nav-collapse-01"></button>
                <div class="nav-collapse collapse" id="nav-collapse-01">
                  <ul class="nav">
                    <li>
                      <a href="<?php echo URL::to(''); ?>">
                        Home
                        <span class="navbar-unread">5</span>
                      </a>
                    </li>
                    <li>
                      <a href="#">
                        Fact Types
                      </a>
                      <ul>
                        <li><a href="#">Happiness</a></li>
                        <li><a href="#">Sorrows</a></li>
                        <li>
                          <a href="#">Other</a>
                          <ul>
                            <li><a href="#">Birth</a></li>
                            <li><a href="#">Death</a></li>
                            <li><a href="#">Politics</a></li>
                            <li><a href="#">Revolution</a></li>
                            <li><a href="#">Social</a></li>
                            <li><a href="#">Literature</a></li>
                          </ul> <!-- /Sub menu -->
                        </li>
                      </ul> <!-- /Sub menu -->
                    </li>
                    <li>
                      <a href="#">
                        Talk of Year
                      </a>
                    </li>                  
                    <li>
                      <a href="#">
                        Most Discussed
                      </a>
                    </li>    
                    <li>
                      <a href="#">
                        Prior 1971
                      </a>
                    </li>                                    
                    <li>
                      <a href="<?php echo URL::to('about'); ?>">
                        About Us
                      </a>
                    </li>
                  </ul>
                </div><!--/.nav -->
              </div>
            </div>
          </div>
        </div>
      </div> <!-- /row -->

      @yield('dateandtalkofthisday')

      <div class="row demo-row">
        <div class="span3">
          <div class="share mrl">
            <ul>
              <li>
                <label class="share-label" for="share-toggle2">Facebook</label>
                <input type="checkbox" checked="" data-toggle="switch" />
              </li>
              <li>
                <label class="share-label" for="share-toggle4">Twitter</label>
                <input type="checkbox" data-toggle="switch" />
              </li>
              <li>
                <label class="share-label" for="share-toggle6">Pinterest</label>
                <input type="checkbox" data-toggle="switch" />
              </li>
            </ul>
            <a href="#" class="btn btn-info btn-block btn-large">Share</a>
          </div> <!-- /share -->          
        </div>
          
        @yield('eventlisting')
        @yield('about')
      </div> <!-- /row -->

    </div> <!-- /container -->
    
    <!-- Load JS here for greater good =============================-->
    <script type="text/javascript">
        $(document).ready(function() {
            $(".day" ).change(function() {
                if(($('#select-month').val() && $('#select-day').val()) != '') {
                    window.location = "<?php echo URL::to(''); ?>"+"/facts/"+$('#select-month').val()+'/'+$('#select-day').val();
                }
                
            });
        });
    </script>       
  </body>
</html>

Though it looks so much code here but take a deeper look and you will get it simple. This is a one page template that was made using the UI elements of Flat UI design kit. We first requested the CSS & Js assets that needed for front end view, on top of the HTML script. N. B. Don’t bother why I placed those such a static way. Its up to you later to make this placement in a more beautiful & effective way.
On the very bottom of the template we used few lines of jQuery so that if user choose a pair of date and month from a select box then it redirects to a specific URL that contains a route along with date and month as parameters on it.
Then, on the line 99 we defined an area in which a sub view will be called up while rendering the full view. That sub view was named “dateandtalkofthisday.blade.php” inside “app/views” directory and contains the following code.

@section('dateandtalkofthisday')
    <!-- Date & Talk of this day -->
      <div class="row demo-row">
        <div class="span3 tb-date">
          <h1>@if(isset($today['month'])) {{ $today['month'] }} @endif</h1>
          <h2>@if(isset($today['day'])) {{ $today['day'] }} @endif</h2>
        </div>
        <div class="span9 tb-hot">
          <div class="tile tb-talk-of-the-day">
            <h3>
                <img src="{{ URL::asset('assets/images/icons/Chat@2x.png') }}" alt="hit">
                Did you know?
            </h3>
              
            @if ((isset($facts) && (count($facts) >= 1)))
            <ul class="tb-ul">
              <li>
                <h6><span class="fui-user"></span> <strong>{{$facts['facts'][0]['title']}}</strong></h6>
                <p>{{$facts['facts'][0]['description']}}</p>
              </li>        
            </ul>
            @else
            <h1 class="error">Oops! No fact found for this day!</h1>
            <h4>Why don't you <a href="<?php echo URL::to('about'); ?>" alt="Let Us Know">let us know</a> about a fact that happened on this day?</h4>
            @endif
          </div>
        </div>
      </div>
      <!-- /Date & Talk of this day -->
      <div class="row demo-row">
          <div class="span2 month-picker">
          <select name="herolist" id="select-month" value="Day" class="select-block span3 day" style="display: none;">
              <option value="">Month</option>
              <option value="01">January</option>
              <option value="02">February</option>
              <option value="03">March</option>
              <option value="04">April</option>
              <option value="05">May</option>
              <option value="06">June</option>
              <option value="07">July</option>
              <option value="08">August</option>
              <option value="09">September</option>
              <option value="10">October</option>
              <option value="11">November</option>
              <option value="12">December</option>
            </select>
          </div>  
          <div class="span1 date-picker">
          <select name="herolist" id="select-day" value="Day" class="select-block span3 day" style="display: none;">
              <option value="">Day</option>
              <option value="01">1</option>
              <option value="02">2</option>
              <option value="03">2</option>
              <option value="04">4</option>
              <option value="05">5</option>
              <option value="06">6</option>
              <option value="06">6</option>
              <option value="07">7</option>
              <option value="08">8</option>
              <option value="09">9</option>
              <option value="10">10</option>
              <option value="11">11</option>
              <option value="12">12</option>
              <option value="13">13</option>
              <option value="14">14</option>
              <option value="15">15</option>
              <option value="16">16</option>
              <option value="17">17</option>
              <option value="18">18</option>
              <option value="19">19</option>
              <option value="20">20</option>
              <option value="21">21</option>
              <option value="22">22</option>
              <option value="23">23</option>
              <option value="24">24</option>
              <option value="25">25</option>
              <option value="26">26</option>
              <option value="27">27</option>
              <option value="28">28</option>
              <option value="29">29</option>
              <option value="30">30</option>
              <option value="31">31</option>
            </select>
          </div>         
        <div class="span9">
          <h3><span class="fui-arrow-left"></span>Select Month &amp; Day to go past!</h3>
        </div>
      </div>            
@stop

You can see a pretty simple implementation of Blade Templating like we defined the section name on the very top of the file and finished it on the very bottom. On line 5, 6, 15, 19 we are using some variables that holds values on those and populating data in convention of Blade Templating system.
You can have a look to other sub views (Needed from inside the master view (layoutfront.blade.php on line 122, 123 of it) inside “app/views” directory if you cloned/downloaded the full github repository.

Controller:

So far our data model & their relationships mapping are done. Also we did split a view file and made some sections. Finally we used Blade’s looping, conditions & other syntaxes to render the view by some data variables.
Now we will create the Controllers that will act at very first time when a URL is requested & a rout become performed. Those controllers will make data ready by using the Models & will provide to the view files.
If you already checked out the post about routing for this application, then you should see, the second Route we used to access the RESTful “FactController.php” is called when user requests the root URL of this application via first Route. So, lets create the “FactController.php” RESTful controller.

Laravel allows you to easily define a single route to handle every action in a controller using simple, REST naming conventions. Just add methods to your controller, prefixed with the HTTP verb they respond to.

<?php

use Carbon\Carbon;

class FactController extends BaseController {

    public function getIndex($month = null, $day = null, $type = null)
    {
        $today = Day::where('day', '=', $day.'-'.$month)->first()->toArray();
        $facts = Day::find($today['id'])->facts;
        $allFacts = array();
        
        $i = 0;
        foreach ($facts as $fact):
            $allFacts['facts'][$i] = $fact->toArray();
            $allFacts['facts'][$i]['types'] = $fact->types->toArray();
            $i++;
        endforeach;       
        
        $thisDay = array ('day' => $day, 'month' => date("F", mktime(0, 0, 0, $month, 10)));
        
        return View::make('eventlisting', array('facts' => $allFacts, 'today' => $thisDay));

    }

    public function postFact()
    {
        //
    }

}

We named the methods in above quoted HTTP REST naming conventions. So, actually our method name is something like “Index” that returns a view with some data but the method named with “GET” keyword prefixed in it. This is the convention of a RESTful Controller in laravel4.
Then on line 9, 10 we are retrieving data using Eloquent ORM. Just check line 10 where we are getting all the facts of a specific day (that is today) using a single line. Without even using query builder. Thats the awesomeness of using ORM (Though you can use query builder along with ORM if needed in special cases). After that, all are known to you till line 21.
In line 22, we are returning the View named “eventlisting” which will contain data of allFacts & thisDay array in “facts” & “today” variables. You can check here about binding data with views in laravel.
The code of the “eventlisting.blade.php” file is following.

@extends('layoutfront')

@include('dateandtalkofthisday')

@section('eventlisting')
    <!-- Event Listing -->  
        <div class="span9">
            @if (count($facts) >= 1)
            <ul class="tb-ul">
                @foreach ($facts['facts'] as $fact)
                  <li>
                    <h6>
                      <span class="fui-check-inverted"></span> <strong>{{$fact['title']}}</strong>
                    </h6>
                    <p>{{$fact['description']}}</p>
                    @if(count($fact['types']) >= 1)
                    <p>FACT TYPE(S):
                        @foreach ($fact['types'] as $type)
                        <span class="fui-radio-checked"> <a href="#">{{$type['type']}}</a></span>
                        @endforeach    
                    </p>    
                    @endif
                  </li>                    
                @endforeach                                                                           
            </ul>             
            @endif
            <div class="row" style="text-align:center;">
              <img src="{{ URL::asset('assets/images/icons/Infinity-Loop@2x.png') }}" alt="Pensils@2x" class="tile-image">
            </div>        
        </div>    
        <!-- /Event Listing -->
@stop

Which is extending the master layout “layoutfront”, including the “dateandtalkofthisday” sub view & holding the data variables that was sent by the Fact controller.

Download/Fork Download/Fork on Github
Watch Demo Live/Demo Application

And thats all! Stay tuned by subscribing via email or by following as WP blogger.

2 thoughts on “laravel4 Eloquent ORM Model, Blade View & Simple Controller

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s