Sudah lama tidak memperbaharui website, kali ini saya akan mencoba utk menggunakan DHTMLX dengan Laravel.

TULISAN INI UNTUK YANG SUDAH CUKUP MENGUASAI DHTMLX & LARAVEL (padahal saya tidak tau sama sekali makanan seperti apa itu Laravel ha ha ha :-) Tetap mencoba dan berusaha).

App Laravel DHTMLX yang saya develop ini tidak begitu memperhatikan segi keamanan jadi mohon tidak langsung menggunakannya mentah-mentah. Bagian CSRF, $_POST, escape query, sql injection saya abaikan (Maaf mastah2 Laravel soalnya saya baru lihat kemaren, ternyata Laravel itu makanan mirip bakwan wkwkwk).

Disini saya menggunakan Laravel 5.2 (kenapa, karena  bisa support PHP 5.5).

 

Langkah-langkahnya :

1. Install composer

2. Download dan pasang laravel menggunakan composer

3. Download Library DHTMLX PHP Connector dengan menggunakan composer. pada command prompt (Linux ataupun Windows), Dari dalam folder laravel ketikkan

composer require dhtmlx/connector-php 

4. copy folder codebase dan js yang isinya DHTMLX Framework dan Jquery ke public

 

5. Tambahkan 3 baris berikut di bagian head views/welcome.blade.php

<script type="text/javascript" src="/{{ URL::to('codebase/dhtmlx.js') }}"></script>
<link rel="stylesheet" type="text/css" href="/{{ URL::to('codebase/dhtmlx.css') }}">
<script type="text/javascript" src="/{{ URL::to('js/jquery.min.js') }}"></script> 

6. Buat database dan tabel address

CREATE TABLE `address` (
	`id` INT(4) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(30) NULL DEFAULT NULL,
	`phone` INT(11) NULL DEFAULT NULL,
	`email` VARCHAR(30) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
) 

7. Atur database user, password dan database name pada file .env yang ada di root directory laravel

8. Tambahkan Main Controller dengan perintah  

php artisan make:controller Main

9. Disini saya tidak memakai model karena menggunakan RAW Query, semuanya di Controller

$pdo = DB::getPdo();
$statement = $pdo->prepare($sql);
$statement->setFetchMode(\PDO::FETCH_ASSOC);
$statement->execute();

10. Tambahkan di app\Http\routes.php

Route::post('/main/form', 'MainController@getForm');

Route::get('/', function () {
    return view('welcome');
});

Route::controller('main', 'MainController'); 

11. Hapus middleware "\App\Http\Middleware\VerifyCsrfToken" pada app\Http\Kernel.php (agar proses CREATE,UPDATE DELETE tidak bermasalah csrf)

12. Isi file views/welcome.blade.php

<!DOCTYPE html>
<html>
    <head>
        <title>Laravel CRUD</title>

        <style>
            html, body {
                height: 100%;
                overflow: hidden;
                margin: 0;
            }
        </style>

        <script type="text/javascript" src="/{{ URL::to('js/jquery.min.js') }}"></script>
        <script type="text/javascript" src="/{{ URL::to('codebase/dhtmlx.js') }}"></script>
        <link rel="stylesheet" type="text/css" href="/{{ URL::to('codebase/dhtmlx.css') }}">        

    </head>
    <body>
    </body>
</html>

<script type="text/javascript">
    //Loading all view file
    var folder = "main/loadview?file=";  
    body = document.getElementsByTagName("head")[0];
    $.ajax({
        url : "main/listview", //list all view file
        dataType: "json",
        success: function (data) {
            data.forEach(function(item) {
                //append all view file to document body
                $("<script />", { type : "text/javascript", src : ""+ folder + item +""}).appendTo(body);
                
            });                  
        },
    });
</script>

 

13. Isi file views/1st.blade.php (file2 selain welcome.blade.php akan dipanggil oleh script jquery di bagian akhir welcome.blade.php, script-scipt ini di-append ke welcome.blade.php)

<?php

$script = <<<"JS"
	var mainLayout = new dhtmlXLayoutObject({
		parent: document.body,
		pattern: '2U',
		cells: [
			{
				id : 'a',
				text: 'Tabel' 
			},
			{
				id : 'b',
				text: 'Form Input' 
			}
		]

	});

	var grid = mainLayout.cells('a').attachGrid();
	grid.setHeader('Nama, Phone, Email');
	grid.attachHeader("#connector_text_filter,#connector_text_filter,#connector_text_filter");
	grid.setInitWidthsP('20,40,40');
	grid.enableSmartRendering(true);
	grid.init();

	grid.load("main/grid");

	var Form = mainLayout.cells("b").attachForm([
		{type: "block", offsetTop: 20, list:[
			{type: "input", name: "name", label: "Nama", inputWidth: 220, labelWidth: 120},
			{type: "input", name: "phone", label: "Phone", inputWidth: 220, labelWidth: 120},
			{type: "input", name: "email", label: "Email", inputWidth: 220, labelWidth: 120},
			// {type: "hidden", name: "_token", value: laraveltoken }

		]},
		{type: "block", offsetTop: 20, offsetLeft:20, list:[
			{type: "button", name: "tambah", value: "Tambah"},
			{type: "newcolumn"},
			{type: "button", name: "update", value: "Update", offsetLeft: 20},
			{type: "newcolumn"},
			{type: "button", name: "delete", value: "Delete", offsetLeft: 20}
		]}
	]);
	
	function clearForm() {
		Form.setItemValue("name", "");
		Form.setItemValue("phone", "");
		Form.setItemValue("email", "");
	}

	grid.attachEvent("onRowSelect", function(id, idx) {
		Form.load("main/form?id="+id);
	});

	var FormDP = new dataProcessor("main/form");
	FormDP.init(Form);

	FormDP.attachEvent("onAfterUpdate", function(id,action,tid,tag) {						
		
		switch (action) {
			case 'inserted':
				var message = tag.firstChild.data;
				dhtmlx.message({text: "Inserted<br>"+message, expire: 5000});
				grid.clearAndLoad("main/grid");
				clearForm();
				break;
			case 'updated':
				var message = tag.firstChild.data;
				dhtmlx.message({text: "Updated<br>"+message, expire: 5000});
				grid.clearAndLoad("main/grid");
				clearForm();				
				break;
			case 'deleted':
				var message = tag.firstChild.data;
				dhtmlx.message({text: "Deleted<br>"+message, expire: 5000});
				grid.clearAndLoad("main/grid");
				clearForm();
				break;
			case 'error':
				var message = tag.firstChild.data;
				dhtmlx.message({type: "error",text: "Error processing <br>"+Form.getItemValue('name')+"<br>"+message, expire: -1});
				break;
		}												
	});

	Form.attachEvent('onButtonClick', function(name) {
		switch (name) {
			case 'tambah':
				Form.resetDataProcessor("inserted");										
				Form.save();				
				break;
			case 'update':
				Form.resetDataProcessor("updated");
				Form.save();
				break;	
			case "delete":
				dhtmlx.modalbox({
					type: "alert-error",
					title: "Caution",
					text: "Are you sure to delete this item",
					buttons: ["Yes", "No"],
					callback: function(index) {
						if (index == 0) {
							Form.resetDataProcessor("deleted");
							Form.save();
						} else if (index == 1) {											
							return false;
						}
					}
				});
				break;	
		}
	});

JS;

echo $script;

?>

 

14. Adapun isi file MainController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use DB;
use Session;
use App\Address;
use App\Classes\Common;

use Dhtmlx\Connector\GridConnector;
use Dhtmlx\Connector\FormConnector;
use Dhtmlx\Connector\ComboConnector;
use Dhtmlx\Connector\XSSFilter\ConnectorSecurity;

class MainController extends Controller
{    

	public $err_message;


	public function xmlEscape($string) {
        return str_replace(array('&', '<', '>', '\'', '"'), array('&amp;', '&lt;', '&gt;', '&apos;', '&quot;'), $string);
    }


	//memuat data ke dalam grid/table
    public function getGrid() {            	

        $findingGrid = new GridConnector(NULL, "PHPLaravel");
        
        //CSRF
		if (!Session::has('dhx_security')){
			Session::put('dhx_security', md5(uniqid()) );
			Session::save();
		}
			
		if ( $findingGrid->is_select_mode() ) {	

			// otherwise PHP sends text/html, which could confuse browsers
	        header ("Content-Type: text/xml; charset=ISO-8859-1 "); 

	        //define variables from incoming values
	        if(isset($_GET["posStart"]))
	            $posStart = $_GET['posStart'];
	        else
	            $posStart = 0;
	        if(isset($_GET["count"]))
	            $count = $_GET['count'];
	        else
	            $count = 20;


	        $sql = "SELECT * FROM address ";

	        
	        //Filtering ['dhx_sort'][0] is column1, ['dhx_sort'][1] is column2   
	        $name = '';
	        $phone = '';
	        $email = '';

	        if ( isset($_GET['dhx_filter']) ) {
	        	if ( $_GET['dhx_filter'][0] != '' ) {
	        		$name = ConnectorSecurity::filter($_GET['dhx_filter'][0]);//xss
	        	}
	        	if ( $_GET['dhx_filter'][1] != '' ) {
	        		$phone = ConnectorSecurity::filter($_GET['dhx_filter'][1]);//xss
	        	}	
	        	if ( $_GET['dhx_filter'][2] != '' ) {
	        		$email = ConnectorSecurity::filter($_GET['dhx_filter'][2]);//xss
	        	}	           	
	        }
	        

	        if ( $name != '' || $phone !='' || $email != '') {
	        	$sql .= " WHERE name LIKE '%".$name."%' AND phone LIKE '%".$phone."%' AND email LIKE '%".$email."%' ";
	        }

	        // var_dump($sql);die();

        	//Smart rendering
	        if ( $posStart == 0 ) {
	        	$statement = DB::getPdo()->prepare($sql);
				$statement->setFetchMode(\PDO::FETCH_ASSOC);
				$statement->execute();
				$result = $statement->fetchAll();	
	            $totalCount = count($result);
	        } else {
	            $totalCount = '';
	        }

	        
	        //Sorting ['dhx_sort'][0] is column1, ['dhx_sort'][1] is column2
	        if ( isset($_GET['dhx_sort'][0])  ) {
	            switch ( $_GET['dhx_sort'][0] ) {
	                case 'asc':
	                    $sql .= " ORDER BY name ASC ";
	                    break;
	                case 'des':
	                    $sql .= " ORDER BY name DESC ";
	                    break;                  
	            }               
	        }

	        if ( isset($_GET['dhx_sort'][1])  ) {
	            switch ( $_GET['dhx_sort'][1] ) {
	                case 'asc':
	                    $sql .= " ORDER BY phone ASC ";
	                    break;
	                case 'des':
	                    $sql .= " ORDER BY phone DESC ";
	                    break;                  
	            }               
	        }

	        if ( isset($_GET['dhx_sort'][2])  ) {
	            switch ( $_GET['dhx_sort'][2] ) {
	                case 'asc':
	                    $sql .= " ORDER BY email ASC ";
	                    break;
	                case 'des':
	                    $sql .= " ORDER BY email DESC ";
	                    break;                  
	            }               
	        }


	        //add limits to query to get only rows necessary for the output
	        $sql.= " LIMIT ".$posStart.",".$count;

	        //query database to retrieve necessary block of data
	        // $result = DB::select($sql)->get();

	        $pdo = DB::getPdo();
			$statement = $pdo->prepare($sql);
			$statement->setFetchMode(\PDO::FETCH_ASSOC);
			$statement->execute();
			$result = $statement->fetchAll();	        

	        //output data in XML format, for smart rendering scroll load   
	        print("<rows total_count='".$totalCount."' pos='".$posStart."' dhx_security='".Session::get('dhx_security')."'>");
	        
	        foreach($result as $key => $row) {	 
	            print("<row id='".$row['id']."'>");
	                foreach ($row as $key => $value) {
	                    
	                    if ($key != 'id') {
	                        print("<cell>");
	                            print( $this->xmlEscape($row[$key]) ); 
	                        print("</cell>");
	                    }

	                }
	            print("</row>");
	        }

	        print("</rows>");
	        die();
	        

		} else {
			//other than SELECT query
			if ($_POST['dhx_security'] != Session::get('dhx_security')) {
				$this->err_message = "CSRF/XSRF detected";
				return "error";
			} else {

				//include XML Header (as response will be in xml format)
				header("Content-type: text/xml");
				//encoding may differ in your case
				echo('<?xml version="1.0" encoding="iso-8859-1"?>'); 
				//output update results
				echo "<data>";


				$ids = explode(",",$_POST["ids"]);
				//for each row
				for ($i=0; $i < sizeof($ids); $i++) { 
					$rowId = $ids[$i]; //id or row which was updated 
					$newId = $rowId; //will be used for insert operation	
					$mode = $_POST[$rowId."_!nativeeditor_status"]; //get request mode

					switch($mode){
						case "deleted":
							$action = $this->griddelete($rowId);
						break;
					}	
					echo "<action type='".$action."' sid='".$rowId."' tid='".$newId."'>";
					
					if ($action == 'error') {
						echo "<![CDATA[".$this->err_message."]]>";
					} else {
						echo "<![CDATA[".$_POST[$rowId.'_c0']."]]>";
					}
				}

				echo "</action></data>";
			}

			die();
		}	

    }

    
	//Saat buka front page, listview(di bawah) akan memanggil loadview ini
    public function getLoadview() {		
		$file = $_GET['file'];
		//remove blade.php from name		
		if ($file != "welcome.blade.php") {
			$file = strtok($file, '.blade.php');
			return view($file);
		}
					
	}

	//list view files name
	public function getListview() {
		$path    = base_path().'/resources/views';		
		$dh  = opendir($path);
		while (false !== ($filename = readdir($dh))) {
		    $files[] = $filename;
		}

		$allviews =preg_grep ('/\.php$/i', $files);	

		$listview = [];
		foreach ($allviews as $view) {
			$listview[] = $view;
		}
		sort($listview);
		
		echo(json_encode($listview));
	}

	public function getForm() {

		$Form = new FormConnector(NULL, "PHPLaravel");


		//CSRF
		if (!Session::has('dhx_security')){
			Session::put('dhx_security', md5(uniqid()) );
			Session::save();
		}


		if ($Form->is_select_mode()) {

			header ("Content-Type: text/xml; charset=ISO-8859-1 "); 

	        $sql = "SELECT id, name, phone, email FROM address ";
	        $id = ConnectorSecurity::filter($_GET['id']);
	        $sql .= " WHERE id=".$id;

	        $pdo = DB::getPdo();
			$statement = $pdo->prepare($sql);
			$statement->setFetchMode(\PDO::FETCH_ASSOC);
			$statement->execute();
			$result = $statement->fetchAll();	   

	        //output data in XML format   
	        print("<data dhx_security='".Session::get('dhx_security')."'>");	            
        
				foreach ($result[0] as $key => $value) {
					if ($key != 'id') {
				        print("<". $key. ">");
				            print( $this->xmlEscape($value) ); 
				        print("</". $key. ">");
				    }
				}     

	        print("</data>");
	        die();

		} else {

			if ($_POST['dhx_security'] != Session::get('dhx_security')) {
				$this->err_message = "CSRF/XSRF detected";
				return "error";
			} else {

				//include XML Header (as response will be in xml format)
				

				//output update results
				echo "<data>";

							
					$rowId = $_POST['ids'];
					$newId = $rowId; //will be used for insert operation	
					$mode = $_POST[$rowId."_!nativeeditor_status"]; //get request mode

					switch($mode){
						case "inserted":
							$action = $this->forminsert($rowId);						
							break;
						case "updated":
							$action = $this->formupdate($rowId);
							break;
						case "deleted":
							$action = $this->formdelete($rowId);
							break;
					}	

					echo "<action type='".$action."' sid='".$rowId."' tid='".$newId."'>";

					if ($action == 'error') {
						echo "<![CDATA[".$this->err_message."]]>";
					} else {
						echo "<![CDATA[".$_POST[$rowId.'_name']."]]>";
					}
				

				echo "</action></data>";
				die();
			}

		}	

	}	


	private function forminsert($rowId) {
		$name = ConnectorSecurity::filter($_POST[$rowId.'_name']);
		$phone = ConnectorSecurity::filter($_POST[$rowId.'_phone']);
		$email = ConnectorSecurity::filter($_POST[$rowId.'_email']);		

		$sql = "INSERT INTO address(name,phone,email) VALUES ('".$name."','".$phone."', '".$email."')";

		$pdo = DB::getPdo();
		$statement = $pdo->prepare($sql);
		$statement->setFetchMode(\PDO::FETCH_ASSOC);
		$result = $statement->execute();
		
		if ( $result ) {
			return "inserted";
		} else {
			$this->err_message = "DB Error";
			return "error";
		}
		
	}

	private function formupdate($rowId) {		

		$name = ConnectorSecurity::filter($_POST[$rowId.'_name']);
		$phone = ConnectorSecurity::filter($_POST[$rowId.'_phone']);		
		$email = ConnectorSecurity::filter($_POST[$rowId.'_email']);

		$sql = "UPDATE address SET name = '".$name."', phone = '".$phone."', email = '".$email."' WHERE id= ".$rowId;

		$pdo = DB::getPdo();
		$statement = $pdo->prepare($sql);
		$statement->setFetchMode(\PDO::FETCH_ASSOC);
		$result = $statement->execute();
		
		if ( $result ) {
			return "updated";
		} else {
			$this->err_message = "DB error";
			return "error";
		}
		
	}


	private function formdelete($rowId) {	
		$rowId = ConnectorSecurity::filter($rowId);
		$sql = "DELETE FROM address WHERE id= ".$rowId;

		$pdo = DB::getPdo();
		$statement = $pdo->prepare($sql);
		$statement->setFetchMode(\PDO::FETCH_ASSOC);
		$result = $statement->execute();
		
		if ( $result ) {
			return "deleted";
		} else {
			$this->err_message = "DB Error";
			return "error";
		}
		
	}

}


 

DEMO


 

Add comment


Security code
Refresh

Tutorial DHTMLX

29 Agu 2015 07:33
1. Konstruksi DHTMLX
30 Agu 2015 07:33
2. CRUD sederhana
01 Sep 2015 10:08
3. Toko Online
02 Sep 2015 10:11
4. Galeri Gambar
03 Sep 2015 05:30
5. Grafik
04 Sep 2015 07:33
6. Export Grid

Visitor

Indonesia 80.1% Indonesia
United States 10.4% USA

Total:

67

Countries
006269
Today: 13
This Week: 13
This Month: 138