BarCamp Bangkok Winter 2008

งานนี้คงไม่ต้องบรรยายอะไรมากนักในส่วนรายละเอียดงานเพราะข้อมูลต่าง ๆ น่าจะหาได้จากเว็บหลักของงานได้โดยตรง

งานเมื่อวาน (26 มกราคม 2551) คนมากันเพียบ ก่อนงานเริ่มก็มากันเยอะแล้วครับ

P1050658

งานวันดังกล่าวนั้น ชาวต่างชาติเยอะพอสมควรเลย น่าจะ 30 % ของคนในงานได้ครับ โดยผู้เข้ามาร่วมงานนี่เท่าที่กะ ๆ จากสายตาแล้วน่าจะได้ประมาณ 200 กว่าคนได้เลยหล่ะ แถมทุก ๆ คนร่วมด้วยช่วยกันดีมากครับ

P1050660

พี่อาท และพี่ sugree ครับ

P1050666 

พอมาถึง คนที่อยากพูดอะไรก็ไปเขียนหัวข้อไว้ แล้วระยุว่าบรรรยายในภาษาอะไร แล้วก็ให้คนที่มาร่วมงานโหวตกันเองว่าอยากฟังเรื่องอะไรบ้าง

P1050659

โหวตกันเข้าไป อยากฟังเรื่องไหนก็โหวตครับ

P1050661

P1050663

P1050664

หัวข้อของผมในงานครับ "PHP Framework with Hoffman Framework (opening)" มีคนโหวตเยอะพอสมควรเลยครับ ดีใจมากครับผม แต่รู้สึกว่าตัวเองจะ present ไม่ค่อยดีเท่าไหร่ครับ แต่ตอนนี้ทำทำหน้าสำหรับ Project ตัวนี้แล้วครับอยู่ท่  PHP Hoffman Framework ครับผม คาดว่าจะนำตัว source code ตัวที่ปรับแต่งและแก้ไขหลาย ๆ ส่วนที่ให้สมบูรณ์มากกว่านี้ก่อนครับ

P1050662

ด้านล่างนี่รายการแต่ละห้อง อันนี้ถ่ายช่วงแรก ๆ ที่มีการเรียงลำดับเลยครับ แต่มาหลัง ๆ เห็นว่ามีมากกว่าที่เห็นในภาพเยอะมาก ๆ

P1050669P1050670P1050668P1050672P1050671  P1050673 

หัวข้อที่มีคนเข้าร่วมมากที่ "AV Development Life Cycle" ฮาตลอดงานครับ [TH][EN][JP][KR] โดย Hunt, Keng และ Sugree

P1050684

สุดท้ายหลังเลิกงานก็จบที่ร้านสวนอาหารในซอย สุขุมวิท 33/1 ครับ

P1050688

 P1050689

ส่วนอื่น ๆ อ่านต่อได้ที่ รายงานสด BarcampBangkok ครับผม

รูปภาพต่าง ๆ นั้นมีคนเอาไปใส่ใน Photo Gallery ส่วนตัวและนำมาเผยแพร่แล้วหลายคนครับ ;)

ภาพของผมจากเว็บ http://blog.winginfotech.net/

IMG_9710 IMG_9711

IMG_9713 IMG_9717

ผู้เข้าร่วมในหัวข้อผมครับ

IMG_9714

งานนี้ต้องขอบคุณทุกท่านที่เข้ามาร่วมในหัวข้อของผมครับผม  /||\

ขอบคุณผู้สนับสนุนงานด้วยครับ ที่มีพื้นที่เพื่อคนไอทียุคใหม่ครับ ;)

Class Upload (Hmf_Upload) ภายใน PHPHoffman Framework (HMF)

ตัวนี้เป็น source-code ของ Hmf_Upload ของ ภายใน PHPHoffman Framework ได้ปรับแต่งมาพอสมควรจากตัวเก่า ๆ ใน v 0.1a ก่อนหน้านั้น ลดความซับซ้อนลง และปรับ Format Code ใหม่

ตัวนี้รองรับการส่งข้อมูลเข้ามาแบบหลาย ๆ ไฟล์พร้อม ๆ กัน, ดักจับ MIME Type และ Extension Type ที่ไม่ได้กำหนด รวมถึงไม่ให้ส่งไฟล์ขนาดใหญ่เกินกว่าที่กำหนดด้วย

  1. < ?php
  2. define("HMF_UPLOAD_TXT_UPLOAD_COMPLETE", "Upload เสร็จสมบูรณ์.");
  3. define("HMF_UPLOAD_TXT_UPLOAD_ERROR_SIZE", "The uploaded file exceeds the 'filesSize' setting directive.");
  4. define("HMF_UPLOAD_TXT_UPLOAD_ERROR_TYPE", "รูปแบบไฟล์ผิดจากที่กำหนด");
  5. define("HMF_UPLOAD_TXT_UPLOAD_ERROR_OPERATION", "Operation error on Error Messages Explained.");
  6. define("HMF_UPLOAD_TXT_UPLOAD_ERR_INI_SIZE", "The uploaded file exceeds the upload_max_filesize directive.");
  7. define("HMF_UPLOAD_TXT_UPLOAD_ERR_FORM_SIZE", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.");
  8. define("HMF_UPLOAD_TXT_UPLOAD_ERR_PARTIAL", "The uploaded file was only partially uploaded.");
  9. define("HMF_UPLOAD_TXT_UPLOAD_ERR_NO_FILE", "No file was uploaded.");
  10. define("HMF_UPLOAD_TXT_UPLOAD_ERR_NO_TMP_DIR", "Missing a temporary folder.");
  11. define("HMF_UPLOAD_TXT_UPLOAD_ERR_EXTENSION", "File upload stopped by extension.");
  12. define("HMF_UPLOAD_TXT_UPLOAD_ERR_CANT_WRITE", "Failed to write file to disk.");
  13. define("HMF_UPLOAD_TXT_UPLOAD_ERR_DEFAULT", "An unknown file upload error occured.");
  14. define("UPLOAD_ERR_FILE_SIZE", "-1");
  15. define("UPLOAD_ERR_FILE_TYPE", "-2");
  16.  
  17. class Hmf_Upload {
  18.  
  19.     private $mimeType = array();
  20.     private $extensionType = array();
  21.     private $checkUploadStatusText = array();
  22.     private $fileNameUploads = array();
  23.     private $fileSizeUploads = array();
  24.     private $fileMimeTypeUploads = array();
  25.     private $fileExtTypeUploads = array();
  26.     private $formInputName;
  27.     private $filesSize = "2097152";
  28.     private $desinationStoreFiles;
  29.     private $formBegin = false;
  30.     private $dirUpload;
  31.     private $storeFilesName = NULL;
  32.  
  33.     public function SetDirUpload($value) {
  34.         $this->dirUpload = $value;
  35.     }
  36.     public function GetDirUpload() {
  37.         return $this->dirUpload;
  38.     }
  39.     public function SetInputName($value) {
  40.         $this->formInputName = $value;
  41.     }
  42.     public function GetInputName() {
  43.         return $this->formInputName;
  44.     }
  45.     public function SetFilesSize($value) {
  46.         $this->filesSize = $value;
  47.     }
  48.     public function GetFilesSize() {
  49.         return $this->filesSize;
  50.     }
  51.     public function SetAllowMimeType($mimeType) {
  52.         if(is_array($mimeType)) $this->mimeType = $mimeType;
  53.         else $this->mimeType[] = $mimeType;
  54.     }
  55.     public function GetAllowMimeType() {
  56.         return $this->mimeType;
  57.     }
  58.     public function SetAllowExtType($extensionType) {        
  59.         if(is_array($extensionType)) $this->extensionType = $extensionType;        
  60.         else $this->extensionType[] = strtolower($extensionType);    
  61.     }
  62.     public function GetAllowExtType() {
  63.         return $this->extensionType;
  64.     }
  65.     public function SetFileNameUploads($index, $value) {
  66.         $this->fileNameUploads[$index] = $value;
  67.     }
  68.     public function GetFileNameUploads() {
  69.         return $this->fileNameUploads;
  70.     }
  71.     public function SetFileSizeUploads($index, $value) {
  72.         $this->fileSizeUploads[$index] = $value;
  73.     }
  74.     public function GetFileSizeUploads() {
  75.         return $this->fileSizeUploads;
  76.     }
  77.     public function SetFileMimeTypeUploads($index, $value) {
  78.         $this->fileMimeTypeUploads[$index] = $value;
  79.     }
  80.     public function GetFileMimeTypeUploads() {
  81.         return $this->fileMimeTypeUploads;
  82.     }
  83.     public function SetFileExtTypeUploads($index, $value) {
  84.         if(is_array($value)) $this->FileExtTypeUploads = $value;
  85.         $this->fileExtTypeUploads[$index] = strtolower($value);
  86.     }
  87.     public function GetFileExtTypeUploads() {
  88.         return $this->fileExtTypeUploads;
  89.     }
  90.     public function SetStoreFilesName($name) {
  91.         if(is_array($name)) $this->storeFilesName = $name;
  92.         $this->storeFilesName[] = $name;
  93.     }
  94.     public function GetStoreFilesName() {
  95.         return $this->storeFilesName;
  96.     }
  97.     public function SetDestinationStoreFiles($index, $value) {
  98.         if(is_array($value)) $this->desinationStoreFiles = $value;
  99.         $this->desinationStoreFiles[$index] = $value;
  100.     }
  101.     public function GetDestinationStoreFiles() {
  102.         return $this->desinationStoreFiles;
  103.     }
  104.     public function ActionUpload() {
  105.         $storeFilesName = $this->GetStoreFilesName();
  106.         foreach ($_FILES[$this->GetInputName()]["error"] as $key => $error) {
  107.             $name = $_FILES[$this->GetInputName()]["name"][$key];
  108.             $fileExt = $this->GetExt($name);
  109.             if($error != 4 ) {
  110.                 if ($this->CheckUpload($key, $error)) {
  111.                     if($this->CheckMimeType($_FILES[$this->GetInputName()]["type"][$key]) or $this->CheckExtType($fileExt) ) {
  112.                         if($this->CheckSize($_FILES[$this->GetInputName()]["size"][$key])) {
  113.                             $tmp_name = $_FILES[$this->GetInputName()]["tmp_name"][$key];
  114.                             if(!empty($storeFilesName[$key])) $name = $storeFilesName[$key].'.'.$fileExt;
  115.                             if(file_exists($this->GetDirUpload().'/'.$name)) unlink($this->GetDirUpload().'/'.$name);
  116.                             move_uploaded_file($tmp_name, $this->GetDirUpload().'/'.$name);
  117.                             $this->SetDestinationStoreFiles($key, $this->GetDirUpload().'/'.$name);
  118.                         }
  119.                         else {
  120.                             $this->CheckUpload($key, UPLOAD_ERR_FILE_SIZE);
  121.                         }
  122.                     }
  123.                     else {
  124.                         $this->CheckUpload($key, UPLOAD_ERR_FILE_TYPE);
  125.                     }
  126.                 }
  127.                 $this->SetFileNameUploads($key, $_FILES[$this->GetInputName()]["name"][$key]);
  128.                 $this->SetFileSizeUploads($key, $_FILES[$this->GetInputName()]["size"][$key]);
  129.                 $this->SetFileMimeTypeUploads($key, $_FILES[$this->GetInputName()]["type"][$key]);
  130.                 $this->SetFileExtTypeUploads($key, $fileExt);
  131.             }
  132.         }
  133.     }
  134.     public function CheckExtType($value) {
  135.         $arr_type = $this->GetAllowExtType();
  136.         return in_array(strtolower($value), $arr_type);
  137.     }
  138.     public function CheckMimeType($value) {
  139.         $arr_type = $this->GetAllowMimeType();
  140.         return in_array($value, $arr_type);
  141.     }
  142.    public function CheckSize($value) {
  143.         if($value < = $this->GetFilesSize()) return true;
  144.         else return false;
  145.     }
  146.     public function SetUploadStatusText($index, $code, $text, $bool) {
  147.         $this->checkUploadStatusText[$index] = array('code' => $code, 'text'=>$text, 'bool'=>$bool);
  148.     }
  149.     public function GetUploadStatusText($index = NULL) {
  150.         if(empty($index)) return $this->checkUploadStatusText;
  151.         return $this->checkUploadStatusText[$index];
  152.     }
  153.     public function CheckUpload($index, $value) {
  154.         switch ($value) {
  155.             case UPLOAD_ERR_OK:
  156.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_COMPLETE, true);
  157.                 return true;
  158.             case UPLOAD_ERR_INI_SIZE:
  159.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_INI_SIZE, false);
  160.                 return false;
  161.             case UPLOAD_ERR_FORM_SIZE:
  162.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_FORM_SIZE, false);
  163.                 return false;
  164.             case UPLOAD_ERR_PARTIAL:
  165.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_PARTIAL, false);
  166.                 return false;
  167.             case UPLOAD_ERR_NO_FILE:
  168.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_NO_FILE, false);
  169.                 return false;
  170.             case UPLOAD_ERR_NO_TMP_DIR:
  171.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_NO_TMP_DIR, false);
  172.                 return false;
  173.             case UPLOAD_ERR_CANT_WRITE:
  174.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_CANT_WRITE, false);
  175.                 return false;
  176.             case UPLOAD_ERR_EXTENSION:
  177.                 $this->SetUploadStatusText($index, $value, HMF_UPLOAD_TXT_UPLOAD_ERR_EXTENSION, false);
  178.                 return false;
  179.             case UPLOAD_ERR_FILE_SIZE:
  180.                 $this->SetUploadStatusText($index, -1, HMF_UPLOAD_TXT_UPLOAD_ERROR_SIZE, false);
  181.                 return false;
  182.             case UPLOAD_ERR_FILE_TYPE:
  183.                 $this->SetUploadStatusText($index, -2, HMF_UPLOAD_TXT_UPLOAD_ERROR_TYPE, false);
  184.                 return false;
  185.             default:
  186.                 $this->SetUploadStatusText($index, NULL, HMF_UPLOAD_TXT_UPLOAD_ERR_DEFAULT, false);
  187.                 return false;
  188.         }
  189.     }
  190.     public function GetActionInfo() {
  191.         $result_details['name'] = $this->GetFileNameUploads();
  192.         $result_details['destination'] = $this->GetDestinationStoreFiles();
  193.         $result_details['size'] = $this->GetFileSizeUploads();
  194.         $result_details['ext'] = $this->GetFileExtTypeUploads();
  195.         $result_details['mime'] = $this->GetFileMimeTypeUploads();
  196.         $result_details['status'] = $this->GetUploadStatusText();        
  197.         return $result_details;
  198.     }
  199.     public function GetExt($filename){
  200.         return strtolower(substr(strrchr($filename, '.'), 1));
  201.     }
  202. }
  203. ?>

แล้วนี่ code html สำหรับทดสอบครับ

  1. <form method="post" action="upload.php" enctype="multipart/form-data">
  2.     <input type="file" id="fdata" name="fdata[]"/>
  3.     <input type="file" id="fdata" name="fdata[]"/>
  4.     <input type="file" id="fdata" name="fdata[]"/>
  5.     <input type="submit" />
  6. </form>

จะสังเกตว่าผมใช้ HTTP Method แบบ POST แล้วใช้ร่วมกับ Form imput แบบ Array ครับ ทำให้สามารถส่งข้อมูลหลายๆ ค่าได้ในตัว Input form ชื่อเดียวกันเลย

แล้วด้านล่างก็ code หน้าสำหรับเอาไว้ทำงาน

  1. $objUpload = new Hmf_Upload();
  2. $objUpload->SetDirUpload('upload');
  3. $objUpload->SetStoreFilesName(array('1','2','3'));
  4. $objUpload->SetInputName('fdata');
  5. $objUpload->SetAllowExtType(array('jpeg','jpg','png','gif'));
  6. $objUpload->ActionUpload();
  7. $status = $objUpload->GetActionInfo();

SetDirUpload – กำหนด directory ปลายทาง (ไม่ต้องใส่ / ต่อท้าย)
SetStoreFilesName – กำหนดชื่อของไฟล์ที่จะเอาไปวางไว้ปลายทาง กำหนดเป็น array ตาม index ถ้ามี 3 field ก็กำหนด 3 index แต่ถ้าไม่กำหนดจะเป็นชื่อของไฟล์นั้น ๆ เลย
SetInputName – ชื่อ file field ที่เราจะให้มันส่งค่า ไม่ต้องใส่ [] ต่อท้ายครับ
SetAllowExtType – กำหนดนามสกุลที่ต้องการให้ upload ได้ ใส่เป็น array ไป
SetAllowMimeType – กำหนด Mime-type ของไฟล์ลงได้ด้วย กำหนดแบบเดียวกับ SetAllowExtType (ในตัวอย่างไม่มีเพราะดักแต่นามสกุลอย่างเดียว)
ActionUpload – สั้งให้รับค่า upload แล้วทำงาน
GetActionInfo – ข้อมูลต่าง ๆ ที่จำเป็นหลังจาก upload ครับ (ในตัวอย่างส่งไปให้กับ $status)

ข้อมูลที่ได้จากตัวแปร $status เป็น Array ครับ ลอง print_r หรือ var_dump ดูครับ

อันนี้ได้จาก var_dump

  1. array(6) {
  2.   ["name"]=>        array(1) {
  3.                                 [0]=> string(12) "DSC00132.JPG"
  4.                             }
  5.   ["destination"]=> array(1) {
  6.                                 [0]=> string(12) "upload/1.jpg"
  7.                             }
  8.   ["size"]=>           array(1) {
  9.                                 [0]=> int(419231)
  10.                             }
  11.   ["ext"]=>            array(1) {
  12.                                 [0]=> string(3) "jpg"
  13.                             }
  14.   ["mime"]=>        array(1) {
  15.                                 [0]=> string(11) "image/pjpeg"
  16.                             }
  17.   ["status"]=>        array(1) {
  18.                                 [0]=> array(3) {
  19.                                             ["code"]=> int(0)
  20.                                             ["text"]=> string(44) "Upload เสร็จสมบูรณ์."
  21.                                             ["bool"]=> bool(true)
  22.                                           }
  23.                             }
  24. }

ตัว source code ยังคงมี Bug บางส่วน และไม่สมบูรณ์ 100% ครับ ต้องปรับแต่งอีกบางส่วน

ตอนต่อไปเป็นการนำเอา Hmf_Upload ไปใช้คู่กับ Hmf_Img เพื่อ Scale รูป

Code support for PHP 5.2.x

กำลังเตรียมตัวไปงาน BarCamp Bangkok Winter 2008

image

งาน BarCamp Bangkok Winter 2008

จัดในวันที่ 26 มกราคม 2551 โดยจัดที่ร้านอาหาร Indus แถวสุขุมวิท บรรยากาศดีเยี่ยม งานเริ่มตั้งแต่ 10 โมงเช้าจนถึง 6 โมงเย็น แล้วมีปาร์ตี้ข้าวเย็นกันต่อตอนช่วงค่ำ

ตอนนี้กำลังปั่นตัว slide ที่จะเอาไปพูดในงาน 2 ตัว (ในรอบเดียว)

  1. MySQL Tuning นี่คงเอาเนื้อหาเดียวกับที่เคยได้โพสใน entry เก่าไปแล้ว แต่เพิ่มเติมและใส่ประสบการณ์ตรงของตัวเองลงไป
  2. PHP Framework ผมคงไม่พูดถึงตัวอื่นมาก เอาแค่ intro พอนิด ๆ แต่เอา PHP Hoffman Framework (HMF) ไปแสดงก่อน

ซึ่งตัว PHP Framework ของผมเนี่ย ตอนนี้ก็ปั่นตัว implementation code อยู่ ไม่รู้จะทันหรือเปล่า แค่ทำ Routing URL กับพวก Standard Code ต่าง ๆ ใหม่หมดก็เล่นซะหลายวัน รวมถึง Directory structure ก็เพิ่งจะลงตัวไป น่าจะเข้ารูปเข้ารอยในไม่ช้านี้ หลาย ๆ ภายใน Framework ยังไม่นิ่งพอจะเป็น Alpha version ได้ด้วยซ้ำ แถมหลายอย่างที่อยู่ใน 0.1a (ตัวใหม่ผมเรียกมันว่า Rv2 หรือ revolution version 2) ไม่ได้โอนถ่ายมาใส่อีกด้วย เพราะซ้ำซ้อน กับ Zend Components ที่จะเอามาใช้อยู่หลายตัวอย่าง ACL ที่ทำเองใน 0.1a พอมาตัวใหม่นี้ ใช้ Zend_Acl ของ Zend Framework แทน และหลาย ๆ ตัวที่โยกมาใช้ Zend แทนหลายตัวเลย รวมถึงตัว Model ที่ใช้ความสามารถของ Doctrine และ Zend_Db แทนที่ตัว Components ของผมเอง แต่ว่าตัวที่ผมใช้อยู่ก่อนหน้านั้นก็ยังคงมีอยู่ เหมือนเดิม เพียงแต่ไม่ได้เปิดใช้เท่านั้นเอง ส่วน Controller นี่เขียนเองหมดเลย Flow ตัว Controller ต่าง ๆ จัดการเองหมด รวมถึง Standard Structure และ Code ต่าง ๆ ส่วนของ View ก็ใช้ Smarty เข้ามาแทนของเก่าของผมเองทั้งหมดเลย

ตอนนี้ที่ตัดสินใจไว้ทั้ง 3 components หลัก ๆ ก็คือ

LogicModel ใช้ความสามารถต่าง ๆ จาก Doctrine และ Zend_Db และพวก tools ด้าน Business Logic ทั้งหมด
FlowController อันนี้เขียนเองทั้งหมดเพราะหาตัวที่มันโดนใจไม่ได้ ฮา …
RenderView ใช้ความสามารถต่าง ๆ ของ Smarty มาช่วยในส่วนนี้

เพราะเท่าที่หาข้อมูลและ defend กับตัวเองแล้วหลาย ๆ อย่างน่าจะใช้สิ่งที่มีอยู่และนำมาปรับให้เข้ากับแนวทางของ Framwork ของเราเองหลาย ๆ ตัวน่าจะทำให้มันง่าย ๆ เข้าไว้ด้วย Framework บางตัวทำเรื่องง่าย ๆ ให้เป็นเรื่องยากไปซะงั้น บางตัวทำงานไม่ยืดหยุ่นอะไรแบบนั้นอีก เลยทำเองซะ แล้วให้คนอื่นมา defend กับเราว่าควรปรับอะไรอีกบาง

หลาย ๆ อย่าง หลาย ๆ idea มาจากหลาย ๆ Framework มาปรับใช้เข้าด้วยกันบางอย่าง idea ดีมาก ๆ น่าจะทำให้มันทำงานได้ง่าย ขึ้นพอสมควร

แล้วเจอกันที BarCamp ครับ