บันทึกของวีร์ | Vee(r)'s Blog

มิถุนายน 1, 2011

Kohana CLI (2)

Filed under: PHP — ป้ายกำกับ:, , , , , , — वीर @ 8:47 pm

หลังจาก เรียกใช้ Kohana จาก command line interface ได้แล้ว แต่ทีนี้อยากใส่ค่าตัวแปรอะไรเข้าไปด้วย ก็ทำง่ายๆ เลยมันมี option –get กับ –post อยู่

ยกตัวอย่างเช่น ผมมี controller ชื่อ home และ action คือ index และอยากส่งค่า x=10 และ y=abc เข้าไปทาง post method ก็ทำแบบนี้

php index.php –uri=”home/index” –post=”x=10&y=abc”

เสร็จละ

พฤษภาคม 31, 2011

เรียก Kohaha 3 จาก Command line interface

Filed under: PHP — ป้ายกำกับ:, , , , — वीर @ 9:57 pm

วิธีง่ายมากเข้าไป folder ที่มี index.php แล้วก็สั่ง php index.php –uri=ชื่อ controller/ชื่อ method เช่น php index.php –uri=home/index เป็นต้น

กุมภาพันธ์ 4, 2011

กรณีเจ๊งของ PHP และ regular expression เวลาเจอภาษไทย + UTF-8

Filed under: PHP — ป้ายกำกับ:, , , , — वीर @ 4:41 pm

ถ้ามี code แบบนี้ใช้ charset เป็น UTF-8

<?php
	print_r(preg_split("/\\s/", "ประเภท"));
?>

แบบนี้มันไม่น่าจะ split ได้เพราะว่า ไม่มี space ใน “ประเภท” เลยแต่มัน split ได้ซะงั้น

Array
(
    [0] => เธ›เธฃเธฐเน€เธ
    [1] => เธ—
)

แถวๆ “ภ” มันคงแปลงไปเป็นอะไรแล้ว code ไปเป็น space มั้ง

แต่ไม่ว่าจะเพราะว่าอะไร มีท่าแก้ง่ายๆ แบบนี้ใส่ u เข้าไป หายครับ

<?php
	print_r(preg_split("/\\s/u", "ประเภท"));
?>

ผมใช้ php 5.3.5 ที่มากับ xampp 1.7.4 และทดลองบน Windows 7 ครับ

ธันวาคม 12, 2010

ใช้ Swath จาก PHP

Filed under: NLP — ป้ายกำกับ:, , , , — वीर @ 2:20 pm

ทางบ้านถามเข้ามาหลายท่าน ผมจึงเขียนออกมาได้แบบนี้ครับ

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>Swath Web</title>
	<meta name="generator" content="TextMate http://macromates.com/">
	<meta name="author" content="Vee Satayamas">
	
</head>
<body>
<form method="post">
<textarea name="input_text" cols="80" rows="10"></textarea>
<input type="submit" value="submit">
</form>
<?php

    function swath($input_text) 
    {
        $input_filename= tempnam("/tmp", "swath_");
        $output_filename= tempnam("/tmp", "swath_");
        $input_text_tis620 = iconv("UTF-8", "TIS-620", $input_text);
        file_put_contents($input_filename, $input_text_tis620);
        system("/usr/bin/swath < $input_filename > $output_filename");
        $raw = file_get_contents($output_filename);
        $raw_utf8 = iconv("TIS-620", "UTF-8", $raw);
        unlink($input_filename);
        unlink($output_filename);
        return preg_split('/\|/', $raw_utf8);
    }

    if($_REQUEST['input_text']) {
        $output = swath($_REQUEST['input_text']);
        print implode(" ", $output);
    }
?>
</body>
</html>

แต่ว่าแบบนี้เราต้องลง swath ไว้ใน /usr/bin นะครับ ฯ​ ลงไว้ที่อื่นก็ไม่น่าเป็นไรนะครับ เปลี่ยนใน code เอาเลยก็ได้ ฯ อีกอย่างคือต้องการใช้ iconv ด้วย ฯ แต่ถ้าไม่ใช้ iconv ก็น่าจะได้อีกเหมือนกัน ฯ​ เปลี่ยนหน้าเว็บเป็น TIS-620 ให้หมดก็น่าจะใช้ได้เลย ฯ

เมษายน 23, 2010

ใช้ Tubsub API ผ่าน PHP

Filed under: NLP — ป้ายกำกับ:, , , , , — वीर @ 2:16 pm

ก็เขียน code แบบนี้เลยครับ

<?php
  function tubsub($txt) {
    $txt = urlencode($txt);
    $data = "input=$txt";
    $ch = curl_init("http://vivaldi.cpe.ku.ac.th/~vee/tubsube2t.php");
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);      
    curl_close($ch);
    $ans = json_decode($output);
    return $ans[0];
  }

  print tubsub("toto") . "\n";
?>

เขียนแบบข้างบนโปรแกรมก็จะพิมพ์ออกมาว่าเขียน toto ภาษาไทยเขียนอย่างไร ถ้าจะใช้กับอย่างอื่นก็ copy function tubsub ไปใช้ได้เลยครับ

พฤศจิกายน 21, 2009

ใน PDO query 2 ครั้งติดกันอาจจะเจ๊ง ถ้า…

Filed under: PHP — ป้ายกำกับ:, , , , , , — वीर @ 5:54 pm

ใน PDO query 2 ครั้งติดกันอาจจะเจ๊ง ถ้าหากว่า fetch ข้อมูลออกมาไม่หมด (ตามคู่มือ) แต่ก็มีท่าแก้คือ เรียก closeCursor ก่อน

CakePHP app กับ userdir

Filed under: CakePHP — ป้ายกำกับ:, , , , , , , , , , — वीर @ 4:55 pm

เวลาเอา web app ที่เขียนด้วย cakephp ไปใส่ใน userdir เช่น /home/veer/public_html/myapp (ซึ่งมักจะไปตรงกับ url http://hostname/~veer/myapp) มักจะมีปัญหากับ mod_rewrite ขึ้นมา แต่ก็แก้ไม่ยาก เพียงแต่แก้ .htaccess ใน myapp กับ myapp/app/webroot

เดิมทีจะเขียนไว้ประมาณนี้ (ใน myapp กับ myapp/app/webroot ไม่เหมือนกัน แต่ก็แก้เหมือนกัน)


   RewriteEngine on
   RewriteRule    ^$ app/webroot/    [L]
   RewriteRule    (.*) app/webroot/$1 [L]

ก็แก้โดยใส่ RewriteBase เข้าไปเป็นแบบนี้


   RewriteEngine on
   RewriteBase    /~veer/myapp
   RewriteRule    ^$ app/webroot/    [L]
   RewriteRule    (.*) app/webroot/$1 [L]

เสร็จแล้ว

ตุลาคม 27, 2009

Laemya – A lightweight web framework

Filed under: PHP — ป้ายกำกับ:, , — वीर @ 1:43 am

ช่วงนี้ผมเขียน PHP ปกติใช้ CakePHP แต่คราวนี้อยากได้อะไรที่บางกว่า CakePHP สักหน่อย แต่ว่าก็ยังติดใช้ CakePHP อยู่ทำไปทำมาก็เลยก็โปรแกรมอะไรบางอย่างออกมา ไม่รู้ว่าเรียกว่า web framework ได้เปล่า แต่ก็แยกมันออกมาและตั้งชื่อว่า “แหลมหญ้า” (laemya) ตามเขาแหลมหญ้าอุทยานแห่งชาติที่ผมไปเที่ยวบ่อยที่สุด

พยายามจะเขียนเป็นแบบ MVC แต่ก็คงไม่ค่อยเหมือนเท่าไหร่ ไม่ได้อาศัพพวก mod_rewrite หลักๆ แล้วก็ยังใช้การไปเรียกไฟล์ตรงๆ เหมือนใช้ PHP ปกติ แต่ว่า มี code บนหัวไฟล์นิดหน่อยที่จะไปโหลดพวก controller และ model มาให้ แบบนี้ เช่นผมจะสร้างเว็บที่ http://localhost/user/laemya.php ผมก็ไปสร้างไฟล์ user/laemya.php ขึ้นมาแบบนี้

<?php
    require_once "../laemya.php";
    laemya_init(__FILE__);
?>
<?php function title() { return "Laemya test page"; } ?>
<?php laemya_header() ?>
<div>
<?php
    print_r($data);
?>
</div>
<?php laemya_footer() ?>

โปรแกรม 2 บรรทัดข้างบนจะไปสร้าง controller และสร้าง model ยัดใส่ controller ไว้ ส่วน $data ที่ไม่รู้มาจากไหนก็คือผลลัพธ์ที่คืนมาจาก controller

ก็เลยต้องไปสร้าง model รอไว้ก่อน ใน model/user.php

<?php
    class User extends AppModel {
        var $table = 'users';

        function __construct() {
            parent::__construct();
        }
}
?>

model นี้ก็ไม่ได้ถึงกับเป็น orm หรอก ก็แค่ไปเรียกใช้ mdb2 อีกที แต่ก็มีตัวช่วยบ้าง ตามที่ผมจะอยากใช้

ตาราง users หน้าตาประมาณนี้

mysql> desc users;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment | 
| username | varchar(255) | NO   | UNI | NULL    |                | 
| realname | text         | NO   |     | NULL    |                | 
| email    | varchar(255) | NO   | UNI | NULL    |                | 
| password | varchar(255) | NO   |     | NULL    |                | 
| group_id | int(11)      | NO   |     | NULL    |                | 
+----------+--------------+------+-----+---------+----------------+
6 rows in set (0.05 sec)

ทีนี้ก็ลองดู controller ชื่อ controller/user_controller.php

<?php
    class UserController extends Controller {
        function laemya() {
            return $this->User->findAll();          
        }
    }
?>

user/laemya.php มันก็จะมาเรียก method ชื่อ laemya ใน UserController เอง แล้ว UserController ก็ไป query database มาแบบง่ายๆ แล้วคืนผลไป

นอกจากข้างบนแล้ว laemya ก็ยังมี feature พวกนี้ (ที่ปกติ framework ก็มักจะมีกันหมด)

  • authentication – พอใส่ var $auth = true; ลงใน controller มันก็จะถูกเรียกใช้งาน ถ้าอยากให้ controller ถูก protect ก็สร้าง method ชื่อ before ใน controller แล้วเรียก $this->checkUser() ใน before
  • column แบบ json ใน model ใส่ var $jsonColumns = array(“ชื่อ column”) แล้ว model ก็จะแปลง json กับ php ให้เวลาสั่ง findAll กับ save
  • มี validator ด้วย โดยสร้าง method ชื่อ validate ใน model แล้ว return array ที่ประมาณ array(‘user’ => ‘is required’) ออกมา
  • กำหนดได้ว่าจะให้ใส่ model ไหนใน controller บ้างใช้ var $uses = array(‘ชื่อ model’, ‘ชื่อ model’ …);
  • พวก $this->redirect และ $this->flash อะไรแบบนี้ก็ใช้ได้ด้วย

อีกนิดหนึ่งคือ laemya ไม่ได้อ่าน scheme ของ database เวลาจะใช้ save ใน model ต้องบอกมันด้วยว่ามี column อะไร type อะไร แบบนี้

<?php
    class MyModel extends AppModel {
        var $table = 'mytable';
        var $jsonColumns = array('tree');
        var $columns = array('owner_id', 'tree');
        var $types = array('integer', 'text');

        function __construct() {
            parent::__construct();
        }
    }
?>

ถ้าอยาก query ซับซ้อนขึ้นหน่อยก็ต้องเขียน SQL

<?php
    class User extends AppModel {
        var $table = 'users';

        function __construct() {
            parent::__construct();
        }
        
        function auth($email, $password) {
            $types = array('text', 'text');
            $password = md5($password);
            $sth = $this->db->prepare("select id from " . 
                $this->table . 
                " where email=? and password=?", $types);
            $data = array($email, $password);
            $result = $sth->execute($data);
            if (PEAR::isError($result)) 
                die($result->getMessage());
            $row = $result->fetchRow(MDB2_FETCHMODE_ASSOC);
            return $row;
        }
    }
?>

หลักแล้วก็ใช้ mdb2 แต่ว่าต่อไปก็อาจจะมีตัวช่วยเพิ่มขึ้น database ต่อที่ไหน ต้องไปแก้ใน cfg/config.php และพร้อม base url …

ถ้าทราบว่ามีโครงการไหนทำแนวๆ นี้อยู่แล้วช่วยบอกผมด้วยนะครับ เผื่อจะเลิกทำเอง

ลืมบอกว่า project อยู่ที่ http://laemya.sourceforge.net/ ตอนนี้ยังไม่มี package ครับ แต่ว่าสามารถโหลดได้โดย

hg clone http://laemya.hg.sourceforge.net:8000/hgroot/laemya/laemya 

ตุลาคม 25, 2009

Dynamic class instantiation ใน PHP

Filed under: PHP — ป้ายกำกับ:, , — वीर @ 1:58 pm

ไม่ทราบว่าใช้คำถูกต้องหรือเปล่านะครับ ประมาณว่าถ้าผมครับ คืออยากจะสร้าง class ตาม string ที่ให้มาเวลารัน แทนที่จะต้องบอกว่า class ชื่ออะไร วิธีก็คือใช้ reflection class อ่านมาจาก stackoverflow

<?php
    class Toto {
        function printToto() {
            print "This is Toto.\n";
        }
    }
    $className = "Toto";
    $reflectionClass = new ReflectionClass($className);
    $toto = $reflectionClass->newInstance();
    $toto->printToto();
?>

เวลาจะเปลี่ยนชื่อ class ที่จะเอามาสร้าง object ก็เปลี่ยนที่ $className ได้เลย กะว่าจะเอามาใช้กับ controller และ model

ตุลาคม 18, 2009

History สำหรับ CakePHP Model

Filed under: CakePHP — ป้ายกำกับ:, , , , , — वीर @ 2:25 pm

สิ่งผมเขียนไม่ใช่ best practice จริงๆ แล้วผมก็ไม่ค่อยแน่ใจว่ามันจะใช้ได้ดีหรือเปล่า แต่ว่าก็บันทึกไว้ก่อน. เว็บที่ผมเขียนมักจะต้องทำอะไรประเภทมี version control ด้วย แนวๆ wiki ดังนั้นถ้า model ช่วงแบ่งเบาภาระพวก version control ไปได้บ้าง ก็ทำให้ controller ดูรกน้อยลงไปมาก (หวังว่าแบบนั้น) ก่อนหน้านี้ CakePHP เคยมี behavior ด้วยช่วยเก็บ history มาให้ถ้าจำไม่ผิด แต่ตอนนี้หาไม่เจอแล้ว และเพื่อให้ได้อย่างใช้ตัวเองผมก็เลยใช้แค่ callback function.

model ที่ผมต้องการจำ history ชื่อ Textunit สมมุตว่า textunits เป็น table มี column ได้แก่ id และ string เอาแค่นี้ก็พอ เพื่อเป็นตัวอย่าง วิธีของผมก็คือสร้างขึ้นมาอีก table เลยชื่อ history_textunits โดยมี column ดังนี้ id, old_id, revision และ string

จากนั้นก็สร้าง code ใน app/model ตามนี้

<?php
class Textunit extends AppModel {
   var $name = 'Textunit';
   var $history = 'HistoryTextunits';

    function beforeSave() {
        if(!empty($this->id)) {
            $historyModel = ClassRegistry::init($this->history);
            $historyData = $this->findById($this->id);
            $historyModel->record($historyData[$this->name]);
        }                 
        return true;
    }
}
?>

และ

<?php
class HistoryTextunits extends AppModel {
    var $name = 'HistoryTextunits';
    function record($textunit) {
        $history = array();
        foreach($textunit as $k => $v) {
            if($k == "id") 
                $k = "old_id";
            $history[$k] = $v;
        }
        $this->create();
        $this->save($history);
    }
}
?>

แค่นี้เอง :-P

เรื่องที่เก่ากว่า

Theme: Shocking Blue Green. บลอกที่ WordPress.com .

Follow

Get every new post delivered to your Inbox.

Join 632 other followers