วันจันทร์ที่ 29 พฤศจิกายน พ.ศ. 2553

jquery ซ่อนแสดง show/hide column โดยใช้ checkbox


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jquery show hide column</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(function(){
var tb = $('#column_hidable');
var cbp = $('#checkbox_panel');
tb.find('tr:first > td').each(function(){
var cb = $('<input type="checkbox" checked="checked" />').click(function(){
var cbidx = cbp.find(':checkbox').index($(this));
tb.find('tr').each(function(){
$(this).find('td').eq(cbidx).toggle();
});
});
cb.appendTo(cbp).after($(this).text()+'<br'+'/>');
});
});
</script>
</head>

<body>

<?php
$cols = array("Field 1","Field 2","Field 3","Field 4","Field 5");
?>
<div id="checkbox_panel"></div>
<table border="1" cellspacing="0" cellpadding="5" id="column_hidable">
<tr bgcolor="#CC99FF">
<?php foreach($cols as $col_name):?>
<td><?php echo $col_name;?></td>
<?php endforeach;?>
</tr>
<?php $i=0; while($i++<5):?>
<tr>
<?php foreach($cols as $col_name):?>
<td><?php echo $col_name;?></td>
<?php endforeach;?>
</tr>
<?php endwhile;?>
</table>

</body>
</html>

วันอาทิตย์ที่ 28 พฤศจิกายน พ.ศ. 2553

google order check tool

เวลาค้นหาว่าเว็บอยู่อันดับไหนใน google ถ้าไม่ได้อยู่หน้าบนๆ นับลำดับกันลำบากทีเดียวครับ
ผมเลยทดลองเขียนโปรแกรมสำหรับช่วยหาอันดับเว็บไซท์โดยใช้ jquery โหลดข้อมูลมาทาง ajax ว่าจะโหลดมาได้หรือเปล่า
(ตอนแรกไม่ค่อยแน่ใจ เพราะไม่รู้ google จะกันไม่ให้โหลดหน้าเว็บไซท์มาได้หรือเปล่า)

เมื่อเขียนออกมาเวอร์ชั่นแรกใช้กับ firefox และ opera ได้ดีทีเดียว แต่เอามาใช้กับ ie ได้ไม่ดีเลยใช้แล้วโปรแกรมค้างเลยครับ
ผมเข้าใจว่าเป็นเพราะ ie ไม่สามารถโหลดข้อมูล html โดยใช้ ajax ได้เยอะๆ0

เวอร์ชั่นนี้เป็นเวอร์ชั่นใหม่แก้ใหม่สามารถใช้ได้ด้ทั้ง ie และ firefox ครับ
สำหรับท่านที่เคยโหลดเวอร์ชั่นแรกไปแนะนำให้เปลี่ยนมาใช้เวอร์ชั่นนี้จะเร็วขึ้นกว่าเดิมหลายเท่าครับ
เพราะเวอร์ชั่นแรกผมปล่อยให้ server ส่ง html มาตรงๆ เลย 100K คราวนี้ใช้ function ตัด string มาเฉพาะที่ใช้เหลือแค่ 4-5K เท่านั้นครับ :D

เวอร์ชั่น 2 ทำให้เร็วขึ้น แต่ทำการค้นหาเพียงหน้าเดียว (หน้าละ 5, 10, 20, 50, 100 รายการ)
เวอร์ชั่น 3 สามารถค้นหาหน้าละ 10 รายการ หลายๆ หน้า ทำให้ได้ผลลัพธ์เหมือนการค้นหาแบบปกติ


<?php
if (isset($_GET['search'])){
set_time_limit (60);

unset($_GET['search']);
//set total num (total result)
$total_num = ($_GET['total_num']>100) ?100:intval($_GET['total_num']);
unset($_GET['total_num']);

//set num (num per page)
$num = ($_GET['num']<5) ?5:intval($_GET['num']);
if ($num==10){
unset($_GET['num']);
}

//set default query
$q = '';
foreach($_GET as $k=>$v){
$q.='&'.urlencode($k).'='.urlencode($v);
}

//request all result from google
$s = '';
$start_num = 0;
while ($start_num < $total_num) {
$start = '&start='.$start_num;
$buffer = file_get_contents('http://www.google.co.th/search?'.$q.$start);
if (empty($buffer)){
$s .= '<cite>ERROR</cite>';
break;
}else{
$buffer = strstr($buffer,'<ol>');
$s .= substr($buffer,0,strpos($buffer,'</ol>')+5);
}
$start_num += $num;
}

//create xml response
header('Content-type:text/html;charset=tis-620');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("cache-Control: no-store, no-cache, must-revalidate");
header("cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$matches = array();
preg_match_all('/<cite>(.+?)<\/cite>/',$s,$matches,PREG_SET_ORDER);
unset($s);
$cites = '';
foreach($matches as $m){
list($c) = explode(' - ',strip_tags($m[1]));
$c = preg_replace('/\s+/','',$c);
$cites .= "<c>{$c}</c>";
}
echo "<google>{$cites}</google>";
exit();
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="th" xml:lang="th">
<head>
<title>google order check tool</title>
<meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<script type="text/javascript">
/*<![CDATA[*/
var gTimer;
var gProgress;
function progress(){
if (gProgress){
gProgress.val(gProgress.val()*1+1);
}
gTimer = setTimeout('progress()',1000);
}
function clearProgress(){
gProgress.val(0);
if (gTimer) clearTimeout(gTimer);
}
$(document).ready(function(){
var website = $('#website');
var num = $('#num');
var total_num = $('#total_num');
var keyword = $('#keyword');
var order = $('#order');
var result = $('#result');
gProgress = $('#progress');

$('#searchForm').submit(function(e){
var meta = $('input[name=meta]:checked');
var data;
if (meta.val()=='')
data = {
q: keyword.val(),
num: num.val(),
total_num: total_num.val(),
oe: 'ISO-8859-11',
sa: 'N'
};
else
data = {
hl: 'th',
q: keyword.val(),
as_qdr: 'all',
num: num.val(),
total_num: total_num.val(),
meta: meta.val(),
oe: 'ISO-8859-11',
sa: 'N'
};
$.ajax({
dataType: 'html',
type: "GET",
url: "?search",
data: data,
beforeSend: function() {
clearProgress();
progress();
order.html('');
result.html('');
},
success: function(google) {
var strOrder='';
var strResult='';
var websiteTrim=website.val().replace(/^\s+|\s+$/g,'');
$('c',google).each(function(n){
var site = $(this).text();
n++;
if (websiteTrim=='' || site.indexOf(websiteTrim) == -1) {
strResult += n+': '+site+'<br'+' />';
} else {
strOrder += websiteTrim+' ติดอันดับที่ '+n+
' ของ keyword \''+keyword.val()+'\'<br'+' />';
strResult += n+': <span >'+site+'</span>'+'<br'+' />';
}
});
clearProgress();
result.hide();
if (strOrder=='') {
order.html('ยังไม่ติดอันดับ '+total_num.val()+' อันดับแรก');
}else{
order.html(strOrder);
}
if (strResult=='') {
result.html('ไม่พบผลลัพธ์จาก keyword นี้').show('normal');
}else{
result.html(strResult).show('normal');
}
},
error: function(a,b,c){
alert(b);
}
});
return false;
});
});
/*]]>*/
</script>
</head>
<body>

<b>ค้นหา ว่า website 'website' ติด 100 อันดับแรกของ keyword 'keyword' หรือยัง</b>
<br />

<div><form action="?" id="searchForm">
website: <input type="text" id="website" /><br />
keyword: <input type="text" id="keyword" /><br />
แสดงหน้าละ: <select id="num">
<option value="5">5</option>
<option value="10" selected="selected">10</option>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<br />
result: <select id="total_num">
<option value="5">5</option>
<option value="10">10</option>
<option value="20" selected="selected">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
<option value="60">60</option>
<option value="70">70</option>
<option value="80">80</option>
<option value="90">90</option>
<option value="100">100</option>
</select>
<br />
ค้นหา :
<input type="radio" name="meta" value="" checked="checked" />เว็บ
<input type="radio" name="meta" value="lr=lang_th" />หน้าที่เป็นภาษาไทย
<input type="radio" name="meta" value="cr=countryTH" />เว็บจากประเทศไทย
<br />
progress: <input type="text" id="progress" /><br />

<input type="submit" id="request" value="search" />
</form></div>

<div style="background-color:yellow">
อันดับ : <br /><span id="order"></span>
</div>
<div style="background-">
ผลลัพธ์ : <span id="result"></span>
</div>

</body>
</html>



มีคนเคยแจ้งมาว่าโค้ดใช้การไม่ได้ผมตรวจดูแล้ว
เกิดจากเว็บโฮสนั้นไม่อนุญาติให้ใช้ allow url fopen (เปิดอ่าน url)
ลองตรวจสอบจุดนี้ก่อนครับ หลังจากนั้นถ้ายังไม่ได้แจ้งให้ผมตรวจสอบแก้ไขได้ครับ

วันศุกร์ที่ 26 พฤศจิกายน พ.ศ. 2553

service user pattern

ในการเขียน function เราก็สามารถจัดระเบียบให้เป็น oop pattern รูปแบบหนึ่งได้เช่นกันครับ
( เป็น oop โดยการจัดรูปแบบ )

เช่น
/services/global-service.php
/services/project1-service.php
/services/project2-service.php
/services/project3-service.php
กับ
/project1/home.php
/project1/contactus.php
ซึ่งเราจะแบ่งส่วนให้มีส่วนประกาศ function เฉพาะใน mylibs เท่านั้น
และส่วนเรียกใช้งาน function ต่างๆจะมีอยู่ใน user เท่านั้น
ซึ่งเราอาจจะเรียกว่า oop แบบนี้ว่าเป็น service - user pattern ครับ
โดยมีไฟล์กลุ่มหนึ่งทำหน้าที่เป็น service ไฟล์อีกกลุ่มหนึ่งทำหน้าที่เรียกใช้ service object เรียกว่า user object
โดย service จะไม่เข้าไปปะปนกับ user ,แบ่งหน้าที่โดย service เป็นผู้ให้บริการส่วน user เป็นผู้เรียกและขอรับบริการจาก service เท่านั้น

global-service.php
<?php
function f1(){...}
?>

project1-service.php
<?php
function f2(){...}
?>

เราอาจจะนับได้ว่า project1-service.php ได้รับการสืบทอบมาจาก global-service.php

ซึ่งในการเรียก service มาใช้งานเพื่อความสะดวกเราจะสร้างไฟล์สำหรับ initial ค่าต่างๆ สำหรับ project
ซึ่่งไฟล์ดังกล่าวจะเป็น user ที่ทำการติดต่อกับ service ก่อน user อื่นๆ ทุกครั้งขึ้นมาโดยให้ชื่อว่า coordinator.php (แปลว่าผู้ติดต่อประสานงาน)

coordinator.php
<?php
require '/services/global-service.php';
require '/services/project1-service.php';
//connect db
//initial project1 global value
?>

home.php
<?php
require 'coordinator.php';
f1();
f2();
?>

เรียกได้ว่า home.php สืบทอดคุณสมบัติจาก coordinator.php เพื่อทำการติดต่อกับ service ต่างๆ

แต่การเขียนแบบนี้ส่วนใหญ่เรามักจะไม่ระมัดระวังโดยมักจะแทรก function ในไฟล์ user
และแอบแทรกคำสั่งทำงานทันทีในส่วน service
ซึ่งทำให้หาส่วนประกาศ function ยาก และหาลำดับขั้นตอนการทำงานตั้งแต่เริ่มต้นยากครับ

วันพฤหัสบดีที่ 25 พฤศจิกายน พ.ศ. 2553

singleton pattern


<?php
//singleton โครงสร้างเพื่อป้องกันไม่ให้มีการสร้าง instance ขึ้นหลายครั้ง
//อย่างเช่น database class connection ที่ควรจะมีแค่ครั้งเดียว

class Example
{
private static $obj;
private function __construct() {}
public static function singleton() // singleton method
{
if (!isset(self::$obj)) {
$c = __CLASS__;
self::$obj = new $c;
}
return self::$obj;
}
public function __clone(){ // Prevent users to clone the instance
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}

$obj = Example::singleton();
//$obj = new Example();// error (private constructor)
//$obj2 = clone $obj;// error

?>

template method


<?php
//template method คือ
//method ที่เตรียมไว้เป็นโครงสร้างแต่คำสั่งที่จะปรับปรุงเงื่อนไขต่างๆ ที่ซับซ้อน
//จะมอบให้เป็นหน้าที่ของ function ที่มันเรียกอีกทีหนึ่ง

abstract class Shape
{
public abstract function height();
public abstract function width();
public function area(){ //template method
return $this->height()*$this->width();
}
}

class Rectangle extends Shape
{
function height(){ return 10;}
function width(){ return 20;}
}

class Square extends Shape
{
function height(){ return 10;}
function width(){ return 10;}
}

$r = new Rectangle(); echo $r->area();
echo '<br','>';
$s = new Square(); echo $s->area();

?>

jquery curve rounded corner

http://malsup.com/jquery/corner/
http://blue-anvil.com/jquerycurvycorners/test.html
http://www.curvycorners.net/

image corner technic

javascript only number ควบคุมให้ป้อนข้อมูลได้เฉพาะตัวเลขเท่านั้น

นำเสนอสองวิธีการในการควบคุมครับ วิธีแรก replaceDigit เป็นการแทนค่า string ที่ผู้ใช้ป้อนเข้าไปครับ
วิธีที่สองเป็น appeptOnlyDigit จะยอมรับคำสั่งที่ป้อนมาทาง keyboard เฉพาะตัวเลขและรหัสควบคุมบางตัวเท่านั้นครับ
ทั้งสองวิธียังไม่ได้กันการ copy และ paste นะครับในส่วนนี้ต้องหาทางแก้ไขเพิ่มเติมครับ

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="th" xml:lang="th">
<head>
<meta http-equiv="content-type" content="text/html; charset=tis-620" />
<title>javascript only digit textbox</title>
<script type="text/javascript">
//<![CDATA[
function replaceDigit(el){
el.value=el.value.replace(/\D/,'');
}
function acceptOnlyDigit(event,el){
var e=window.event?window.event:event;
var keyCode=e.keyCode?e.keyCode:e.which?e.which:e.charCode;
//0-9 (numpad,keyboard)
if ((keyCode>=96 && keyCode<=105)||(keyCode>=48 && keyCode<=57)){
return true;
}
//backspace,delete,left,right,home,end
if (',8,46,37,39,36,35,'.indexOf(','+keyCode+',')!=-1){
return true;
}
return false;
}
//]]>
</script>
</head>
<body>


<form method="post" action="?" id="box">
<br/>replace digit: <input type="text" name="onlydigit" value="" onkeyup="replaceDigit(this)" />
<br/>accept only digit: <input type="text" name="onlydigit2" value="" onkeydown="return acceptOnlyDigit(event,this)" />
</form>

</body>
</html>

วันพุธที่ 24 พฤศจิกายน พ.ศ. 2553

jquery graph

http://www.1stwebdesigner.com/resources/top-jquery-chart-libraries-interactive-charts/

วันอังคารที่ 23 พฤศจิกายน พ.ศ. 2553

import table sql server 2008 to sql server 2005

ใน database name ใน object explorer คลิ้กขวาเลือก task > generate scripts ..
ที่ชั้น scripts option คลิ้กปุ่ม advance ให้เลือก script mode และตั้ง server version เป็น sql server 2005
เลือกตำแหน่งไฟล์ที่จะบันทึก sql นำ script ที่ได้ไป run ใน server ที่ต้องการ import โครงสร้างตาราง
http://www.devx.com/dbzone/Article/40531

วันจันทร์ที่ 22 พฤศจิกายน พ.ศ. 2553

check duplicate value exists in array


<?php
$a = array(1,2,3,4,1,2,3,4);
$b = array(1,2,3,4,5,6,7);

echo '<br','>$a=';
if (count(array_unique($a)) == count($a)){
echo 'not duplicate';
} else {
echo 'duplicate';
}

echo '<br','>$b=';
if (count(array_unique($b)) == count($b)){
echo 'not duplicate';
} else {
echo 'duplicate';
}

?>

search intersection array


<?php
$a = array(5,6,7);
$b = array(1,2,3,4);
$c = array(1,2,3);

echo '<br','>$a,$b: ';
if (count(array_intersect($a,$b)) > 0){
echo 'duplicate ', var_export(array_intersect($a,$b),true);
} else {
echo 'not duplicate';
}

echo '<br','>$b,$c: ';
if (count(array_intersect($b,$c)) > 0){
echo 'duplicate ', var_export(array_intersect($b,$c),true);
} else {
echo 'not duplicate';
}

?>

วันอาทิตย์ที่ 21 พฤศจิกายน พ.ศ. 2553

Abstract factory pattern

abstract class เพื่อให้เรียกใช้งาน class ต่างๆ ที่มีรายชื่อคำสั่ง function เหมือนกันได้
โดยสามารถสลับไปใช้ class ที่มีรายชื่อคำสั่งเหมือนกันได้ผ่าน configuration

<?php

abstract class DbFactory
{
public static function getFactory($type){
$type .= 'Db';
return new $type;
}
public abstract function connect();
//public abstract function query();
//public abstract function fetch();
//public abstract function close();
}

class MysqlDb extends DbFactory
{
public function connect(){
echo '[Mysql Connect]';
}
}

class MssqlDb extends DbFactory
{
public function connect(){
echo '[Mssql Connect]';
}
}

$config = 'Mssql';
$db = DbFactory::getFactory($config);
$db->connect();
//...
?>

oop vs procedural

พูดถึงตัวแปร global ก่อนนะครับ
ถ้าใช้ตัวแปร global แสดงว่าทุก function สามารถเข้าถึงตัวแปร global ได้หมด
เวลาเกิด error ขึ้นในโปรแกรม โดยเฉพาะ error จาก logic เราจะไม่สามารถวิเคราะห์ได้ว่า
ภายใน function ไหนที่เป็นตัวเข้าไปแก้ไขทำใ้ห้ตัวแปร global หรือโปรแกรมของเราทำงานผิดพลาด
ดังนั้นภายในโปรแกรมควรจะจำกัดตัวแปร global ให้น้อยที่สุดครับ

ถึงจะมีข้อแนะนำว่าไม่ควรใช้ตัวแปร global หรือใช้น้อยที่สุด
แต่ว่าบางโปรแกรมที่จำเป็นต้องใช้ตัวแปรร่วมระหว่าง function ครับ
f1($a); ต้องการตัวแปร $x ไปประมวลผล
f2($a,$b); ต้องการตัวแปร $x ไปประมวลผล
f2($c,$d); ต้องการตัวแปร $x ไปประมวลผล
ซึ่งถ้าเราไม่ใช้ตัวแปร global เราก็ต้องเขียนแบบนี้ครับ
f1($a,$x);
f2($a,$b,$x);
f2($c,$d,$x);
แต่ว่าปัญหาเกิดครับ มีโค้ดซ้ำ ได้แก่ ,$x ซึ่งทำให้โปรแกรมเขียนและอ่านยากขึ้น
และเราไม่สามารถบอกได้ว่า function f1,f2,f3 มีความสัมพันธ์ต่อเนื่องกันหรือไม่
ซึ่งถ้าเขียนแบบ function ก็ทำได้ครับเช่น mysql_connect, mysql_query อันนี้เป็นการระบุความสัมพันธ์จาก คำหน้าหน้าชื่อ function

สำหรับการเขียนแบบ class นะครับ
เป็นการแก้โจทย์ปัญหาเกี่ยวกับตัวแปรร่วมที่ใช้ function ต่างๆ โดยไม่ต้องส่ง parameter ไปมา
การสร้างเป็น class นั้น ตัวแปรที่เป็นตัวแปรร่วมจะเรียกว่า member ของ class
ส่วน function จะเรียกว่าเป็น behavior ของ class (บรรทัดนี้และบรรทัดบนนี้ไม่รู้ถูกป่าวนะผมก็แค่ฟังๆผ่านๆจาก lecture ที่มหาวิทยาลัย)
ประโยชน์อย่างหนึ่งก็คือจัดกลุ่มของ function ที่สัมพันธ์กันโดยไม่ต้องมี คำนำหน้าเดียวกัน และไว้ที่เดียวกัน
ประโยชน์อีกอย่างคือ ตัวแปร member จะถูกแก้ไขโดย function และำคำสั่งภายใน class เท่านั้น
ทำให้พอจะระบุตำแหน่งของ error ได้ง่ายขึ้น เพราะในการเขียนแบบ oop ไม่จำเป็นต้องใช้ตัวแปร global มากมายอย่างในแบบ procedural
ประโยชน์อีกอย่างก็คือการจัดรูปแบบของ program จะมีลักษณะเป็นวัตถุกลุ่มก้อนมากขึ้น
การมองการเขียนโปรแกรมในรูปแบบ oop จะต่างจาก function ซึ่งเพียงแต่จะเน้นเพียงวัตถุประสงค์ให้โปรแกรมทำงานสำเร็จลุล่วง
แต่จะมองว่าเป็นการพยายามทำให้วัตถุต่างๆ ในโปรแกรมสื่อสารโต้ตอบกัน ใน oop เรียกว่าส่ง message การทำแบบนี้จะทำให้โปรแกรมที่ค่อนข้างซับซ้อน สามารถนำกลับมาใช้ใหม่ได้สะดวกครับ แต่การเขียนแบบอิสระก็จะทำให้เกิดความไม่เป็นระเบียบได้เหมือนกันจึงมีผู้ออกแบบ oop design pattern ที่ใช้กันบ่อยๆ ขึ้นมาครับ ซึ่งแม้ว่าการเขียนแบบ function ธรรมดาก็ทำได้เช่นเหมือนกัน แต่จะจัดระเบียบยุ่งยากกว่าแบบ class อยู่พอควรครับ

วันศุกร์ที่ 19 พฤศจิกายน พ.ศ. 2553

php game


<?php
session_start();
if (strlen('ก') > 1) header('content-type:text/html;charset=utf-8');
else header('content-type:text/html;charset=tis-620');

$a = @$_GET['a'];

$result = '-';
if ($a == 'start'){
srand();
$_SESSION['number'] = rand(1,999);
$_SESSION['time'] = 0;
}
if ($a == 'guess'){
$_SESSION['time']++;
$s = (int)$_SESSION['number'];
$ans = (int)$_GET['ans'];
if ($s == $ans){
$result = '<b>ถูกต้อง!!! คำตอบคือ'.$ans.' คุณทำสำเร็จภายใน '.$_SESSION['time'].' ครั้ง</b>';
}
if ($ans < $s){
$result = $ans.' น้อยกว่าหมายเลขปริศนา';
}
if ($ans > $s){
$result = $ans.' มากกว่าหมายเลขปริศนา';
}
}


?>

<h3>เกมส์ทายตัวเลขที่ซ่อนอยู่ (1-999)</h3>

<a href="?a=start">เริ่มเล่นใหม่</a><br/>

<?php if (isset($_SESSION['number'])):?>

<div>สถิติ: เล่นจำนวน <?php echo intval(@$_SESSION['time']);?> ครั้ง</div>

<div>ผลลัพธ์: <?php echo $result;?></div>

<form name="game" action="" method="get">
<input type="hidden" name="a" value="guess"/>

<input type="text" name="ans" value="" />
<input type="submit" name="submit" value="ตอบ"/>

</form>
<script>
window.onload = function(){ document.game.ans.focus(); };
</script>
<?php endif;?>

วันอังคารที่ 16 พฤศจิกายน พ.ศ. 2553

non new and method chaining

แทนที่จะ new object ของ class จากด้านนอก เราสามารถเขียนอีกแบบซึ่งจะสะดวกกว่าในหลายๆ กรณี
โดยการประกาศตัวแปร object ภายใน static method ของ class นั้นแทน
และใช้วิธี method chaining เพื่อลดการเรียกชื่อผ่านตัวแปร object จากด้านนอกและ
เรียกๆ method ที่คืนค่าของ class ไปเรื่อยๆ เพื่อประมวลผล (method chaining)
และสิ้นสุดด้วยการเรียก result method เพื่อนำค่าที่ได้ไปใช้งาน ดังนี้ครับ

PHP

<?php

class Cal
{
protected $n;
public function __construct($n){
$this->n = $n;
}
public function add($n){
$this->n += $n;
return $this;
}
public function mul($n){
$this->n *= $n;
return $this;
}
public function result(){
return $this->n;
}
public static function create($n){
return new Cal($n);
}
}

echo Cal::create(3)->add(5)->mul(100)->result();

?>



C#

// Cal.cs
public class Cal
{
protected int n;
public static Cal Create(int n)
{
return new Cal(n);
}
public Cal(int n)
{
this.n = n;
}
public Cal Add(int n){
this.n += n;
return this;
}
public Cal Mul(int n)
{
this.n *= n;
return this;
}
public int Result()
{
return this.n;
}
}
//Example
//Response.Write(Cal.Create(10).Add(1).Mul(3).Result());

วันจันทร์ที่ 15 พฤศจิกายน พ.ศ. 2553

array of condition


<?php

$result_no = 5;
$cond = array(
array(1=>'ชาย', '15', 'ก', 'a', 1),
array(1=>'ชาย', '15', 'ก', 'b', 2),
array(1=>'ชาย', '15', 'ก', 'c', 3),
array(1=>'ชาย', '15', 'ข', 'a', 4),
);
$choice = array(
1=>array('ชาย','หญิง',''), array('15','16',''), array('ก','ข',''), array('a','b'),
);

$ans = array(1=>'ชาย', '15', 'ก', 'c');
foreach($cond as $c){
$result = $c[$result_no]; unset($c[$result_no]);
if ($c == $ans) { echo $result; break; }
}

วันเสาร์ที่ 13 พฤศจิกายน พ.ศ. 2553

utf8 character hex


<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
$s = 'ทดสอบabc'; //must be utf8 string
$max = mb_strlen($s,'UTF-8');
for($i=0;$i<$max;$i++){
$c = mb_substr($s,$i,1,'UTF-8');
echo $c,' ',bin2hex($c),'<','br/>';
}
?>

วันพุธที่ 10 พฤศจิกายน พ.ศ. 2553

jquery menu

http://www.filamentgroup.com/examples/menus/flyout.php

inner new php function

function หา string ที่อยู่ระหว่างคำสองคำที่ระบุ

<?php

function inner($s,$f,$e){
$f = (string)$f; $e = (string)$e;
if (strlen($f)==0 || strlen($e)==0 || ($start = strpos($s, $f))===false) return "";
$s = substr($s, $start+strlen($f));
return substr($s, 0, strrpos($s, $e));
}

function innerutf8($s,$f,$e){ //safe สำหรับ utf8 มากกว่า
foreach(array('s','f','e') as $i) $$i = iconv('UTF-8','TIS-620',$s);
return iconv('TIS-620','UTF-8',inner($s,$f,$e));
}

$s = '[abc][abc] test0 [defg] test1 [/defg] test2 [/abc][/abc]';
echo '<hr/>'; var_dump(inner($s,'[defg]','[/defg]'));
echo '<hr/>'; var_dump(inner($s,'[abc]','[/abc]'));
echo '<hr/>'; var_dump(inner($s,'0','2'));
echo '<hr/>'; var_dump(inner($s,0,2));
echo '<hr/>'; var_dump(inner($s,'[abc]','[/abcd]')); //not found
echo '<hr/>'; var_dump(inner($s,'[abcd]','[/abc]')); //not found
echo '<hr/>'; var_dump(inner($s,'[abcd]','[/abcd]')); //not found
echo '<hr/>'; var_dump(inner($s,'','')); //not found

?>

การใช้งาน ajax กับภาษาไทย thai tis620

ajax tis620

supplied argument is not a valid MySQL result resource

error นี้เจอประจำครับ 99% เกิดจาก
1) คำสั่ง mysql syntax ผิด อย่างเช่น select * form table_name ซึ่งจริงๆ จะเป็น select * from table_name
2) เกิด error ขึ้นที่คำสั่ง mysql ยกตัวอย่างเช่นพิมพ์ชื่อ field ผิด พิมพ์ชื่อ table ผิด
3) หรือส่งตัวแปรผิดครับ อย่างเช่น mysql_num_rows($result) แต่เขียนเป็น mysql_num_rows($reslut); เป็นต้น

วิธีแก้ไขให้แทรกคำสั่ง mysql_error(); ไว้เพื่อตรวจสอบผลการทำงานของโปรแกรมเสมอครับ


$rs = mysql_query('select * from tb');
echo mysql_error();
$num = mysql_num_rows($rs);
?>

วันอังคารที่ 9 พฤศจิกายน พ.ศ. 2553

phpmsadmin

http://sourceforge.net/projects/phpmsadmin/

sort by index with asort


<?php
$ver = array();
$ver[1] = array(1,5,7,9,10) ;
$ver[2] = array(6,7,7,10,100) ;
$ver[3] = array(1,5,8,5,3) ;
$ver[4] = array(10,5,70,11,10) ;

foreach(range(0,4) as $index){
echo '<hr>index:'.$index.'<'.'br>';
$a = sort_by_index($ver,$index); //call function
foreach($a as $item){
foreach ($item as $n)
printf('%03d &nbsp;&nbsp; ',$n);
echo '<'.'br>';
}
}

function sort_by_index($ver,$sort_index){
$a = $b = array(); $i=1;
foreach($ver as $k=>$v){
$a[$k] = $v[$sort_index];
}
asort($a);
foreach($a as $k=>$v){
$b[$i++] = $ver[$k];
}
return $b;
}


?>


แบบที่เร็วกว่า

<?php
$ver = array();
$ver[1] = array(1,5,7,9,10) ;
$ver[2] = array(6,7,7,10,100) ;
$ver[3] = array(1,5,8,5,3) ;
$ver[4] = array(10,5,70,11,10) ;

foreach(range(0,4) as $index){
echo '<hr>index:'.$index.'<'.'br>';

$a = array(); foreach ($ver as $key => $row) $a[$key] = $row[$index];
array_multisort($a, SORT_ASC, $ver);

foreach($ver as $item){
foreach ($item as $n)
printf('%03d &nbsp;&nbsp; ',$n);
echo '<'.'br>';
}
}

?>

วันจันทร์ที่ 8 พฤศจิกายน พ.ศ. 2553

dream weaver keyboard shortcut ที่ช่วยให้ท่อง tag html และแทรก php ได้ง่ายขึ้น

ใน sourcecode mode

ให้แท่ง cursor ตำแหน่งพิมพ์ของ keyboard อยู่ใน tag ที่้ต้องการ collapse

เช่น <table><tr><td>test</td></tr></table>

กดปุ่ม keyboard ctrl + shift + j ช่วยให้หาตำแหน่งแทรกคำสั่ง <?php if ():?> <?php while():?> ฯลฯ และ tag ต่างๆ สะดวกขึ้นมากครับ

วันอาทิตย์ที่ 7 พฤศจิกายน พ.ศ. 2553

OOP Basics

OOP (Object-Oriented Programing)
การโปรแกรมเชิงวัตถุ มีคำอธิบายว่าคือการเขียนโปรแกรมให้มีคุณสมบัติเหมือนวัตถุ

ซึ่งเราสามารถจำแนกรูปแบบของการเขียนโปรแกรมเชิงวัตถุพื้นได้แก่
1) Encapsulation คุณสมบัติการห่อหุ้ม
ถ้าการเขียน class ใดๆ ที่มีการใช้ตัวแปร global หรือการเข้าแก้ไขตัวแปร member ของ object อื่นๆ ตัวแปรอื่นๆ นอกจากตัวแปร member ของมันเอง
ถือว่าเป็นการเขียนรูปแบบ OOP ที่ไม่ดี อาจจะเรียกได้ว่าไม่ใช่ OOP เลยก็ได้
คุณสมบัตินี้ถือเป็นคุณสมบัติที่สำคัญมาก เพราะถ้า object หนึ่งมีการ share ตัวแปร global กับ object อื่นๆ แล้วย่อมทำให้คุณสมบัติการจัดกลุ่มตัวแปร scope ของตัวแปร
สูญเสียไปอย่างสิ้นเชิง ถือว่าไม่ต่างจากการเขียนโปรแกรมแบบ Procedural ทั่วๆ ไป นอกจากนี้ยังอ่านและแก้ไขโปรแกรมได้ยากกว่าอีกด้วย

2) Inheritance คุณสมบัติการสืบทอด
โดยปกติแล้วเราไม่จำเป็นต้องสร้าง class และสร้าง class ที่สืบทอดจากอีก class นี้เพื่อให้ class มีคุณสมบัติเป็น OOP
แต่การสืบทอดหรือใน php ที่เราใช้ keyword extends นั้นมีประโยชน์ที่ทำให้เราสามารถใช้งานโค้ดได้อย่างมีระเบียบมากขึ้น
ตัวอย่างเช่น class A มีคุณสมบัติ Encapsulation ดีมาก สามารถนำไปใช้ได้หลายงาน
แต่ในการใช้งานจริงเราอาจจำเป็นต้องมี class ซึ่งใช้งานเฉพาะด้าน ถ้าหากเราเข้าไปแก้ไข class A จะทำให้ class A สูญเสียคุณสมบัติในการนำกลับมาใช้ใหม่ในทันที
เพื่อที่จะสามารถนำ class มาใช้งานเฉพาะด้านเราจึงสร้าง class B extends A เพื่อให้ class B ของเรามีคุณสมบัติเหมือน class A
และ class B จะถูกนำไปแก้ไขเพื่อใช้กับงานประยุกต์เฉพาะด้านโดยไม่ส่งผลกระทบกับ class ต้นฉบับ

3) Polymorphism การเรียกใช้แบบเดียวแต่ทำงานตอบสนองได้หลายแบบ
ตัวอย่างนี้ของคุณสมบัตินี้มักจะถูกยกตัวอย่างในรูปของ class Shape
โดยมี class Circle, Rectangle, Triangle เป็นคลาสลูก หรือ class ที่สืบทอดมาจาก class Shape
ซึ่งชี้ให้เห็นว่าการเรียกใช้งาน function cal นั้น ซึ่งมีการเรียก method cal ของคลาสลูกของ Shape สามารถทำงานปรับเปลี่ยนไปตามคุณสมบัติของคลาสลูก ได้

ประโยชน์ของการมี class ที่เป็น polymorphism ได้แก่ class หรือ function อื่นๆ ที่เรียก method cal นั้น
นั่นก็คือไม่เพียงแต่ class หรือ function จะยึดติดให้การทำงานใช้ได้เฉพาะกับ class Shape เท่านั้น แต่
class หรือ function เดิมนั้นยังสามารถนำกลับมาใช้ใหม่กับคลาสลูกของ Shape ได้ โดยมีการทำงานตามคุณสมบัติของ class ลูกโดยเฉพาะอีกด้วย
กล่าวคือเราสร้าง function เดียวแต่สามารถเปลี่ยนแปลงการทำงานโดยไม่ต้องแก้ที่ function หลัก แต่เพียงแต่แก้ที่ method ของคลาสลูกเท่านั้น
การเขียนในรูปแบบ OOP นี้จึงทำให้โค้ดหลักมีความเป็นระเบียบ โค้ดรูปแบบเดียวสามารถ
เปลี่ยนแปลงการทำงานโดยเพียงแค่เปลี่ยนชื่อคลาสลูกหรือเปลี่ยนตัวแปรเป็น object ของคลาสลูก


<?php
class Shape{
var $name='S';
function cal(){
return 0;
}
}
class Circle extends Shape{
var $ray;
var $name='C';
function Circle($ray){
$this->ray = $ray;
}
function cal(){
return (22/7)*pow($this->ray,2);
}
}
class Rectangle extends Shape{
var $edge;
var $name='R';
function Rectangle($edge){
$this->edge = $edge;
}
function cal(){
return pow($this->edge,2);
}
}
class Triangle extends Shape{
var $base;
var $height;
var $name='T';
function Triangle($base,$height){
$this->base = $base;
$this->height = $height;
}
function cal(){
return 0.5*$this->base*$this->height;
}
}
function cal(Shape $obj){
return $obj->cal();
}
$c = new Circle(10);
$r = new Rectangle(10);
$t = new Triangle(10,10);
foreach(array($c,$r,$t) as $shape){
echo '<br',' />',$shape->name,' = ',cal($shape);
}
?>

PHP OOP tutorial

object หรือ instance ของ class


$q1 และ $q2 เป็น object ของ class Quote
ซึ่ง class ก็เป็นเหมือนนามธรรม อย่างเช่น รถยนต์ซึ่งมีคุณสมบัติต่างๆ
ส่วน object ก็เหมือนรูปธรรมอย่างเช่น รถยนต์คันหนึ่งซึ่งมีคุณสมบัติรถยนต์
จะเห็นว่า object $q1 และ $q2 จะมีตัวแปร s เป็นคุณสมบัติเฉพาะตัว
เราอาจจะเปรียบเทียบ s เป็นลายของรถยนต์
ซึ่งเสมือนกับว่า $q1 เป็นรถยนต์คันหนึ่งมีลาย hello
ซึ่งเสมือนกับว่า $q2 เป็นรถยนต์คันหนึ่งมีลาย doraemon
และมี squote เป็นการทำงานของ class อาจจะเทียบเป็นการแสดงลายของรถยนต์
แม้ว่ามีการทำงานเหมือนกัน แต่การแสดงลายจะแสดงต่างกัน เพราะรถยนต์แต่ละคันมีลายต่างกันนั่นเอง


<?php

class Quote{
   protected $s = '';
   function __construct($s){
        $this->s = $s;
   }
   function squote(){
        return "'".$this->s."'";
   }
}
$q1 = new Quote('hello');
$q2 = new Quote('doraemon');
echo $q1->squote();
echo ', ';
echo $q2->squote();

?>


จะใช้ private protected หรือ public


โดยปกติไม่ควรตั้งสมาชิกตัวแปรให้เป็น public เพราะจะทำให้สามารถทำให้ object อื่นๆ สามารถเข้ามาแก้ไขเปลี่ยนแปลงสมาชิกตัวแปรของ object ได้โดยตรง
อย่างไรก็ตามถ้าสมาชิกตัวแปรเป็นตัวแปรที่ใช้เป็น configuration หรือการกำหนด setting การทำงานของ object ให้กำหนดเป็น public เพื่อความสะดวก
ทำให้ object ต่างๆ สามารถเข้ามาแก้ไข configuration ได้ทันที ไม่จำเป็นที่เราจะต้องสร้าง function เพื่อ set ค่าจำนวนมาก


<?php
class Car{
  protected $color = 'red';
  private $wheal = 4;
  public $tag = 'great car';
}

class Bmw extends Car{
  protected $color = 'blue';
  public $tag = 'bmw car';
}
?>

อย่างไรก็ตามการกำหนดค่าผ่านตัวแปร public จะมีข้อเสียก็คือการกำหนดชื่อตัวแปรผิดได้ เพราะ php จะไม่มีการแจ้งเตือนเมื่อมีการกำหนดค่าตัวแปรใหม่ซึ่งไม่มีใน class
เราสามารถทำให้เกิดการ warning เมื่อกำหนดค่าตัวแปรที่ไม่มีใน class ได้ โดยใช้  member overloading


<?php
class Car{
  protected $color = 'red';
  private $wheal = 4;
  public $tag = 'great car';
public function __set($name, $val){
echo "<br/>Error: Setting undefined member $name to $val";
}
}

$c = new Car();
$c->taggg = 'normal car';
?>


member accessibility ที่แนะนำให้ใช้เป็นประจำได้แก่ protected เพื่อช่วยให้ class ที่สืบทอด class ที่เราสร้างขึ้นสามารถใช้ตัวแปรได้เช่นกัน
อย่างไรก็ตามในบางครั้งอาจจะมีตัวแปรพิเศษซึ่งเราใช้เป็นตัวแปรชั่วคราวสำหรับเทคนิคการโปรแกรมบางอย่าง
ซึ่งไม่ต้องการให้ class ที่สืบทอด class นี้รู้จักตัวแปรหรือนำตัวแปรไปใช้ เราจะตั้งตัวแปรนี้เป็น private

ตัวแปรที่เป็น protected และ private ก็สามารถถูกเปลี่ยนแปลงค่าจากภายนอกได้เช่นกันโดยผ่านทาง method ที่เป็น public
ข้อดีของการใช้ public method ในการเข้าถึงตัวแปร private หรือ protected ก็คือสามารถกรองข้อมูลที่จะถูกกำหนดค่าของสมาชิกตัวแปร
ในตัวอย่างข้างนี้เราใช้ function __set (member overloading function) และ setColor (public function)
เพื่อทำการกรองข้อมูลที่ถูกกำหนดค่าเข้ามาให้เป็นตัวอักษรตัวเล็กเสมอ


<?php
class Car{
protected $color = 'red';
private $wheal = 4;
public $tag = 'great car';
public function __set($name, $val){
if ($name == 'color'){
$this->color = strtolower($val);
}
}
public function setColor($c){
$this->color = strtolower($c);
}
public function getColor(){
return $this->color;
}
}
$c = new Car();
$c->color = 'GREEN';
echo ',',$c->getColor();
$c->setColor('BLUE');
echo ',',$c->getColor();

?>

ควรจะเขียนเป็น static หรือ non static method

เรามักจะละเลยการเขียน static method หรือในบางเวลาเราจะเรียกว่า class method
เพราะว่าในหนังสือสอนการเขียน OOP ส่วนใหญ่จะไม่ได้ให้ความสำคัญกับ static method มากเท่ากัีบ method ของ object หรือ method ที่ต้องประกาศ object ก่อนถึงจะเรียกใช้งานได้

แต่ในความเป็นจริงแล้วคำสั่งส่วนใหญ่ควรจะเขียนเป็น static ในขั้นเริ่มต้นเสมอ
นอกจากวิเคราะห์แล้วว่า static method ไม่สามารถตอบโจทย์ในการแก้ทำจุดประสงค์ของ method เนื่องจากข้อจำกัดของความเป็น static function ไม่สามารถทำได้ ได้แก่
- จำเป็นต้องใช้ตัวแปรของ object เพื่อเก็บสถานะของการเรียกคำสั่ง
- จำเป็นต้องเรียกใช้ method ของ object เพื่อให้การทำงานเสร็จสมบูรณ์

static method นั้นดีกว่า object method
- เพราะว่า สามารถเรียกใช้งานได้โดยไม่ต้องประกาศ object ก่อน
- static method สามารถทำงานได้เร็วกว่า
- ไม่มีผลกระทบกับ ตัวแปรอื่นๆ ทำให้ debug ได้ง่ายและมั่นใจในความถูกต้องได้ง่ายกว่า

dropdown listbox เลือก จังหวัด อำเภอ และตำบล โดยใช้ jquery

ประกอบด้วย 3 ไฟล์
config.inc.php สำหรับเก็บต่อ database mysql
geo.php สำหรับเป็นหน้าแบบฟอร์ม
geo_combo.php เป็นไฟล์ที่ geo.php ใช้โหลด tag option ให้กับ combobox ด้วยวิธี ajax

*** จะต้องบันทึกไฟล์ geo_combo.php เป็น utf8
ส่วน geo.php ให้บันทึกเป็น tis620 (ansi)
ดาวน์โหลดไฟล์ database ได้ที่ http://www.thaicreate.com/free-web-script/thailand-province-database.html

*** ได้ทำการแก้ไขโค้ด onchange ของกล่องเลือกจังหวัด โดยเพิ่มคำสั่งลบรายการตำบลของอำเภอที่ได้เลือกในครั้งก่อนทิ้งด้วย
*** เพิ่มไฟล์ตัวอย่างที่ใช้กับ asp.net (c#) http://www.ziddu.com/download/7432325/jquery-multilevel-combobox-asp.net.zip.html
*** เพื่มไฟล์ตัวอย่างที่ใช้กับ php http://www.ziddu.com/download/7660090/jquery-multilevel-combobox-php.zip.html

1. config.inc.php

<?php
mysql_connect('localhost','root','12345');
mysql_select_db('geo');
mysql_query('SET NAMES UTF8');
?>

2. geo.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="th" xml:lang="th">
<head>
<meta http-equiv="content-type" content="text/html; charset=tis-620" />
<meta name="Author" content="num, dragon_html[at]hotmail.com" />
<title>combobox เลือก จังหวัด ตำบล อำเภอ โดยใช้ jquery</title>
<style type="text/css">
/*<![CDATA[*/
#error {color:red}
#notice {color:green}
/*]]>*/
</style>
<!-- โหลด jquery.js มาไว้ในเครื่อง จะทำให้เว็บโหลดเร็วขึ้น -->
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
//<![CDATA[

var province_id = <?php echo isset($_POST['province_id'])
?intval($_POST['province_id']):'0'; ?>;
var amphur_id = <?php echo isset($_POST['amphur_id'])
?intval($_POST['amphur_id']):'0'; ?>;
var district_id = <?php echo isset($_POST['district_id'])
?intval($_POST['district_id']):'0'; ?>;

function loadSelectBox(id,url,selected){
$.get(
url,{},function(data){
$(id).html(data);
if (selected!=0){
$(id+' option[value='+selected+']').attr('selected','selected');
}
}
);
}

$(function(){
loadSelectBox(
'#province_id',
'geo_combo.php?load=province',
province_id
);
loadSelectBox(
'#amphur_id',
'geo_combo.php?load=amphur&province_id='+province_id,
amphur_id
);
loadSelectBox(
'#district_id',
'geo_combo.php?load=district&amphur_id='+amphur_id,
district_id
);
$('#province_id').change(function(e){
var selected = e.target.value;
loadSelectBox(
'#amphur_id',
'geo_combo.php?load=amphur&province_id='+selected,
0
);
$('#district_id :not(option:first)').remove(); //add
});
$('#amphur_id').change(function(e){
var selected = e.target.value;
loadSelectBox(
'#district_id',
'geo_combo.php?load=district&amphur_id='+selected,
0
);
});
});
//]]>
</script>
</head>
<body>

<h1>combobox เลือกจังหวัด อำเภอ และตำบล โดยใช้ jquery</h1>
<?php
if (isset($_POST['title'])){
require_once 'config.inc.php';
$e = array();
$level = 'district';
// validation
if (empty($_POST['title'])){
$e[] = 'title ไม่ถูกต้อง';
}
if (empty($_POST['district_id'])){
if (empty($_POST['amphur_id'])){
if (empty($_POST['province_id'])){
$e[] = 'ไม่ได้ระบุจังหวัด';
}
$e[] = 'ไม่ได้ระบุอำเภอ';
$e[] = 'ไม่ได้ระบุตำบล';
} else {
$amphur_id = intval($_POST['amphur_id']);
$r = mysql_query("SELECT count(*) FROM `amphur` WHERE `AMPHUR_ID`=$amphur_id");
if (mysql_result($r,0)==0){
$e[] = 'อำเภอไม่ถูกต้อง';
} else {
$r = mysql_query("SELECT count(*) FROM `district` WHERE `AMPHUR_ID`=$amphur_id");
if (mysql_result($r,0)>0){
$e[] = 'ยังไม่ได้ระบุตำบล';
} else {
$level = 'amphur';
//ไม่จำเป็นต้องระบตำบลเพราะอำเภอไม่มีตำบล
}
}
}
} else {
$district_id = intval($_POST['district_id']);
$r = mysql_query("SELECT count(*) FROM `district` WHERE `DISTRICT_ID`=$district_id");
if (mysql_result($r,0)==0){
$e[] = 'ตำบลไม่ถูกต้อง';
}
}
if (count($e)>0){
echo '<div id="error">',implode('<br />',$e),'</div>';
} else {
echo "<div id=\"notice\">valid at level : $level</div>";
$district_value = 0;
if ($level == 'district'){
$r = mysql_query("SELECT * FROM `district` WHERE `DISTRICT_ID`=$district_id");
$district_value = $district_id;
$amphur_value = mysql_result($r,0,'AMPHUR_ID');
$province_value = mysql_result($r,0,'PROVINCE_ID');
} else {
$r = mysql_query("SELECT * FROM `amphur` WHERE `AMPHUR_ID`=$amphur_id");
$amphur_value = mysql_result($r,0,'AMPHUR_ID');
$province_value = mysql_result($r,0,'PROVINCE_ID');
}
//insert province_value,amphur_value,district_value and title into some table
}
}

?>
<form action="?" method="post">
news <input type="text" name="title" value="<?php textbox('title');?>" />
<br />จังหวัด <select id="province_id" name="province_id">
<option value="0">-- เลือกจังหวัด --</option>
</select>
<br />อำเภอ <select id="amphur_id" name="amphur_id">
<option value="0">-- เลือกอำเภอ --</option>
</select>
<br />ตำบล <select id="district_id" name="district_id">
<option value="0">-- เลือกตำบล --</option>
</select>
<br /> <input type="submit" value="submit" />
</form>

</body>
</html>
<?php
function textbox($name){
global $_POST;
echo isset($_POST[$name])?htmlspecialchars($_POST[$name]):'';
}
?>

3. geo_combo.php

<?php
header('Content-type:text/html;charset=UTF-8');
require_once 'config.inc.php';
if (!isset($_GET['load'])){
$_GET['load'] = 'province';
}
switch($_GET['load']){
case 'province':
$r = mysql_query("SELECT * FROM `province`") or report();
echo '<option value="0">-- เลือกจังหวัด --</option>';
while ($row = mysql_fetch_assoc($r)){
echo '<option value="',$row['PROVINCE_ID'],'">',
$row['PROVINCE_NAME'],
'</option>';
}
break;
case 'amphur':
$province_id = isset($_GET['province_id'])?intval($_GET['province_id']):0;
$r = mysql_query("SELECT * FROM `amphur` WHERE `PROVINCE_ID`=$province_id") or report();
echo '<option value="0">-- เลือกอำเภอ --</option>';
while ($row = mysql_fetch_assoc($r)){
echo '<option value="',$row['AMPHUR_ID'],'">',
$row['AMPHUR_NAME'],
'</option>';
}
break;
case 'district':
$amphur_id = isset($_GET['amphur_id'])?intval($_GET['amphur_id']):0;
$r = mysql_query("SELECT * FROM `district` WHERE `AMPHUR_ID`=$amphur_id") or report();
echo '<option value="0">-- เลือกตำบล --</option>';
while ($row = mysql_fetch_assoc($r)){
echo '<option value="',$row['DISTRICT_ID'],'">',
$row['DISTRICT_NAME'],
'</option>';
}
break;
}
function report(){
return die('<option>'.htmlspecialchars(mysql_error()).'</option>');
}
?>


โค้ดข้างบนนี้จะเป็นโค้ดสำหรับการเพิ่มข้อมูลนะครับ
หากต้องการแสดงผลข้อมูลเพื่อแก้ไขให้ทำการเปลี่ยนแปลงโค้ด

var province_id = <?php echo isset($_POST['province_id'])
    ?intval($_POST['province_id']):'0'; ?>;
var amphur_id = <?php echo isset($_POST['amphur_id'])
    ?intval($_POST['amphur_id']):'0'; ?>;
var district_id = <?php echo isset($_POST['district_id'])
    ?intval($_POST['district_id']):'0'; ?>;

เป็น

<?php
//ดึงข้อมูลจากตารางเพื่อมาแก้ไข
$id = (int)$_GET['id'];
$result = mysql_query("SELECT * FROM tb WHERE id='$id' ");
$row = mysql_fetch_assoc($result);
?>
//แล้วก็นำค่า id ต่างๆ ที่เกี่ยวข้องกับตำบลอำเภอและจังหวัดมาใช้เป็นค่า default ของ ตัวแปรใน javascript แทนค่า '0' ครับ
var province_id = <?php echo isset($_POST['province_id'])
    ?intval($_POST['province_id']):$row['province_id']; ?>;
var amphur_id = <?php echo isset($_POST['amphur_id'])
    ?intval($_POST['amphur_id']):$row['amphur_id']; ?>;
var district_id = <?php echo isset($_POST['district_id'])
    ?intval($_POST['district_id']):$row['district_id']; ?>;



เว็บที่เกี่ยวข้อง
jquery auto province

วันเสาร์ที่ 6 พฤศจิกายน พ.ศ. 2553

jquery row highlight


<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>d</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<style type="text/css">
.silver {color:silver;background-color:#990000;}
.green {color:#009999;}
.red {color:#FF0000;}
</style>
<script type="text/javascript">
$(function(){
$('.green').click(function(e){
e.preventDefault();
$(this).parents('.row').find('td').removeClass('silver');
});
$('.red').click(function(e){
e.preventDefault();
$(this).parents('.row').find('td').addClass('silver');
});
});

</script>

</head>
<body>


<table border="1" width="70%">
<?php foreach(range(1,5) as $i):?>
<tr class="row"><td><?php echo "TEST$i";?></td><td><a href="#" class="red">red</a></td><td><a href="#" class="green">green</a></td></tr>
<?php endforeach;?>
</table>


</body>
</html>

ตรวจสอบว่าชื่อผู้ใช้ว่ามีอยู่ในตารางหรือเปล่าโดยใช้ jquery ajax check username exists

วิธีใช้ให้เปลี่ยนค่าต่างๆ ใน mysql_connect('localhost','root','12345'); และ mysql_select_db('test'); แล้วทดลอง run ใน browser ดูครับ
และถ้าจะให้ดีให้เซฟไฟล์ http://code.jquery.com/jquery-latest.js ไปไว้ในเครื่องเว็บจะโหลดเร็วกว่าครับ

แบบกดปุ่ม


<?php
//กำหนดชื่อ host/username/password/databasename ก่อน
mysql_connect('localhost','root','12345') or die(mysql_error());
mysql_select_db('test') or die(mysql_error());

//create test data
$r = mysql_query("SHOW TABLES LIKE 'user_test'");
if (mysql_num_rows($r) == 0){
mysql_query(
'CREATE TABLE `user_test` ('.
'`id` int(10) unsigned NOT NULL AUTO_INCREMENT,'.
'`username` varchar(30) NOT NULL,'.
'PRIMARY KEY (`id`)'.
')'
) or die(mysql_error());
echo 'create table successfully.<br>';
mysql_query(
"insert into `user_test`(`id`,`username`) values ".
"(1,'abc'),".
"(2,'abc2'),".
"(3,'abc3'),".
"(4,'abc4');"
) or die(mysql_error());
echo 'insert data successfully.<br>';
}

//ajax process
if (isset($_GET['userExists'])){
$username = mysql_real_escape_string($_POST['username']);
$r = mysql_query("SELECT 1 FROM user_test WHERE username='$username'");
echo mysql_num_rows($r)?'yes':'no';
exit(0);
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
<title>check user exsits</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script>
//<![CDATA[
$(function(){

$('#check-user-exists-button').click(function(e){
var user = $.trim($('#regis input[name=username]').val());
if (user.length == 0){
alert('please enter the username');
} else {
$.ajax({
url: '?userExists',
type: 'POST',
dataType: 'html',
data: $('#regis').serialize(),
success: function(data){
if (data.indexOf('yes') != -1){
alert("user '" + user + "' already exists , \nplease choose other name");
} else {
alert("you can use name '" + user + "' ");
}
}
});
}
e.preventDefault();
});

});
//]]>
</script>
</head>

<body>

<div style="background-color:lemonchiffon;border:solid green 2px;margin-top:20px;padding:10px;">
ทดลองพิมพ์ชื่ออะไรก็ได้แล้วกดปุ่ม cher username<br />
(จะไม่สามารถใช้ชื่อ abc ได้เพราะมี username นี้ในตารางอยู่ก่อนแล้ว)
<form id="regis" action="?post" method="post">
<input type="text" name="username" value="" />
<input id="check-user-exists-button" type="button" value="check username" />
<br />
<input type="submit" value="submit" />
</form>
</div>

</body>
</html>



แบบอัตโนมัติเมื่อพิมพ์ชื่อ


<?php
//กำหนดชื่อ host/username/password/databasename ก่อน
mysql_connect('localhost','root','12345') or die(mysql_error());
mysql_select_db('test') or die(mysql_error());

//create test data
$r = mysql_query("SHOW TABLES LIKE 'user_test'");
if (mysql_num_rows($r) == 0){
mysql_query(
'CREATE TABLE `user_test` ('.
'`id` int(10) unsigned NOT NULL AUTO_INCREMENT,'.
'`username` varchar(30) NOT NULL,'.
'PRIMARY KEY (`id`)'.
')'
) or die(mysql_error());
echo 'create table successfully.<br>';
mysql_query(
"insert into `user_test`(`id`,`username`) values ".
"(1,'abc'),".
"(2,'abc2'),".
"(3,'abc3'),".
"(4,'abc4');"
) or die(mysql_error());
echo 'insert data successfully.<br>';
}

//ajax process
if (isset($_GET['userExists'])){
$username = mysql_real_escape_string($_POST['username']);
$r = mysql_query("SELECT 1 FROM user_test WHERE username='$username'");
echo mysql_num_rows($r)?'yes':'no';
exit(0);
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
<title>check user exsits</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
//<![CDATA[
$(function(){

$('#username-input').keyup(function(e){
var user = $.trim($(this).val());
if (user.length > 0){
$.ajax({
url: '?userExists',
type: 'POST',
dataType: 'html',
data: $(this).serialize(),
success: function(data){
if (data.indexOf('yes') != -1){
$('#username-status').html('not ok');
} else {
$('#username-status').html('ok');
}
}
});
}
e.preventDefault();
});

});
//]]>
</script>
</head>

<body>

<div style="background-color:lemonchiffon;border:solid green 2px;margin-top:20px;padding:10px;">
ทดลองพิมพ์ชื่ออะไรก็ได้ แต่จะไม่สามารถใช้ชื่อ abc ได้เพราะมี username นี้ในตารางอยู่ก่อนแล้ว
<form id="regis" action="?post" method="post">
<input type="text" id="username-input" name="username" value="" />
<span id="username-status"></span>
<br />
<input type="submit" value="submit" />
</form>
</div>

</body>
</html>

ajax

ajax : เอแจ็กซ์ (AJAX - Asynchronous JavaScript And XML)

เป็นเทคโนโลยีที่เกี่ยวของกับการ request file web หรือ webpage ต่างๆ โดยไม่ต้องเปลี่ยนหน้าใหม่
โดยใช้เทคโนโลยีที่มีอยู่เดิมคือ javascript และ xml โดยทำการ request แบบ asynchronous (ไม่ประสานจังหวะ) ทำให้ในขณะ request โดยใช้ิวิธี ajax ผู้ใช้ก็ยังใช้งานเว็บเพจได้ตามปกติราวกับว่าไม่มีการกำลัง request เว็บอีกหน้าหนึ่งอยู่เลย (เริ่มต้นมีการใช้ xml ใน ajax กันมาก จึงมีการตั้งชื่อตาม xml แต่ปัจจุบันมีผู้นิยมใช้ data รูปแบบอื่นแทน xml อย่างเช่น json , html format ฯลฯ)

ajax wiki

ในการใช้ ajax เรามักจะใช้ jquery ซึ่งเป็น function library หรืออาจจะเรียกว่า framework ก็ได้ ซึ่งมีผู้พัฒนาขึ้นมาจาก javascript ช่วยให้การใช้งาน ajax ทำได้ง่าย โดยปกติถ้าเขียน javascript เรียก ajax ด้วยตนเองจะต้องเขียนถึง 10-20 บรรทัด แต่ถ้าใช้ jquery สามารถเีขียนให้จบได้ใน 1-10 บรรทัดเท่านั้น

วันศุกร์ที่ 5 พฤศจิกายน พ.ศ. 2553

php weighted random choice

fast wegithed random choice in php

jquey threesixty panorama 360

panorama
reel

send json data with jquery

Download Sourcecode


<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST'){
$json = json_decode($_GET['json_data']);
$json2 = json_decode($_GET['json_data2']);
var_dump($json);
echo '<hr/>';
var_dump($json2);
echo '<hr/>';
foreach($json as $item)
echo $item.' ';
echo '<hr/>';
foreach($json2 as $row)
echo $row->name.' '.$row->tel.'<br/>';
exit;
}
?>

<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>send json data with jquery json plugin</title>
<script type="text/javascript" src="jquery.js"></script>
<!-- jquery plugin : http://code.google.com/p/jquery-json/ -->
<script type="text/javascript" src="jquery.json-2.2.js"></script>
<script type="text/javascript">
$(function(){

$('#submit-btn').click(function(e){
e.preventDefault();
var mydata = ['abc','defg','xyz'];
var mydata2 = [{name:'num',tel:'001'},{name:'nobita',tel:'002'},{name:'doraemon',tel:'003'}];
var json = $.toJSON(mydata);
var json2 = $.toJSON(mydata2);
$.ajax({
url:'?'+$.param({json_data:json, json_data2:json2}),
type:'POST',
dataType:'html',
success:function(e){
alert(e);
$('#result').html(e);
}
});
});
});

</script>

</head>
<body>


<button id="submit-btn">send data</button><br/>
Result: <div id="result"></div>

</body>
</html>


jquery plugin
http://code.google.com/p/jquery-json/

tinymce template_list

// This list may be created by a server logic page PHP/ASP/ASPX/JSP in some backend system.
// There templates will be displayed as a dropdown in all media dialog if the "template_external_list_url"
// option is defined in TinyMCE init.

var tinyMCETemplateList = [
// Name, URL, Description
["Simple snippet", "templates/snippet1.htm", "Simple HTML snippet."],
["Layout", "templates/layout1.htm", "HTML Layout."]
];

วันพฤหัสบดีที่ 4 พฤศจิกายน พ.ศ. 2553

edit php config file

Download: save-config

save-confg.php

<?php
require_once 'config.php';
$h = 'htmlspecialchars';
$n = "\n";
if ($_SERVER['REQUEST_METHOD']=='POST'){
$s = '<?php'.$n.'$conf = array();'.$n;
foreach($conf as $k=>$v)
$s .= '$conf['.var_export($k,true).'] = '.var_export($_POST[$k],true).';'.$n;
file_put_contents('config.php',$s.$n.'?>');
header('location:save-config.php');
exit;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-874" />
<title>save config</title>
</head>

<body>


<form method="post" action="?save">
dbname:<input type="text" name="dbname" value="<?php echo $h($conf['dbname']);?>"/><br/>
username:<input type="text" name="username" value="<?php echo $h($conf['username']);?>"/><br/>
password:<input type="text" name="password" value="<?php echo $h($conf['password']);?>"/><br/>
site name:<input type="text" name="site_name" value="<?php echo $h($conf['site_name']);?>"/><br/>
<input type="submit" value="save"/>
</form>

</body>
</html>


confg.php อย่าลืมตั้งไฟล์นี้ให้ write ได้ด้วยนะ ทั้ง apache / iis / appserv ฯลฯ ตั้องตั้ง permission ให้เขียนไฟล์ได้ก่อนครับ

<?php
$conf = array();
$conf['dbname'] = 'test';
$conf['username'] = 'root';
$conf['password'] = '1234';
$conf['site_name'] = 'dorameon';

?>

reverse engineering php variable expression

<?php ob_start();?>
<script type="text/javascript">var szu=encodeURIComponent(location.href); var szt=encodeURIComponent(document.title).replace(/\'/g,'`'); var szjsh=(window.location.protocol == 'https:'?'https://ssl.seitzeichen.de/':'http://w4.seitzeichen.de/'); document.write(unescape("%3Cscript src='" + szjsh + "w/a5/90/widget_a590cf3bb1647729447d6d105499cdda.js' type='text/javascript'%3E%3C/script%3E"));</script>
<?php $s = ob_get_clean();?>
<?php
echo htmlspecialchars($s);
#echo $s;
echo htmlspecialchars(var_export($s,1)); //reverse engineering variable expression show
#echo var_export($s,1); //reverse engineering variable expression
?>

Best Practices for Speeding Up Your Web Site

speeding up your web site
MySQL/MySQL-Optimization-part-1/
10-tips-for-optimizing-mysql-queries-that-dont-suck/

jquery api after









code

<script src='http://code.jquery.com/jquery-latest.js' type='text/javascript'></script>
<script type="text/javascript">
/*<![CDATA[*/
$(function(){
$('.cb01 :checkbox').each(function(){
$(this).after( $(this).attr('id') );
});
});
/*]]>*/
</script>

<div class="cb01">
<input type="checkbox" name="c1" id="c1" value="v1"/>
<input type="checkbox" name="c2" id="c2" value="v2"/>
<input type="checkbox" name="c3" id="c3" value="v3"/>
</div>

Jiddu Krishnamurti The Core of the Teachings

The following statement was written by Krishnamurti himself on October 21, 1980 in which he summarizes the teachings. It may be copied and used provided this is done in its entirety. No editing or change of any kind is permitted. No extracts may be used.

"The core of Krishnamurti's teaching is contained in the statement he made in 1929 when he said: 'Truth is a pathless land'. Man cannot come to it through any organization, through any creed, through any dogma, priest or ritual, not through any philosophic knowledge or psychological technique. He has to find it through the mirror of relationship, through the understanding of the contents of his own mind, through observation and not through intellectual analysis or introspective dissection. Man has built in himself images as a fence of security - religious, political, personal. These manifest as symbols, ideas, beliefs. The burden of these images dominates man's thinking, his relationships and his daily life. These images are the causes of our problems for they divide man from man. His perception of life is shaped by the concepts already established in his mind.

The content of his consciousness is his entire existence. This content is common to all humanity. The individuality is the name, the form and superficial culture he acquires from tradition and environment. The uniqueness of man does not lie in the superficial but in complete freedom from the content of his consciousness, which is common to all mankind. So he is not an individual.

Freedom is not a reaction; freedom is not a choice. It is man's pretence that because he has choice he is free. Freedom is pure observation without direction, without fear of punishment and reward. Freedom is without motive; freedom is not at the end of the evolution of man but lies in the first step of his existence. In observation one begins to discover the lack of freedom. Freedom is found in the choiceless awareness of our daily existence and activity. Thought is time. Thought is born of experience and knowledge which are inseparable from time and the past. Time is the psychological enemy of man. Our action is based on knowledge and therefore time, so man is always a slave to the past. Thought is ever-limited and so we live in constant conflict and struggle. There is no psychological evolution.

When man becomes aware of the movement of his own thoughts he will see the division between the thinker and thought, the observer and the observed, the experiencer and the experience. He will discover that this division is an illusion. Then only is there pure observation which is insight without any shadow of the past or of time. This timeless insight brings about a deep radical mutation in the mind.

Total negation is the essence of the positive. When there is negation of all those things that thought has brought about psychologically, only then is there love, which is compassion and intelligence."

© 1993 The Krishnamurti Foundation Trust Ltd,
Brockwood Park, Bramdean, Hampshire, England.

http://www.deeshan.com/krishnamurti.htm
http://www.katinkahesselink.net/kr/k_exper.htm

cool quotes

In your life, There's no such a thing as you can do it or you can't!! but, it's a matter of 'doing it or not doing it!!

the talent of hard work

the first step to the nex level, i think is courageously stepping into the unknown

facebook game ที่น่าสนใจ

http://apps.facebook.com/ohhwords/

วันพุธที่ 3 พฤศจิกายน พ.ศ. 2553

วันอังคารที่ 2 พฤศจิกายน พ.ศ. 2553

ใช้ ajax แบบ synchronize ในการเรียกใช้ php function

ดาวน์โหลดไฟล์ตัวอย่างได้ที่
http://www.ziddu.com/download/6732230/call-php-function-by-ajax.zip.html

ถ้าตั้ง php config ให้ magic_quotes_gpc เป็น on จะต้องแก้ไขโค้ดด้านล่างดังนี้ครับ

    if (in_array($_GET['phpfunction'],$allow,true)){
        //เรียกใช้งาน function
        if ( get_magic_quotes_gpc() ) { //เพิ่ม
            $_GET['param'] = stripslashes($_GET['param']); //เพิ่ม
        } //เพิ่ม
        $param = json_decode($_GET['param']);        
        $value = call_user_func_array($_GET['phpfunction'],$param);
    } else {
        $value = 'error';
    }




<?php

if (isset($_GET['phpfunction'])){
//ระบุ function ที่อนุญาติให้เรียกใช้งานได้
$allow = array('plus','minus','mul','div');
//ประกาศ function
function plus($n,$m){return $n+$m;}
function minus($n,$m){return $n-$m;}
function mul($n,$m){return $n*$m;}
function div($n,$m){return $n/$m;}
//ตรวจสอบว่า function ที่เรียกเป็น function ที่ได้รับอนุญาติให้ใช้หรือไม่
if (in_array($_GET['phpfunction'],$allow,true)){
//เรียกใช้งาน function
$param = json_decode($_GET['param']);
$value = call_user_func_array($_GET['phpfunction'],$param);
} else {
$value = 'error';
}
//ส่งค่า json string กลับไปให้ฝั่ง client
die( json_encode(compact('value')) );
}
?>

<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=TIS-620" />
<title>JSONP</title>
<script type="text/javascript" src="jquery.js"></script>
<!-- jquery plugin : http://code.google.com/p/jquery-json/ -->
<script type="text/javascript" src="jquery.json-2.2.js"></script>
<script type="text/javascript">

function remoteFunction(name,parameter){
var value;
var param = $.toJSON(parameter);
//request แบบ synchronize
$.ajax({
url:'?phpfunction='+name+'&'+$.param({param:param}),
type:'GET',
async:false,
dataType:'json',
success:function(e){
value = e.value;
}
});
return value;
}

$(function(){
$("#cal-button").click(function(e){
//นำค่าจาก dropdownlistbox มาไว้ในตัวแปร f1
var f1 = $('#function-name').val();
//นำค่าจาก textbox มาเก็บไว้ในตัวแปร d1, d2
var d1 = $('#d1').val();
var d2 = $('#d2').val();
//เรียก remote function f1 และส่งตัวแปร d1 และ d2 ไป
var d3 = remoteFunction(f1,[d1,d2]);
$('#d3').val(d3);
e.preventDefault();
});
});

</script>

</head>
<body>

<br />function:<select id="function-name">
<option value="plus" selected="selected">บวก</option>
<option value="minus">ลบ</option>
<option value="mul">คูณ</option>
<option value="div">หาร</option>
</select>
<br />d1:<input type="text" id="d1" value="1" />
<br />d2:<input type="text" id="d2" value="2" />
<br />d3:<input type="text" id="d3" value="?" />
<input type="button" id="cal-button" value="cal" />

</body>
</html>

http://code.google.com/p/jquery-json/

mysql complex query

1. GROUP BY Query Pagination



SELECT * FROM box;

id    box1    box2
4    1    abc
3    1    def
5    2    ghi
6    3    jkl
7    2    mno

SELECT COUNT(*) FROM box GROUP BY( box1 );
box1    COUNT(*)
1    2
2    2
3    1
จะเห็นได้ว่า count(*) จะเป็นค่าที่เก็บจำนวนของ box1 ที่ซ้ำกัน อย่างเช่น box=1 มี 2 แถว จึงมีค่า count(*)=2

โดยปกติเมื่อเราจะทำการแบ่งหน้าใน PHP (Pagination) เราต้องการจำนวนแถวของผลลัพธ์ทั้งหมด
จะเห็นได้ว่าเมื่อใช้คำสั่ง GROUP BY เราจะไม่สามารถใช้ query count(*) อย่างข้างบนในการหาจำนวนแถวผลลัพธ์ทั้งหมด
เนื่องจาก query count(*) จะถูกนำไปใช้เป็นจำนวนที่ซ้ำกันของข้อมูลที่ถูก GROUP BY ไว้

ซึ่งปัญหานี้จะสามารถแก้ไขได้ง่ายๆ ด้วยการใช้ sub query อย่างข้างล่างนี้ครับ

SELECT COUNT(*) FROM (SELECT COUNT(*) FROM box GROUP BY box1) AS t1;
COUNT(*)
3

2. FIND THE STUDENTS GOT MAXIMUM SCORE IN EACH SUBJECT


ปัญหานี้ค่อนข้างซับซ้อนกว่าที่คิดครับ

ถ้าต้องการจะทดสอบ query สามารถเอา sql statement นี้ไปสร้างตารางเพื่อใช้ในการทดสอบได้ครับ

CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sname` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

insert into `students`(`id`,`sname`) values (1,'A'),(2,'B'),(3,'C'),(4,'D');

CREATE TABLE `subjects` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sjname` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

insert into `subjects`(`id`,`sjname`) values (1,'CT211'),(2,'CT212'),(3,'CT316'),(4,'CT317'),(5,'CT488');

CREATE TABLE `tests` (
`student_id` int(11) NOT NULL,
`subject_id` int(11) NOT NULL,
`score` int(11) NOT NULL,
PRIMARY KEY (`student_id`,`subject_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

insert into `tests`(`student_id`,`subject_id`,`score`) values (1,1,80),(1,2,70),(1,3,25),(1,4,61),(1,5,99),(2,1,50),(2,2,72),(2,3,85),(2,4,11),(3,1,83),(3,2,39),(3,3,95),(3,4,96),(3,5,99),(4,1,98),(4,2,21),(4,3,60);


มาดู query ที่ใช้ในการหาคนที่ได้คะแนนสูงสุดในแต่ละวิชากันครับ

SELECT sname,sjname,score
FROM students,subjects,tests
WHERE tests.student_id = students.id AND
tests.subject_id = subjects.id AND
CONCAT(tests.student_id,'-',tests.subject_id) IN
(
SELECT CONCAT(student_id,'-',subject_id) FROM
(
SELECT tests.student_id,tests.subject_id FROM tests ORDER BY tests.subject_id, tests.score DESC
)
AS temp_table
GROUP BY subject_id
);

ซึ่งจะได้ผลลัพธ์
sname    sjname    score
A    CT488    99
B    CT212    72
C    CT316    95
C    CT317    96
D    CT211    98

query ดังกล่าวดูเผินๆ ก็ทำงานปกติดีแต่ มีข้อเสียคือทำงานช้าครับ เนื่องจากใช้ฟังค์ชั่น concat()
ตอนนั้นผมยังไม่รู้จักการใช้ column หลายๆ column มาเปรียบเทียบพร้อมๆ กัน ซึ่งจะทำให้ query
SELECT * FROM tb1 WHERE c1=1 AND c2=2;
ทำให้เขียนได้สั้นๆ ดังนี้ครับ
SELECT * FROM tb1 WHERE (c1,c2)=(1,2);

จากความรู้นี้ทำให้สามารถปรับปรุง query ก่อนให้เร็วขึ้นและเขียนสั้นลงอีกด้วยครับ

SELECT sname,sjname,score
FROM students,subjects,tests
WHERE tests.student_id = students.id AND
tests.subject_id = subjects.id AND
(tests.student_id,tests.subject_id) IN
(
SELECT student_id,subject_id FROM
(
SELECT tests.student_id,tests.subject_id FROM tests ORDER BY tests.subject_id, tests.score DESC
)
AS temp_table
GROUP BY subject_id
);

ในตอนหลังผมพบว่าสามารถเขียน query ให้ได้ง่ายๆ ขึ้นด้วยคำสั่งนี้

SELECT sname,sjname,score
FROM students,subjects,tests
WHERE tests.student_id = students.id AND
tests.subject_id = subjects.id
AND tests.score = (SELECT MAX(score) FROM tests AS t1 WHERE t1.subject_id=tests.subject_id);


ปัญหาใหม่ก็คือในบางครั้งจะมีคนที่ได้คะแนนสูงสุดเหมือนกัน แต่ query ข้างบนนี้จะแสดงแยกแถวกันซึ่งไม่สะดวกในการใช้งาน
ซึ่งเราสามารถแก้ไขโดยใช้คำสั่ง GROUP BY ร่วมกับ GROUP_CONCAT

SELECT GROUP_CONCAT(sname) AS snames,sjname,score
FROM students,subjects,tests
WHERE tests.student_id = students.id AND
tests.subject_id = subjects.id
AND tests.score = (SELECT MAX(score) FROM tests AS t1 WHERE t1.subject_id=tests.subject_id)
GROUP BY sjname;

ซึ่งจะได้ผลลัพธ์เป็นไปตามความต้องการดังนี้ครับ
snames    sjname    score
D    CT211    98
B    CT212    72
C    CT316    95
C    CT317    96
C,A    CT488    99 /* C และ A ได้คะแนนสูงสุดเท่ากัน */


3. FIND RANDOM NAME OF EACH GROUP ONLY ONCE


s    name
1    ddd
2    eee
3    fff
1    mmm
2    ggg
3    zzz
1    hhh
2    bbb
3    ttt

SELECT CONCAT('set',s) AS `set`,`name` FROM (SELECT * FROM t ORDER BY RAND()) AS t1 GROUP BY s;

set    name
set1    hhh
set2    eee
set3    fff



4. JOIN TABLE


แบบที่ 1) SELECT b1.id FROM b1,b2 WHERE b1.id = b2.b1_id;
แบบที่ 2) SELECT b1.id FROM b1 INNER JOIN  b2 ON b1.id = b2.b1_id;
ทั้ง 2 แบบให้ผลลัพธ์เหมือนกัน แต่แบบที่ 2 จะเร็วกกว่าครับ


5. DELETE DUPLICATE RECORD



DROP TABLE IF EXISTS id_temp;
CREATE TEMPORARY TABLE id_temp (
`id` SMALLINT(5) UNSIGNED NOT NULL
) SELECT `id` FROM b3 GROUP BY `code` HAVING COUNT(*)>1;

DELETE FROM b3 WHERE b3.`id` IN(SELECT id_temp.`id` FROM id_temp);

6. GET MAX ORDER_ID OF CURRENT YEAR



$r = mysql_query("
SELECT
MAX(CAST(MID(pr_order,5,3) AS UNSIGNED)) AS now_id,
RIGHT(pr_order,4) AS year_id
FROM pr_description
GROUP BY year_id
HAVING year_id = YEAR(CURRENT_DATE)+543
");
if (mysql_num_rows($r)){
$now_id = mysql_result($r,0,'now_id');
} else {
$now_id = 1;
}
$now_id = sprintf("%02d",$now_id);
echo $now_id;


SELECT
MAX(CAST(MID(pr_order,5,3) AS UNSIGNED)) AS now_id,
RIGHT(pr_order,4) AS year_id
FROM
(
SELECT 'CPMK001/2552' AS pr_order
UNION
SELECT 'CPMK003/2552' AS pr_order
UNION
SELECT 'CPMK004/2551' AS pr_order
UNION
SELECT 'CPMK002/2552' AS pr_order
) AS t1
GROUP BY year_id
HAVING year_id = YEAR(CURRENT_DATE)+543

7. TOP 5 BEST SELLER



SELECT products.id,products.name,SUM(order_details.qty) AS sum_qty
FROM orders
INNER JOIN order_details ON orders.id=order_details.order_id
INNER JOIN products ON products.id=order_details.product_id
WHERE YEAR(orders.create_at)='2009'
GROUP BY products.id
ORDER BY sum_qty DESC
LIMIT 5;


7. FIXING THAI CHARACTER SET SORT


character set utf8 จะมีปัญหากับการเรียงลำดับภาษาไทย
เช่น กางเกง และ เกม จะเรียงลำดับห่างกัน เพราะ collation ของ utf8 จะนับเอาตัวอักษรตัวแรกเป็นตัวเริ่มต้นเรียงลำดับ
แต่สามารถแก้ไขโดยการ convert character set ให้เป็น tis620 ก่อน
SELECT * FROM tb ORDER BY CONVERT (NAME USING tis620);

8. Find Related Post




SELECT COUNT(posts_tags.tag_id) ct FROM posts_tags
WHERE posts_tags.tag_id IN
(
SELECT posts_tags.tag_id
FROM posts_tags
WHERE posts_tags.post_id='10'
)
GROUP BY post_id
ORDER BY ct DESC LIMIT 10
;


9. SELECT between date or datetime



SELECT CAST(created AS DATETIME)
FROM posts
WHERE created BETWEEN CAST('2009-02-01' AS DATETIME) AND CAST('2009-06-01' AS DATETIME);


10. SELECT ORDER BY ID ASC LIMIT 5 OF SELECT ORDER BY ID DESC



$rs = mysql_query('SET @lim:=0;');
$rs = mysql_query('SELECT * FROM (SELECT id FROM posts ORDER BY id DESC) AS t1 WHERE (@lim:=(@lim+1)) < 5 ORDER BY id ASC');
echo mysql_error();
while($r = mysql_fetch_assoc($rs)){
echo $r['id'],'<br','>';
}


11. SEARCH MULTI TABLE



$sql = "
select column_1 as c1 from tb1 where column_1 like '%notebook%'
union
select column_2 as c1 from tb2 where column_2 like '%notebook%'
union
select column_3 as c1 from tb3 where column_3 like '%notebook%'
";
$rs = mysql_query($sql);
while($r = mysql_fetch_assoc($rs)){
echo '<br','>',$r['c1'];
}

การใช้ linq to sql

sql-linq-part-i.aspx
sql-linq-part-ii.aspx
sql-linq-part-iii.aspx

using-linq-to-sql-part-1.aspx

แปลง psd เป็น html

สอนวิธีแปลงไฟล์ photoshop ให้เป็น html ครับ
http://www.tutoriallounge.com/2010/03/25-ultimate-useful-psd-to-html-tutorials/

webdesign1
webdesign2

create button

photoshop tutorial

yii php framework

ข้อดีของ yii

  1. orm ดีมาก สนับสนุนการ join ที่ซับซ้อนโดยไม่ต้องเขียน query
  2. การประมวลผลเร็วมากกว่า php framework เกือบทุกเจ้า
  3. มีระบบ gii ช่วยสร้าง class และ view ผ่านทางหน้าเว็บไซท์
  4. เอกสารที่ดี อ่านเข้าใจได้ง่าย
  5. มีเว็บบอร์ดที่ตอบคำถามไวมากโดยผู้ผลิต framework และผู้เชี่ยวชาญการใช้งาน


เฟรมเวิร์คที่ผมเคยใช้ cakephp, codeigniter, zoop, zend, yii ผมว่า yii ออกแบบโครงสร้าง mvc มาดีที่สุด (เฉพาะ mvc แต่ component ของ framework อื่นบางตัวออกแบบดีกว่า yii)

http://www.yiiframework.com/
ทำความรู้จักกับ yii

ประโยชน์ของ framework
ประโยชน์หลักของ framework เลยก็คือจะมีการวางแบบแผนและระบบต่างๆ ที่ช่วยให้เขียนโค้ดเป็นระเบียบขึ้น การใช้ framework มีประโยชน์อย่างมากถ้าเขียนโปรแกรมเดียวกันพร้อมกันหลายๆ คน เพราะโครงสร้างโค้ดและ flow ของโปรแกรมจะเป็นไปในแนวเดียวกันหมด ทำให้สามารถเขียนและแก้ไขโปรแกรมที่คนอื่นเขียนได้ง่ายขึ้นมากๆๆๆๆๆ ครับ

ประโยชน์ทางอ้อมก็คือ เพราะว่า framework ถูกเขียนโดยผู้ที่เขียนเว็บที่มีประสบการณ์มากและเก่งมากๆ การได้เรียนรู้จักคำสั่งภายใน framework จะทำให้ได้แนวคิดที่จะช่วยในการเขียนเว็บในหลายๆ อย่าง อย่างเช่น การเขียนคำสั่งที่จะนำกลับมาใช้ใหม่ได้ ช่วยให้ได้รู้จักการวางระเบียบ function และ class ซึ่งจะมีประโยชน์มากต่อการเขียนเว็บอย่างมากครับ

framework คือโครงสร้างและคำสั่งในการพัฒนาระบบซึ่งผู้มีประสบการณ์ได้วางระบบไว้ให้ ซึ่งจะมีประโยชน์ในการพัฒนาระบบในระยะยาวเพราะว่าโค้ดมีความเป็นระเบียบอยู่ แล้ว ทำให้ไม่ต้องกังวลว่าในอนาคต โครงสร้างที่เราวางไว้อาจจะไม่สามารถตอบสนองกับระบบที่จะพัฒนาเพิ่มเติมเข้า ไปในภายหลัง หรือเมื่อพบจุดที่เป็นปัญหาต้องตามไปแก้โค้ดในทุกๆ หน้า ซึ่งเป็นเรื่องที่น่ากลัวมากครับ.. แต่ถ้าใช้ framework ที่ออกแบบไว้ดี จะสามารถแก้ปัญหาได้โดยการแก้เพียงไม่กี่จุด

แต่ framework ก็มีข้อเสียเหมือนกันอย่างเช่น cakephp มีข้อเสียอย่างหนึ่งก็คือ
ถ้าเราเขียน class เป็น component, behavior, helper นั้น จะนำกลับมาใช้ใหม่ได้ก็กับเฉพาะโปรแกรม ที่สร้างด้วย cakephp เท่านั้น ไม่สามารถนำไปใช้ใน application ทั่วๆ ไปได้

สรุปได้ว่าถ้าเราวางระบบในการพัฒนาซึ่งมีการจัดระเบียบไว้ดีแล้ว และนำไปใช้ในการสร้างโปรแกรมต่างๆ ได้อย่างไม่มีปัญหา ก็ไม่จำเป็นต้องใช้ framework ครับ (แต่การจัดระเบียบเว็บก็เหมือนเราสร้าง framework ของตัวเองขึ้นมาใช้เหมือนกันอะ แหะๆ)

สรุปแล้ว ในที่สุดเราก็ต้องใช้ framework ไม่ว่าจะเป็นของคนอื่นหรือของตัวเองครับ ..แป่ววว

การขอคือภาษีหัก ณ ที่จ่าย request return tax

  1. ภาษีหัก ณ ที่จ่าย คือ ภาษีจากเงินได้ ที่ต้องถูกหักไว้เพื่อทางบริษัทจะนำส่งสรรพากรในทุกเดือน
  2. การขอคืนทำได้คือ คุณต้องถือใบหัก ณ ที่จ่ายไว้จนกว่าจะครบปีภาษี แล้วเมื่อสิ้นปีภาษีคุณก็นำเอาใบหัก ณ ที่จ่ายทั้งหลายที่คุณถือไว้ทั้งหลาย(อาจมีหลายใบ)มาคำนวณภาษีทั้งปีอีกที หนึ่งว่าภาษีทั้งปีเท่าไหร่ แล้วเปรียบเทียบกับที่ถูกหักไว้อันใหนเยอะกว่า ถ้ามีภาษีทั้งปีมากกว่าถูกหักไว้ก็ต้องเสียเพิ่ม ถ้าภาษีทั้งปีน้อยกว่า(ถูกหักไว้เยอะกว่า)ก็ขอคืนภาษี ต้องกรอกแบบฟอร์มการคำนวณภาษีแบบ ภงด 91 สำหรับผู้มีเงินได้แบบเงินเดือนอย่างเดียว หรือกรอกแบบ ภงด 90 สำหรับผู้มีเงินได้แบบอื่น ๆ ด้วย เช่น บริการ+เงินเดือน+ขายที่ดิน ฯลฯ
  3. จะขอคืนได้เมื่อไหร่ ก็คือดูว่าในใบหักภาษีนั้นเป็นของปีใหน ถ้าปี 49 ก็ภายในวันที่ 31มีนาคม 2550 ถ้าปี 50 ก็ภายในวันที่ 31 มีนาคม 2551


เครดิตคุณจิน ที่ตอบที่เว็บ mthai
http://webboard.mthai.com/7/2007-04-28/318414.html

วันจันทร์ที่ 1 พฤศจิกายน พ.ศ. 2553

บทความจาก devzone.zend.com ที่น่าสนใจ

http://devzone.zend.com/article/12132-Getting-Started-with-MongoDB-and-PHP
http://devzone.zend.com/article/12010-Kevin-van-Zonnevelds-Blog-Redis-PHP-Introduction
http://devzone.zend.com/article/8855-PHP-DOM-XML-extension-encoding-processing
http://devzone.zend.com/article/4486-Wrapping-C-Classes-in-a-PHP-Extension
http://devzone.zend.com/article/3645-Creating-Template-Based-Applications-with-HTML_Template_Flexy
http://devzone.zend.com/article/3592-Three-Quick-Tips-To-Make-Your-PHP-Understandable
http://devzone.zend.com/article/3336-Reading-and-Writing-Spreadsheets-with-PHP
http://devzone.zend.com/article/2387-XML-and-PHP-5
http://devzone.zend.com/article/1591-IBM-Convert-XML-to-JSON-in-PHP
http://devzone.zend.com/article/2783-Zend_Gdata-for-Picasa-YouTube-Google-Documents-List
http://devzone.zend.com/article/178-Consuming-Google-Calendars-with-the-Zend-Framework-
http://devzone.zend.com/node/view/id/70
http://devzone.zend.com/article/119-Blueprint-for-PHP-Applications-Bootstrapping-part-2
http://devzone.zend.com/article/1236-The-Best-Tool-For-The-Job-OO-versus-Procedural-Programming-in-PHP
http://devzone.zend.com/article/1086-Writing-Socket-Servers-in-PHP
http://devzone.zend.com/article/1084-Accepting-payments-using-Verisigns-Payflow-Pro
http://devzone.zend.com/article/1081-Using-cURL-and-libcurl-with-PHP
http://devzone.zend.com/article/1304-Using-MySQL-Full-text-Searching
http://devzone.zend.com/article/1083-Using-Ncurses-in-PHP
http://devzone.zend.com/article/1307-XML--RPC-Client