ผมได้ออกแบบฐานข้อมูลชื่อ db_cakephp และสร้างเทเบิล products กับ categories ดังรูป
มาดูโค๊ดกันเลยครับ
1.สร้างไฟล์ ValidationHelper.php ไว้ใน View/Helper ให้ใช้โค๊ดดังนี้
<?php /* * CakePHP jQuery Validation Plugin * Copyright (c) 2009 Matt Curry * www.PseudoCoder.com * http://github.com/mcurry/cakephp_plugin_validation * http://sandbox2.pseudocoder.com/demo/validation * * @author mattc <matt@pseudocoder.com> * @license MIT * */ //feel free to replace these or overwrite in your bootstrap.php if (!defined('VALID_EMAIL_JS')) { define('VALID_EMAIL_JS', '/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/'); } //I know the octals should be capped at 255 if (!defined('VALID_IP_JS')) { define('VALID_IP_JS', '/^[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}\.[\d]{1,3}$/'); } class ValidationHelper extends Helper { var $helpers = array('Javascript'); //For security reasons you may not want to include all possible validations. //In your bootstrap you can define which are allowed //Configure::write('javascriptValidationWhitelist', array('alphaNumeric', 'minLength')); var $whitelist = false; public function bind($modelNames, $options=array()) { $defaultOptions = array('form' => 'form', 'inline' => true, 'root' => Router::url('/'), 'watch' => array(), 'catch' => true); $options = am($defaultOptions, $options); $pluginOptions = array_intersect_key($options, array('messageId' => true, 'root' => true, 'watch' => true)); //load the whitelist $this->whitelist = Configure::read('javascriptValidationWhitelist'); $validation = array(); if (!is_array($modelNames)) { $modelNames = array($modelNames); } //filter the rules to those that can be handled with JavaScript foreach($modelNames as $modelName) { $model = classRegistry::init($modelName); $arr=explode('.',$modelName); $realModelName=$arr[0]; foreach ($model->validate as $field => $validators) { if (array_intersect(array('rule', 'allowEmpty', 'on', 'message', 'last'), array_keys($validators))) { $validators = array($validators); } foreach($validators as $key => $validator) { $rule = null; if (!is_array($validator)) { $validator = array('rule' => $validator); } //skip rules that are applied only on created or updates if (!empty($validator['on'])) { continue; } if (!isset($validator['message'])) { $message = sprintf(__($key, true), __($field, true)); if($key != $message) { $validator['message'] = $message; } else { $validator['message'] = sprintf('%s %s', __('There was a problem with the field', true), Inflector::humanize($field) ); } } if (!empty($validator['rule'])) { $rule = $this->__convertRule($validator['rule']); } if ($rule) { $temp = array('rule' => $rule, 'message' => __($validator['message'], true) ); if (isset($validator['last']) && $validator['last'] === true) { $temp['last'] = true; } if (isset($validator['allowEmpty']) && $validator['allowEmpty'] === true) { $temp['allowEmpty'] = true; } if (in_array($validator['rule'], array('blank'))) { //Cake Validation::_check returning true is actually false for blank //add a "!" so that JavaScript knows $temp['negate'] = true; } $validation[$realModelName . Inflector::camelize($field)][] = $temp; } } } if(!empty($pluginOptions['watch'])) { $pluginOptions['watch'] = $this->__fixWatch($modelName, $pluginOptions['watch']); } } if ($options['form']) { if($options['catch']) { $js = sprintf('$(function() { $("%s").validate(%s, %s) });', $options['form'], $this->Javascript->object($validation), $this->Javascript->object($pluginOptions)); } else { $js = sprintf('$(function() { $("%s").data("validation", %s) });', $options['form'], $this->Javascript->object($validation)); } } else { return $this->Javascript->object($validation); } if ($options['inline']) { return sprintf($this->Javascript->tags['javascriptblock'], $js); } else { $this->Javascript->codeBlock($js, array('inline' => false)); } return; } public function __convertRule($rule) { $regex = false; if ($rule == '_extract') { return false; } $params = array(); if (is_array($rule)) { $params = array_slice($rule, 1); $rule = $rule[0]; } if (is_array($this->whitelist) && !in_array($rule, $this->whitelist)) { return false; } if ($rule == 'comparison') { $params[0] = str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', strtolower($params[0])); switch ($params[0]) { case 'isgreater': $params[0] = '>'; break; case 'isless': $params[0] = '<'; break; case 'greaterorequal': $params[0] = '>='; break; case 'lessorequal': $params[0] = '<='; break; case 'equalto': $params[0] = '=='; break; case 'notequal': $params[0] = '!='; break; } } //Certain Cake built-in validations can be handled with regular expressions, //but aren't on the Cake side. switch ($rule) { case 'alphaNumeric': return '/^[0-9A-Za-z]+$/'; case 'between': return sprintf('/^.{%d,%d}$/', $params[0], $params[1]); case 'boolean': return array('rule' => 'boolean'); case 'date': //Some of Cake's date regexs aren't JavaScript compatible. Skip for now if (!empty($params[0])) { $params = $params[0]; } else { $params = 'ymd'; } return array('rule' => 'date', 'params' => $params); case 'email': return VALID_EMAIL_JS; case 'equalTo': return sprintf('/^%s$/', $params[0]); case 'extension': if (empty($params[0])) { $params = array('gif', 'jpeg', 'png', 'jpg'); } else { $params = $params[0]; } return sprintf('/\.(%s)$/', implode('|', $params)); case 'inList': return array('rule' => 'inList', 'params' => $params[0]); case 'ip': return VALID_IP_JS; case 'minLength': return sprintf('/^[\s\S]{%d,}$/', $params[0]); case 'maxLength': return sprintf('/^[\s\S]{0,%d}$/', $params[0]); case 'money': //The Cake regex for money was giving me issues, even within PHP. Skip for now return array('rule' => 'money'); case 'multiple': $defaults = array('in' => null, 'max' => null, 'min' => null); $params = array_merge($defaults, $params[0]); return array('rule' => 'multiple', 'params' => $params); case 'notEmpty': return array('rule' => 'notEmpty'); case 'numeric': //Cake uses PHP's is_numeric function, which actually accepts a varied input //(both +0123.45e6 and 0xFF are valid) then what is allowed in this regular expression. //99% of people using this validation probably want to restrict to just numbers in standard //decimal notation. Feel free to alter or delete. return '/^[+-]?[0-9|.]+$/'; case 'range': case 'comparison': //Don't think there is a way to do this with a regular expressions, //so we'll handle this with plain old javascript return array('rule' => $rule, 'params' => array($params[0], $params[1])); } //try to lookup the regular expression from //CakePHP's built-in validation rules $Validation =& Validation::getInstance(); if (method_exists($Validation, $rule)) { $Validation->regex = null; call_user_func_array(array(&$Validation, $rule), array_merge(array(true), $params)); if ($Validation->regex) { $regex = $Validation->regex; } } if ($regex) { //special handling switch ($rule) { case 'postal': case 'ssn': //I'm not a regex guru and I have no idea what "\\A\\b" and "\\b\\z" do. //Is it just to match start and end of line? Why not use //"^" and "$" then? Eitherway they don't work in JavaScript. return str_replace(array('\\A\\b', '\\b\\z'), array('^', '$'), $regex); } return $regex; } // If not rule is selected handle with a regular expression return($rule); } public function __fixWatch($modelName, $fields) { foreach($fields as $i => $field) { if (strpos($field, '.') !== false) { list($model, $field) = explode('.', $field); $fields[$i] = ucfirst($model) . ucfirst($field); } else { $fields[$i] = $modelName . ucfirst($field); } } return $fields; } } ?>
2.สร้างไฟล์ validation.js ใน webroot/js ให้ใช้โค๊ดดังนี้
/* * CakePHP jQuery Validation Plugin * Copyright (c) 2009 Matt Curry * www.PseudoCoder.com * http://github.com/mcurry/cakephp_plugin_validation * http://sandbox2.pseudocoder.com/demo/validation * * @author mattc <matt@pseudocoder.com> * @license MIT * */ (function($) { $.fn.validate = function(rules, opts) { options = $.extend({watch: []}, opts); $.each(options.watch, function(fieldId) { $("#" + options.watch[fieldId]).change(function() { $.fn.validate.ajaxField($(this)); }); }); return this.each(function() { $this = $(this); $this.submit(function() { return $.fn.validate.check(rules); }); }); }; $.fn.validate.check = function(rules) { var errors = []; var val = null; $.fn.validate.beforeFilter(); $.each(rules, function(field) { $field = $("#" + field); if ($field.attr("type") == "checkbox") { if ($field.filter(":checked").length > 0) { val = $field.filter(":checked").val(); } else { val = "0"; } } else { val = $field.val(); } var fieldName = $field.attr('name'); if (typeof val == "string") { val = $.trim(val); } $.each(this, function() { //field doesn't exist...skip if ($("#" + field).attr("id") == undefined) { return true; } if (this['allowEmpty'] && typeof val == "string" && val == '') { return true; } if (this['allowEmpty'] && typeof val == "object" && val == null) { return true; } if (!$.fn.validate.validateRule(val, this['rule'], this['negate'], fieldName)) { errors.push(this['message']); $.fn.validate.setError(field, this['message']); if (this['last'] === true) { return false; } } }); }); $.fn.validate.afterFilter(errors); if (errors.length > 0) { return false; } return true; } $.fn.validate.validateRule = function(val, rule, negate, fieldName) { if (negate == undefined) { negate = false; } //handle custom functions if (typeof rule == 'object') { if ($.fn.validate[rule.rule] != undefined) { return $.fn.validate[rule.rule](val, rule.params, fieldName); } else { return true; } } //handle regex rules if (negate && val.match(eval(rule))) { return false; } else if (!negate && !val.match(eval(rule))) { return false; } return true; }; $.fn.validate.boolean = function(val) { return $.fn.validate.inList(val, [0, 1, '0', '1', true, false]); }; $.fn.validate.comparison = function(val, params) { if (val == "") { return false; } val = Number(val); if (val == "NaN") { return false; } if (eval(val + params[0] + params[1])) { return true; } return false; }; $.fn.validate.inList = function(val, params) { if (params != null) { if ($.inArray(val, params) == -1) { return false; } } return true; }; $.fn.validate.multiple = function(val, params) { if (typeof val != "object" || val == null) { return false; } if (params.min != null && val.length < params.min) { return false; } if (params.max != null && val.length > params.max) { return false; } if (params["in"] != null) { for (i = 0; i < params["in"].length; i++) { if ($.inArray(params["in"][i], val) == -1) { return false; } } } return true; }; $.fn.validate.notEmpty = function(val, params) { if (typeof val == "string" && val == "") { return false; } if (typeof val == "object" && val.length == 0) { return false; } return true; } $.fn.validate.range = function(val, params) { if (val < parseInt(params[0])) { return false; } if (val > parseInt(params[1])) { return false; } return true; }; $.fn.validate.ajaxField = function($field) { $.fn.validate.clearError($field); $.fn.validate.ajaxBeforeFilter($field); var data = new Object; data[$field.attr("name")] = $field.val(); $.post(options.root + "js_validate/field/" + $field.attr("id"), data, function(validates) { $.fn.validate.ajaxAfterFilter($("#" + validates.field)); if (!validates.result) { $.fn.validate.setError(validates.field, validates.message); } }, "json"); } $.fn.validate.ajaxBeforeFilter = function($field) { $field.after("<img class=\"ajax-loader\" src=\"" + options.root + "js_validate/img/ajax-loader.gif\">"); } $.fn.validate.ajaxAfterFilter = function($field) { $field.siblings(".ajax-loader").remove(); } $.fn.validate.clearError = function($field) { if (typeof $field == "string") { $field = $("#" + field); } $field.removeClass("form-error").parents("div:first").removeClass("error").children(".error-message").remove(); } $.fn.validate.setError = function(field, message) { $("#" + field).addClass("form-error").parents("div:first").addClass("error").append('<div class="error-message">' + message + '</div>'); }; $.fn.validate.beforeFilter = function() { if (options.messageId != null) { $("#" + options.messageId).html("").slideDown(); } $(".error-message").remove(); $("input").removeClass("form-error"); $("div").removeClass("error") }; $.fn.validate.afterFilter = function(errors) { if (options.messageId != null) { $("#" + options.messageId).html(errors.join("<br />")).slideDown(); } }; var options = []; })(jQuery);
แค่นี้เราก็ได้ Validation Javascript ไว้ใช้งานแล้วครับ ต่อมาก็เป็นวิธีใช้ครับ
3.สร้างไฟล์ ProductsController.php ในโฟลเดอร์ Controller ให้พิมพ์โค๊ดดังนี้
<?php class ProductsController extends AppController { public $name = 'Products'; public $helpers = array('Html', 'Form', 'Validation'); //เรียกใช้ Helpers ให้ทำงานในส่วนของ View public $uses = array('Product', 'Category'); //เรียกใช้ Model Product,Category public function add() { $this->set('title_for_layout', 'เพิ่มรายการสินค้า'); if ($this->request->is('post')) {//ตรวจว่ามีการส่งค่าแบบ post เข้ามา $data = $this->data['Product']; if ($this->Product->save($data)) {//Validationและบันทึกข้อมูลและReturnค่ากลับมาในคำสั่งนี้ //บันทึกข้อมูลเรียบร้อยแล้ว } } $categories = $this->Category->getCategory(); //ไปดึงข้อมูลหมวดสินค้าจากเมธอด getCategoy() ใน Class Category จากไฟล์ Category.php $this->set('category', $categories); } } ?>
4.ในส่วนของ Model ให้สร้างไฟล์ Product.php ไว้ในโฟลเดอร์ Model ครับ และพิมพ์โค๊ดดังนี้
<?php class Product extends AppModel { public $name = 'Product'; var $validate = array( 'name' => array( 'notEmpty' => array( 'rule' => 'notEmpty', 'required' => true, 'message' => 'กรุณากรอกชื่อสินค้า' ), 'between' => array( 'rule' => array('minLength', 5), 'message' => 'กรุณาระบุชือสินค้าไม่ต่ำกว่า 5 ตัวอักษร' ) ), 'category_id' => array( 'rule' => 'notEmpty', 'message' => 'กรุณาเลือกประเภทสินค้า' ), 'quantity' => array( 'rule' => 'numeric', 'message' => 'กรุณาระบุจำนวนเป็นตัวเลข' ), 'price' => array( 'rule' => 'numeric', 'message' => 'กรุณาระบุราคาเป็นตัวเลข' ), 'image' => array( 'rule' => 'notEmpty', 'message' => 'กรุณาเลือกรูปสินค้า' ) ); } ?>
5.Model อีกตัวนึงคือ Category เพื่อสำหรับไว้แสดงหมวดสินค้า ให้สร้างไฟล์ชื่อ Category.php ไว้ในโฟลเดอร์ Model และให้ใช้โค๊ดังนี้
<?php class Category extends AppModel{ public $name='Category'; public $validate =array( 'name'=>array( 'notEmpty'=>array( 'rule'=>'notEmpty','message'=>'กรอกชือหมวดสินค้าด้วยครับ' ) ) ); public function getCategory(){ return $this->find('list',array('fields'=>array('Category.id','Category.name'),'order'=>'Category.name ASC') ); } } ?>
6.สร้างไฟล์ add.php ใน View/Products/ ครับ และให้พิมพ์โค๊ดดังนี้
<?php echo $this->Html->script('validation');//เรียกใช้ validation.js echo $this->Html->script('ckeditor/ckeditor');//เรียกใช้ ckeditor/ckeditor.js echo $this->Form->create('Product', array('action' => 'add'));//สร้างฟอร์ม echo $this->Validation->bind('Product');//เรียกใช้ Validation จาก Model "Product" ?> <table width="780" border="0" align="center" cellpadding="4" cellspacing="0"> <tr> <td colspan="2" align="center" ><h2>เพิ่มรายการสินค้า</h2></td> </tr> <tr> <td align="right"><strong>ชื่อสินค้า</strong></td> <td><?php echo $this->Form->input('name', array('label' => false, 'style' => 'width:450px')); ?></td> </tr> <tr> <td align="right"><strong>ประเภทสินค้า</strong></td> <td><?php echo $this->Form->input('category_id', array('label' => false, 'type' => 'select', 'empty' => 'เลือกประเภท', 'options' => $category)); ?></td> </tr> <tr> <td align="right"><strong>จำนวน</strong></td> <td><?php echo $this->Form->input('quantity', array('label' => false, 'style' => 'width:80px')); ?></td> </tr> <tr> <td align="right"><strong>ราคา</strong></td> <td><?php echo $this->Form->input('price', array('label' => false, 'style' => 'width:100px')); ?></td> </tr> <tr> <td align="right"><strong>เลือกรูปสินค้า</strong></td> <td><?php echo $this->Form->input('image', array('label' => false, 'type' => 'file')); ?></td> </tr> <tr> <td align="right"><strong>รายละเอียด</strong></td> <td><?php echo $this->Form->textarea('detail', array('label' => false, 'cols' => '70', 'rows' => '20')); echo $this->Ckeditor->loadcustom('Product.detail'); //วิธีเลือกใช้ ชือโมเดล.ชื่อฟิลด์ ?></td> </tr> <tr> <td width="150"> </td> <td><?php echo $this->Form->submit('บันทึกข้อมูล'); ?> </td> </tr> </table> <?php echo $this->Form->end(); ?>
จากนั้นให้ลองรันทดสอบ โดยพิมพ์ว่า http://localhost/cakephp/products/add
ไม่มีความคิดเห็น :
แสดงความคิดเห็น