model & migration


We need to create database tables before creating forms to make data entry and save them in database. We know, we can migrate database tables using composer and we need to create models too in order to interact with the database. Then, why not create both model and migration together using composer. Let's create model and migration files for menu table then.

php artisan make:model tbl_menu -m	

A model will be created app directory named tbl_menu.php and a migration file with currentdatetime_create_tbl_menus_table.php in database/migration directory.

Now, we'll define the protected table name in plural tense and primary key in the model.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class tbl_menu extends Model
{
    protected $table = 'tbl_menus';
    protected $primaryKey = 'mid';
}	

We'll define the table columns for the same table in it's migration file. We need to change the auto increment id in schema::create if we've changed it from default in our model.

public function up()
{
	Schema::create('tbl_menus', function (Blueprint $table) {
	    $table->increments('mid');
	    $table->string('title')->unique();
	    $table->string('slug');
	    $table->string('status');
	    $table->timestamps();
	});
}	

We made the title unique to avoid conflict while adding menu titles. up() function creates the defined table once we run the artisan command migrate.

php artisan migrate	

Now, the tbl_menus table is created with mid as the primary key along with title, slug and status columns as well as the timestamps column named created_at and updated_at.

INSERT MENU

Now the database table is created, lets carry out the insert operation.

FORM PAGE

We can create form page in our resources/backend/views/ folder to insert menus to the table. Let's create a new folder named inserts to hold all the insert forms pages and create all such pages inside it along with routes to view it.

First, we'll define the route to view the page.

Route::get('menuform', function () {
    return view('backend.inserts.menu');
});	

Now, we'll create the page to add menu titles to the database. We'll add another route as action attribute for the form that we'll define later.

@extends('backend.master')
@section('content')

<div class="row">
	<div class="col-sm-6">
		<form method="post" action="{{url('addmenu')}}">
			{{ csrf_field() }}
			<div class="form-group">
				<label>Title</label>
				<input type="text" name="title" class="form-control">
			</div>
			<div class="form-group">
				<label>Status</label>
				<select class="form-control" name="status">
					<option value="on">on</option>
					<option value="off">off</option>
				</select>
			</div>
			<div class="form-group">
				<input type="submit" class="btn btn-success" value="Add Menu">
			</div>
		</form>
	</div>
</div>

@stop	

Now, the form page is created. We also added another url to the form page to process the data. If we continued to define all the routes with the data processing logics as well in it, the file will look much clumsy. So, we'll create a separate controller to process all the requests coming to and from the backend application. Let's name it adminController. We'll create it using composer.

ADMINCONTROLLER

php artisan make:controller adminController	

The adminController file is created inside the app/Http/Controllers/ directory that extends the base controller. Now, we can create all the closure functions intented to backend application inside this controller rather than in the routes file itself and point to those methods from the routes files instead.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class adminController extends Controller
{
    public function admin(){
    	return view ('backend.index');
    }

    public function addmenu(){
    	return view ('backend.inserts.menu');
    }
}	

Then, we'll redefine the routes in web.php file.

Route::get('admin','adminController@admin');

Route::get('menuform','adminController@addmenu');	

CRUDCONTROLLER

Now the routes to and from the backend are well organized in the adminController file, lets create another separate controller to process the data sent through forms. We'll name it crudController and it'll hold all the logics to process the requests.

php artisan make:controller crudController	

We know where the controller file will be placed by default. Lets add some logics to process the data and save it in database then.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use DB;
use Session;

class crudController extends Controller
{
	private function slug($str){
        $str = strtolower(trim($str));
        $str = preg_replace('/\s+/','-',$str);
        $str = preg_replace('/[^a-z0-9-]/', '-', $str);
        $str = preg_replace('/-+/', "-", $str);
        return rtrim($str, '-') ;
    }

    public function insertData(){
    	$data = Input::except('_token');
    	$tbl = $data['table'];
    	unset ($data['table']);
    	$data['slug'] = $this->slug($data['title']);
    	$data['created_at'] = date('Y-m-d H:i:s');
    	DB::table($tbl)->insert($data);
    	session::flash('message','Data inserted successfully!!!');
        return redirect()->back()->with('message','New data successfully inserted');
    }
}	

We need to use the Input class to work with input requests and use the DB and session work with database and store and display the operation messages to the user.

Then the logic to create slug from the title which trims all the empty spaces and replaces all the special characters with - hyphens and insert data into the table along with storing flash message in session to display to the user and the function to get redirected back to the form page.

Finally, we'll add the url defined in the form to link it to the crudController.

Route::post('addmenu','crudController@insertData');	

DISPLAY MENU

Now, let's create a route and a method to display all data from the menus table in backend. First, we'll create a method in adminController to retrieve all data from database and for the w'll need to add use DB; before the class block stats.

public function displaymenu(){
    $data = DB::table('tbl_menus')->get();
    return view ('backend.display.menu',['data'=>$data]);
}	

We'll hold all the data from the table in a variable and return the view file along with the array when the method is called.

Route::get('displaymenu','adminController@displaymenu');	

Lets create the display page then. We'll create another folder in the backend named display where we'll keep all the pages intended to display data from the database.

@extends('backend.master')
@section('content')
<div class="row">
	<div class="col-sm-12">
		<table class="table table-striped table-hover table-bordered">
			<thead>
				<tr>
					<td>S.N.</td>
					<td>Title</td>
					<td>Slug</td>
					<td>Status</td>
					<td>Edit</td>
					<td>Delete</td>
				</tr>
			</thead>
			<tbody>
				@foreach($data as $key => $menu)
				<tr>
					<td>{{++$key}}</td>
					<td>{{$menu->title}}</td>
					<td>{{$menu->slug}}</td>
					<td>{{$menu->status}}</td>
					<td><a href="{{url('editmenu')}}/{{$menu->mid}}" class="btn btn-sm btn-success"><i class="fa fa-edit"></i></a></td>			
					<td><a href="{{url('deletemenu')}}/{{$menu->mid}}" class="btn btn-sm btn-danger"><i class="fa fa-trash"></i></a></td>
				</tr>
				@endforeach
			</tbody>
		</table>
	</div>
</div>
@stop	

DELETE MENU

The data has been displayed, let's go to the delete action. Since we need data id to be able to edit or delete a data, we added it with the route in those delete and edit links. We'll create a method to delete data in adminController first. We'll need to add use Session; prior to the class block to be able to save flash message in session and display it to the user while redirecting back to the display page.

public function deletemenu($id){
    $data = DB::table('tbl_menus')->where('mid',$id)->delete();
    session::flash('message','Data deleted successfully!!!');
    return redirect()->back()->with('message','Data deleted successfully');
}	

Let's add the route too to carry out the delete action where we'll define the parameter to be passed as string.

Route::get('deletemenu/{id}','adminController@deletemenu');	

UPDATE MENU

To edit a data, we'll need to pass the id of that data row. Rest will be similar to the method we defined to add menu. Let's create a method first to retrieve the data by it's id in adminController.

public function editmenu($id){
    $data = DB::table('tbl_menus')->where('mid',$id)->first();
    return view ('backend.updates.menu',['data'=>$data]);
}	

We need to define the route in web.php to be able to view that page. Let's do that then.

Route::get('editmenu/{id}','adminController@editmenu');	

Now, we can create the form page inside the updates folder of resources/views/backend folder to edit the menu data.

@extends('backend.master')
@section('content'
<div class="row">
	<div class="col-sm-12">
		@if (session('message'))
		    <div class="alert alert-success alert-dismissable fade in">
		        {{ session('message') }}
		    </div>
		@endif
	</div>
	<div class="col-sm-6">
		<form method="post" action="{{url('updatemenu')}}/{{$data->mid}}">
			{{ csrf_field() }}
			<input type="hidden" name="table" value="tbl_menus">
			<input type="hidden" name="mid" value="{{$data->mid}}">
			<div class="form-group">
				<label>Title</label>
				<input type="text" name="title" value="{{$data->title}}" class="form-control">
			</div>
			<div class="form-group">
				<label>Status</label>
				<select class="form-control" name="status">
					<option value="on">on</option>
					<option value="off">off</option>
				</select>
			</div>
			<div class="form-group">
				<input type="submit" class="btn btn-success" value="Update Menu">
			</div>
		</form>
	</div>
</div>
@stop	

The form will be displayed with the value being displayed from the database row once the editmenu url request is sent along with the data id. Now, lets add some processing logic to update those data rows then and the logic will be quite similar to the one we added to insert data.

public function updateData(){
    $data = Input::except('_token');
    $tbl = $data['table'];
    unset ($data['table']);
    $data['updated_at'] = date('Y-m-d H:i:s');
    $data['slug'] = $this->slug($data['title']);
    DB::table($tbl)->where(key($data),reset($data))->update($data);
    session::flash('message','Data updated successfully!!!');
    return redirect()->back()->with('message','Data successfully updated');
}	

Lets define the route to this method in web.php then.

Route::post('updatemenu/{id}','crudController@updateData');	

So, all the database operations regarding menu have been accomplished but it's a bit inconvenient to type the url in the browser all the time. So, let's replace the dummy links with these links in our master layout's navigation so that we'll get the page to insert and display menu on a click.

<li class="treeview">
    <a href="#">
        <i class="fa fa-files-o"></i> <span>Menu</span>    
        <span class="pull-right-container">
        	<i class="fa fa-angle-left pull-right"></i>
        </span>          
    </a>
    <ul class="treeview-menu">
        <li><a href="{{url('menuform')}}"><i class="fa fa-circle-o"></i>Add Menus</a></li>
        <li><a href="{{url('displaymenu')}}"><i class="fa fa-circle-o"></i>View Menus</a></li>
    </ul>
</li>