0

สร้าง diagram ด้วย LibreOffice

ผมใช้ LibreOffice 3.5.7.2 บน Ubuntu 12.04 LTS นะครับ ผมมีปัญหาว่าตัววาดรูปบน Writer ไม่ไม่ถูกใจ ลองไปลองมาแล้วรู้สึกว่าโปรแกรมวาดรูปบน Impress ถูกใจที่สุดก็เลยใช้ Impress วาดแต่มีปัญหาว่าพอใช้ Impress เวลาเอามาแปะใน Writer ภาพมันเละหรือ Export เป็นรูปธรรมามันมีที่ว่างขาว ๆ เยอะเกินไปมาก ๆ

วิธีแก้คือก่อน export เลือกเฉพาะส่วนที่เราต้องการ

ภาพหน้าจอ

เวลา export เลือกใน checkbox selection ข้างล่างด้วย

ภาพหน้าจอ

เวลามาเปิดดูมันก็จะพอดีกับภาพแบบรูปข้างล่าง ก็เอาไป insert ใส่ Writer ได้เลย

ภาพหน้าจอ

0

เริ่มทำ app บน Firefox OS ตอนที่ 1

ทีแรกก็ลง Firefox ก่อนครับ แล้วก็ลง Firefox OS Simulator ทีนี้ก็โหลด app ตัวอย่างมา https://github.com/comoyo/ffos-list-detail วิธีลงก็ตามใน link อะครับ แต่ผมต้อง cd เข้าไปใน bin แล้วค่อยสั่ง sudo ./init.sh ทำแบบในเว็บแล้วเจ๊งเพลียนิด ๆ เสร็จแล้วก็กลับมาที่หน้า Simulator firefox_sim
แล้วก็เอา url ของ app ที่เรารันไว้มาแปะ ในที่นี้คือ http://localhost:8081 แล้วก็สั่ง run เลยใช้ได้แล้ว … ตั้งแต่ลอง mobile os มา ผมว่านี่ง่าย เรื่องน้อย สุด ๆ แล้ว

1

Using Auth module in Kohana 3.2

This post is shown incomplete example for using Auth module in Kohana 3.2

  1. Besides installing Kohana as normal. bootstrap.php has be modified in order to enable these modules that are Auth, Database and Orm. File-based authentication seems to be available also but this post will be focus on using orm and database only.

    Kohana::modules(array(
        'auth'       => MODPATH.'auth',       // Basic authentication
        // 'cache'      => MODPATH.'cache',      // Caching with multiple backends
        // 'codebench'  => MODPATH.'codebench',  // Benchmarking tool
        'database'   => MODPATH.'database',   // Database access
        // 'image'      => MODPATH.'image',      // Image manipulation
        'orm'        => MODPATH.'orm',        // Object Relationship Mapping
        // 'unittest'   => MODPATH.'unittest',   // Unit testing
        // 'userguide'  => MODPATH.'userguide',  // User guide and API documentation
        ));
    
  2. Provide configuration files in application/config. There should be auth.php and database.php copied from /modules.
  3. Create a database using SQL file named auth-schema-mysql.sql, which is included in Kohana 3.2. ( I made a mistake by spending time to find it using Google. ). Then change database.php to conform your database.
  4. Create application/view/template/default.php

    <?php echo $content;?>
    
  5. Create application/view/pages/login.php
    <?php echo form::open('/user/login'); ?>
     <?php echo form::label('username', 'Username:'); ?>
     <?php echo form::input('username'); ?>
     <?php echo form::label('password', 'Password:'); ?>
     <?php echo form::password('password'); ?>
     <?php echo form::submit('submit', 'Login'); ?>
    <?php echo form::close(); ?>
    

    (This is based on http://docs.kohanaphp.com/addons/auth#mysql_schema

  6. Create a user controller by inheriting Template controller as follow
    <?php defined('SYSPATH') or die('No direct script access.');
    
    class Controller_User extends Controller_Template
    {
     public $template = 'templates/default';
    
     public function action_login() 
     {
     $this->auto_render = FALSE; 
     $post = $this->request->post();
     $success = Auth::instance()->login($post['username'], $post['password']);
    
     if ($success)
     {
     $this->response->body('OK');
     }
     else
     {
     $this->response->body('FAIL');
     }
     }
     
     public function action_login_form()
     {
     $this->template->content = View::factory('pages/login');
     }
     
    } 
    
    

    At this state, you must be able to access URL /user/login_form and try to login and it should always report FAIL

  7. Add a user by directly insert a user to the table Users in MySQL. However the password must be generated from Auth::instance()->hash. Moreover users_roles must be added. Normally you should add 1,1.
  8. Everything should works now. However the controller still did not check whether the user is logged in. Register action is still not provided. I think what is left is not difficult to do by consulting an API reference.

Tags: , , , , , ,

1

ไปฟังเรื่อง “ขั้นตอนการผลิตและเขียนบทความวิจัยในวารสาร” มา

วันนี้ฟัง ขั้นตอนการผลิตและเขียนบทความวิจัยในวารสาร โดย ศาสตราจารย์ ดร. ชิดชนก เหลือสินทรัพย์ ในงาน NCSEC 2009 จัดที่โรงแรม Montien Riverside ไม่รู้สะกดอย่างไร เข้าไปในเว็บหาภาษาไทยไม่พบ

ไกลเหมือนกัน แต่ว่าทางภาควิชาฯและคณะฯก็จัดรถดูแลเรื่องลงทะเบียนให้ ก็ขึ้นรถตู้ของคณะฯ ไปสบายๆ ^_^.

ที่น่าไปฟังเพราะว่า จะเรียนให้จบปริญญาเอก ต้องตีพิมพ์ผลงาน จริงๆ ช่วงนี้ผมก็ไปฟังเรื่องพวกนี้บ่อย เพราะว่าหลายๆ อย่างมาจากประสบการณ์ของผู้สอน (ผู้บรรยาย) ก็ได้เกร็ดอะไรที่แตกต่างกันไป

ปัญหาของผมที่คนอื่นก็คงมีคล้ายๆ กัน ไม่ใช่เฉพาะคนไทย แต่นักเรียนทั่วไปที่ไม่ได้ใช้ภาษาอังกฤษเป็นภาษาหลัก เวลาตีพิมพ์ระดับนานาชาติ ก็มักจะมีปัญหาในการใช้ภาษาอังกฤษ นอกจากพยายามเพิ่มความสามารถในการใช้ภาษาอังกฤษแล้ว ก็ยังมีเทคนิคที่จะหลีกเลี่ยงปัญหาประเภทนี้ด้วย นอกจากปัญหาด้านภาษาแล้วก็ยังมีปัญหาอื่นๆ อีกเยอะ ที่คนที่เริ่มตีพิมพ์แรกๆ ก็อาจจะไม่ทราบ

ไปฟังครั้งนี้รู้สึกว่าเข้มข้นและลงรายละเอียดมาก (เป็นสิ่งที่ผมต้องการ) อย่างเช่น เวลาวิจารณ์งานของคนอื่น ก็ควรจะหลีกเลี่ยงการใช้คำว่า “weak point” “disadvange” และ “drawback” ที่มันแรงเกินไป ควรเขียนว่างานนั้นดีอย่างไรทำอะไรได้ แล้วตามด้วยข้อจำกัด แล้วใช้ศัพท์เช่น “not applicable” และ “not enough” แทน แล้วก็มีเรื่องต่างๆ อีกมากมาย ที่ผมขี้เกียจเขียนแล้ว …

0

cross processing effect ด้วย gimp

เห็นภาพของ มร.โชค ที่ http://mrchoke.multiply.com/photos/album/193/My_Way…#45 แล้วชอบใจ. จึงถามมร.โชคว่าทำอย่างไร มร.โชคว่าใช้ cross processing effect (ประมาณนั้น) ผลว่าได้เว็บนี้มา http://www.lilahpops.com/cross-processing-with-the-gimp/ เป็นวิธีทำ cross processing effect บน gimp. ผมก็เลยจัดแจงทำตาม ได้ผลแบบภาพดอกทานตะวันข้างล่าง.

cross process by gimp

ชอบใจนัก ^_^ …

ป.ล. gimp เป็นซอฟต์แวร์เสรีเอาไว้ทำอะไรต่างๆ กับรูปภาพ มีทั้งบน gnu/linux, mac, windows ว่าไปก็คล้ายๆ photoshop แต่ว่าไม่ต้องซื้อหามาในราคาแพง แก้ไขปรับปรุงได้ตามใจ แถมใช้บน gnu/linux ได้เลยด้วย.

2

CakePHP 1.2.0.6311b: Group + ACL + AuthComponent

หลังจากที่ใช้ ACL กับ AuthComponent ได้แล้ว … ก็จะลองเปลี่ยนตัวอย่างเก่าให้ใช้ Group ได้ดู ก็แก้เยอะเหมือน :-P.

ผมเริ่มจากการแก้ database schema ก่อน. หลังจากที่ลองใช้ migration อยู่พักใหญ่แล้วผมก็งงๆ เลยตัดสินใจสละ table: aros และ users ไป.

เริ่มจากลบของใน table: aros และ aros_acos ก่อน ด้วยคำสั่ง:

mysql -u<your_username> -p<your_password> my_project -e 'delete from aros;'
mysql -u<your_username> -p<your_password> my_project -e 'delete from aros_acos;'

แล้วก็แก้ CakeSchema ของ user ใน folder: app/config/sql, ไฟล์: users.php แก้เป็นแบบนี้:

class UsersSchema extends CakeSchema {

    var $name = 'users';

    function before($event = array()) {
        return true;
    }

    function after($event = array()) {
    }

    var $users =
        array('id' =&gt; array('type'=&gt;'integer',
                            'null' =&gt; false,
                            'key' =&gt; 'primary',
                            'extra' =&gt; 'auto_increment'),
              'username' =&gt;  array('type'=&gt;'string',
                                   'null' =&gt; false,
                                   'length' =&gt; 255),
              'password' =&gt;  array('type'=&gt;'string',
                                   'null' =&gt; false,
                                   'length' =&gt; 255),
              'group_id' =&gt; array('type' =&gt; 'integer',
                                  'null' =&gt; false),
              'indexes' =&gt; array('PRIMARY' =&gt; array('column' =&gt; 'id',
                                                    'unique' =&gt; 1)));
    var $groups =
        array('id' =&gt; array('type' =&gt; 'integer',
                            'null' =&gt; false,
                            'key' =&gt; 'primary',
                            'extra' =&gt; 'auto_increment'),
              'name' =&gt; array('type' =&gt; 'string',
                              'null' =&gt; 'false',
                              'length' =&gt; 255,
                              'unique' =&gt; true),
              'parent_id' =&gt; array('type' =&gt; 'integer'),
              'indexes' =&gt; array('PRIMARY' =&gt; array('column' =&gt; 'id',
                                                    'unique' =&gt; true),
                                 'GRP_NAME_KEY' =&gt; array('column' =&gt; 'name',
                                                         'unique' =&gt; true)));

ของใหม่อีกอย่างหนึ่งในตัวอย่างนี้คือ AclBehavior ที่จะช่วย sync ระหว่าง users, groups และ acl. แต่เท่าที่ใช้มา AclBehavior ไม่แก้ค่า alias ใน Aro ก็เลยสร้าง AclaBehavior จากการดัดแปลง AclBehavior นิดๆ หน่อยๆ โดยเพิ่มไฟล์ acla.php ลงใน folder: app/model/behaviors แบบข้างล่าง (จริงแล้วต้องเปิด <?php และปิดด้วย ?> ด้วย … แต่ว่าใส่ใน wordpress แล้วเหมือนเพี้ยนๆ ผมก็แก้ไม่เป็นด้วย.)

/* SVN FILE: $Id: acl.php 6311 2008-01-02 06:33:52Z phpnut $ */
/**
 * ACL behavior class.
 *
 * Enables objects to easily tie into an ACL system
 *
 * PHP versions 4 and 5
 *
 * CakePHP :  Rapid Development Framework 
 * Copyright 2006-2008, Cake Software Foundation, Inc.
 *                                1785 E. Sahara Avenue, Suite 490-204
 *                                Las Vegas, Nevada 89104
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @copyright        Copyright 2006-2008, Cake Software Foundation, Inc.
 * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
 * @package            cake
 * @subpackage        cake.cake.libs.model.behaviors
 * @since            CakePHP v 1.2.0.4487
 * @version            $Revision: 6311 $
 * @modifiedby        $LastChangedBy: phpnut $
 * @lastmodified    $Date: 2008-01-02 00:33:52 -0600 (Wed, 02 Jan 2008) $
 * @license            http://www.opensource.org/licenses/mit-license.php The MIT License
 */
/**
 * Short description for file
 *
 * Long description for file
 *
 * @package        cake
 * @subpackage    cake.cake.libs.model.behaviors
 */
class AclaBehavior extends ModelBehavior {

/**
 * Maps ACL type options to ACL models
 *
 * @var array
 * @access protected
 */
    var $__typeMaps = array('requester' =&gt; 'Aro', 'controlled' =&gt; 'Aco');
/**
 * Sets up the configuation for the model, and loads ACL models if they haven't been already
 *
 * @param mixed $config
 */
    function setup(&amp;$model, $config = array()) {
        if (is_string($config)) {
            $config = array('type' =&gt; $config);
        }
        $this-&gt;settings[$model-&gt;alias] = array_merge(array('type' =&gt; 'requester'), (array)$config);
        $type = $this-&gt;__typeMaps[$this-&gt;settings[$model-&gt;alias]['type']];

        if (!ClassRegistry::isKeySet($type)) {
            uses('model' . DS . 'db_acl');
            $object =&amp; new $type();
        } else {
            $object =&amp; ClassRegistry::getObject($type);
        }
        $model-&gt;{$type} =&amp; $object;
        if (!method_exists($model, 'parentNode')) {
            trigger_error("Callback parentNode() not defined in {$model-&gt;alias}", E_USER_WARNING);
        }
    }
/**
 * Retrieves the Aro/Aco node for this model
 *
 * @param mixed $ref
 * @return array
 */
    function node(&amp;$model, $ref = null) {
        $type = $this-&gt;__typeMaps[strtolower($this-&gt;settings[$model-&gt;alias]['type'])];
        if (empty($ref)) {
            $ref = array('model' =&gt; $model-&gt;alias, 'foreign_key' =&gt; $model-&gt;id);
        }

        return $model-&gt;{$type}-&gt;node($ref);
    }
/**
 * Creates a new ARO/ACO node bound to this record
 *
 * @param boolean $created True if this is a new record
 */
    function afterSave(&amp;$model, $created) {
        if ($created) {
            $type = $this-&gt;__typeMaps[strtolower($this-&gt;settings[$model-&gt;alias]['type'])];
            $parent = $model-&gt;parentNode();

            if (!empty($parent)) {
                $parent = $this-&gt;node($model, $parent);
            } else {
                $parent = null;
            }

            $acl_node_alias = null;

            if(method_exists($model, "aclNodeAlias"))
                $acl_node_alias = $model-&gt;aclNodeAlias();

            $model-&gt;{$type}-&gt;create();
            $model-&gt;{$type}-&gt;save(array(
                'parent_id'        =&gt; Set::extract($parent, "0.{$type}.id"),
                'model'            =&gt; $model-&gt;alias,
                'foreign_key'    =&gt; $model-&gt;id,
                'alias'         =&gt; $acl_node_alias
            ));
        }
    }
/**
 * Destroys the ARO/ACO node bound to the deleted record
 *
 */
    function afterDelete(&amp;$model) {
        $type = $this-&gt;__typeMaps[strtolower($this-&gt;settings[$model-&gt;alias]['type'])];
        $node = Set::extract($this-&gt;node($model), "0.{$type}.id");
        if (!empty($node)) {
            $model-&gt;{$type}-&gt;delete($node);
        }
    }
}

ไม่พอก็ยังต้องแก้ CakeShell ต่อใน folder: app/vendors/shells

แก้ user.php:

uses ('controller'.DS.'components'.DS.'auth');

class UserShell extends Shell {
    var $uses = array("User", "Group");
    function add() {
        $auth = new AuthComponent();
        $username = $this-&gt;args[0];
        $password = $auth-&gt;password($this-&gt;args[1]);
        $grp_name = $this-&gt;args[2];
        $grp = $this-&gt;get_group($grp_name);
        $data = array("User" =&gt;
                      array("username" =&gt; $username,
                            "password" =&gt; $password,
                            "group_id" =&gt; $grp["id"]));
        if($this-&gt;User-&gt;save($data))
            print "Success: $username was added\n";
        else
            print "Fail\n";
    }

    function get_group($name) {
        $data = $this-&gt;Group-&gt;findByName($name);
        if(!$data)
            return null;
        else
            return $data["Group"];

    }
}

สร้าง group.php ขึ้นมาใหม่:

class GroupShell extends Shell {

    var $uses = array("Group", "Aro");

    function add() {
        $name = $this-&gt;args[1];
        $parent_name = $this-&gt;args[0];
        if($parent_name == '/')
            $parent_id = null;
        else
            $parent_id = $this-&gt;get_parent($parent_name);
        $data = array("Group" =&gt;
                      array("parent_id" =&gt; $parent_id,
                            "name" =&gt; $name));
        if($this-&gt;Group-&gt;save($data))
            print "Success: group: $name has been added\n";
        else
            print "Fail\n";
    }

    function get_parent($name) {
        $data = $this-&gt;Group-&gt;findByName($name, null, null, False);
        if(!$data['Group']['id'])
            return null;
        else
            return $data['Group']['id'];
    }
}

ยังไม่หมดต้องมาแก้ model ต่อใน folder: app/model

แก้ user.php:

class User extends AppModel {
    var $actsAs = array('Acla');
    var $belongsTo = array('Group');

    function parentNode() {
        if(!$this-&gt;id)
            return null;

        $data = $this-&gt;read();
        if(!$data['Group']['id'])
            return null;
        else
            return array('model' =&gt; 'Group',
                         'foreign_key' =&gt; $data['Group']['id']); 
    }
}

ตามด้วยเขียน group.php ขึ้นมาใหม่:

class Group extends AppModel {
    var $actsAs = array('Acla');
    var $hasMany = array('User');
    function parentNode() {
        if(!$this-&gt;id)
            return null;
        $data = $this-&gt;read();
        if(!$data['Group']['parent_id'])
            return null;
        else
            return array('model' =&gt; 'Group',
                         'foreign_key' =&gt; $data['Group']['parent_id']);
    }

    function aclNodeAlias() {
        if(!$this-&gt;id)
            return null;
        $data = $this-&gt;read();
        if(!$data['Group']['name'])
            return null;
        else
            return $data['Group']['name'];
    }

}

จาก code ที่แก้มามากมายก็จะเริ่มเรียกใช้แล้ว. โดย cd เข้าไปใน cake/console สั่ง: ./cake schema run create users แล้วก็กด y ไปเรื่อยๆ. เพื่อที่จะ drop table: users เก่าทิ้งไป แล้วสร้าง table: users และ groups ขึ้นมาใหม่.

ตามด้วยสร้าง group ขึ้นมาใหม่แบ่งเป็น admins กับ users ตามนี้:

./cake group add ‘/’ users

./cake group add ‘/’ admins

แล้วก็ add user ไว้ทดลอง group ละ 1 user:

./cake user add myadmin mypassword admins
./cake user add myuser mypassword users

grant ให้ admins ดูได้ทั้ง site (ทุกหน้า, ทุก action):

./cake acl grant admins site ‘*’

grant ให้ users ดู Pages/display (เอาไว้ redirect มาเวลาดูหน้าอื่นไม่ได้). และ ดู Books/display1:

./cake acl grant users ‘Pages/display’ ‘*’

./cake acl grant users ‘Books/display1′ ‘*’

ถ้าลอง login ด้วย myadmin ก็จะดูได้ทุกหน้า. แต่ถ้า login ด้วย myuser ก็จะดู http://localhost/my_project/books/display2 ไม่ได้.

ก็เป็นอันว่า users แต่ละกลุ่ม ก็ดูหน้าเว็บได้ต่างๆ กันตามที่กำหมดไว้ :-).

อ้างอิง:

http://lemoncake.wordpress.com/2007/07/19/acl-with-groups/

3

CakePHP 1.2.x: Action-based ACL

หลังจากที่ลองใช้ AuthComponent อย่างง่ายไปแล้ว. ผมก็อยากจะลอง ACL (Access control list) บ้าง ไม่รู้ว่าทำถูกวิธีหรือเปล่าด้วย. ผมก็เริ่มจากแก้ app_controller.php ใน cake/libs/controller เลย

class AppController extends Controller {
    var $components = array('Auth', 'Acl');

    function beforeFilter() {
        if(isset($this-&gt;Auth)) {
            $this-&gt;Auth-&gt;authorize = "actions";
            $this-&gt;Auth-&gt;userModel = 'User';
        }
   }
}

ACL ใน CakePHP ระบุความสัมพันธ์ระหว่าง ARO และ ACO. ARO ใน blog entry นี้ก็คือ user ของเว็บ. ส่วน ACO ของ CakePHP เป็นได้หลายอย่าง ได้แก่ controller, model และ action. ในที่นี้ผมระบุว่าใช้ action $this->Auth->authorize = “actions”; โดย action ก็คงประมาณว่าระบุเลยว่า user เข้าไปใช้หน้าไหนได้บ้างเช่น ระบุว่า user1 เข้าไปใช้ http://localhost/books/display1 ได้หรือเปล่า ระบุเป็นรายหน้าเลย.

หลังจากระบุไปแบบนี้แล้วผมก็ลอง login เพื่อที่จะไปเปิดดูหน้า http://localhost/books/display1 ผมก็คือเจ๊งตอบรูปข้างล่าง:

ที่ยังใช้ไม่ได้เพราะยังไม่ได้ใส่ข้อมูลใน ACL. ดูๆ แล้วการใช้ action-based acl เหมือนจะออกแรงเยอะชอบกล :-P. เหมือนกัน. เราเพิ่ม acl ด้วย command line interface เริ่มจาก cd เข้าไปใน folder: cake/console แล้วใช้คำสั่งต่อไปนี้


./cake acl create aro ‘/’ ‘users’
./cake acl create aco ‘/’ ‘site’
./cake acl create aco ‘site’ ‘Pages’
./cake acl create aco ‘Pages’ ‘display’
./cake acl create aco ‘site’ ‘Books’
./cake acl create aco ‘Books’ ‘display1′
./cake acl create aco ‘Books’ ‘display2′
./cake acl create aco ‘site’ ‘Users’
./cake acl create aco ‘Users’ ‘login’
./cake acl create aco ‘Users’ ‘logout’
./cake acl grant ‘users’ ‘Pages/display’ ‘*’
./cake acl grant ‘users’ ‘Books/display1′ ‘*’

แล้วก็ยังไม่พอต้องเข้าไปแก้ database ตรงๆ อีกนิดหน่อย (ผมใช้ MySQL ในตัวอย่างนี้)

mysql -u<your_username> -p<your_password> my_project -e ‘set @userid = (select id from users where username = “myusername”); update aros set foreign_key = @userid, model = “User” where alias=”users”;’

เท่านี้ก็ลองเข้าไปในเว็บได้แล้ว หลังจาก login ที่หน้า http://localhost/my_project/users/login แล้ว. ก็ลองดูเว็บ page ใน http://localhost/my_project/books/display1 ก็ควรจะเข้าไปดูได้ แต่ถ้าเข้าไปใน http://localhost/my_project/books/display2 ก็จะถูก redirect กลับมาที่ http://localhost/my_project/

การใช้ acl แบบนี้ก็ยังมีปัญหาอยู่บ้าง ที่ว่าต้องมา grant สิทธิให้ user แต่ละคน กับหน้าแทบทุกหน้า เพราะ aco นึง map กับ user 1 คน … ถ้ามี user มากๆ ก็คงไม่เคยเหมาะ. ดังนั้นจึงน่าจะใช้ group เข้ามาช่วยได้ คือให้ aco เชื่อมกับ group แทน และระบุว่า group ไหน มี user คนไหนบ้าง.

อ้างอิง

http://aranworld.com/article/162/cakephp-acl-tutorial-initial-setup

5

ใช้ AuthComponent ของ CakePHP 1.2.x อย่างง่าย

หลังจากติดตั้ง CakePHP เรียบร้อยแล้ว. นอกจากนั้นเพื่อให้การทดลองเป็นได้โดยสะดวกผมคิดว่าควรจะสร้าง view กับ controller ง่ายๆ ไว้ใช้ในทดลองก่อน. จากนั้นก็สร้าง user table ผ่านทาง CakeSchema. แล้วก็เตรียม model ของ users table พร้อมด้วย add user เข้าไปลองก่อนสัก user. ขั้นตอนต่อไปก็แก้ AppController ที่อยู่ใน  cake/libs/controller/app_controller.php นิดหน่อย พอแก้แล้วหน้าตาก็จะเป็นแบบด้านล่าง:

ทีนี้ก็ลองเข้าเปิดเว็บดูหน้า http://localhost/my_project/books/display1 ถ้า app ของเราทำงานถูกต้องหน้าเว็บจะถูก redirect ไปที่ http://localhost/my_project/users/login แบบข้างล่าง

แล้วก็กรอก username: myusername และ password: mypassword (ตามที่ add ไปก่อนหน้านี้ในการเตรียม model ของ users table พร้อมด้วย add user เข้าไปลองก่อนสัก user. ) แล้วก็กด “submit” ถ้าเข้าได้ปกติมันก็ redirect มาที่ books/display1 ตามที่เข้าไว้ตอนแรก.

ถ้ามี warning ว่าเขียน app/tmp ไม่ได้ขึ้นมาแบบในตัวอย่างผมก็แก้ permission เอา โดยใช้คำสั่ง chmod -R 777 app/tmp ทำให้ทุก user เขียนได้ … อาจจะมีใช่วิธีแก้ปัญหาที่ดีแต่มันก็ทำ warning หายไป :-P.

เวลาจะ logout ก็แค่เข้าไปที่ http://localhost/my_project/users/logout

ก็เป็นอันว่าเว็บที่สร้างขึ้นมามีระบบ login แล้ว แต่ก็แยกได้แค่ว่า login หรือไม่ login. ใคร login ก็ดูได้ทุกหน้า ไม่ login ก็ดูอะไรไม่ได้. การจะทำอะไรซับซ้อนกว่านี้ใช้ Access control list (ACL) ช่วยได้.

0

ใช้ CakePHP จาก command line interface (terminal, console, etc.)

ใน CakePHP เราสามารถสั่งคำสังต่างใน shell ได้อยู่แล้ว เช่น ./cake bake (ต้องเข้า cd เข้าไปใน folder cake/console ก่อน) ที่มีไว้สร้าง controller, view และอื่นๆ อันโนมัติ.

มากไปกว่านั้นเรายังสร้างคำสั่งบน shell แบบนี้ขึ้นมาให้เองได้ง่ายๆ อีกด้วย. ในกรณีผมต้องการสร้าง shell ขึ้นมาเพื่อ encode password เพื่อใช้กับ AuthComponent ซึ่งจำเป็นต้องใช้ค่า Security.salt ใน app/config/core.php มาคำนวณด้วย ซึ่งแต่ละ app (project) สามารถแตกต่างกันได้. อย่างไรก็ตามเราไม่ต้องเขียนรายละเอียดเอง เพียงแต่เรียก function ชื่อ password จาก AuthComponent. ผมก็เลยเขียน encode.php ไว้ใน /app/vendors/shells แบบข้างล่าง.

password($this-&gt;args[0]);
    }
}
?&gt;

เวลาจะเรียกใช้งานก็ cd เข้าไปใน folder cake/console แล้วก็เรียก ./cake encode <password ที่ต้องการ encode>

อ้างอิง

  1. http://cakebaker.42dh.com/2007/05/07/writing-a-custom-cakephp-console-script/
  2. http://api.cakephp.org/1.2/cake_8php-source.html
3

เริ่มต้นกับ CakePHP

ผมเขียน entry นี้เพื่อที่จะเป็น tuturial เบื้องต้นให้กับ entry เกี่ยวกับ Access control list อีกที โดยดัดแปลง เพิ่มต้มมาจาก http://blog.vee-u.com/2008/02/23/cakephp_acl/ มาเป็นส่วนมาก

เริ่มจากเราไป download CakePHP 1.2.6311B มาจาก http://cakeforge.org/frs/download.php/595/cake_1.2.0.6311-beta.tar.bz2 แล้วก็เอาแกะหีบห่อด้วยคำสั่ง tar xjvf cake_1.2.0.6311-beta.tar.bz2 เราก็จะได้ folder (directory) ชื่อ cake_1.2.0.6311-beta ขึ้นมา. เพื่อที่จะได้เข้าไปใช้ง่ายๆ เราก็สามารถเปลี่ยนชื่อ folder ก่อนได้ เช่น เปลี่ยนไปเป็นชื่อ my_project ด้วยคำสั่ง mv cake_1.2.0.6311-beta my_project เป็นต้น.

เวลาลง CakePHP แล้วต้องเปลี่ยนค่า Salt คืออะไรก็ไม่รู้อะใน app/config/core.php


Configure::write('Security.salt', 'เปลี่ยนค่าตรงนี้');  

แล้วก็ตั้งค่า database ใน app/config/database.php แต่ว่าทีแรกไม่มีไฟล์ database.php เราก็ copy มาจาก database.php.default  (ด้วยคำสั่ง cp app/config/database.php.default app/config/database.php) ได้เลย แล้วก็แก้ค่าข้างในเอา. ถ้าไม่มี database ก็อาจจะไปสร้างรอไว้ก่อน เช่น สร้าง database ด้วยคำสั่ง mysql -umyuser -pmypassword -e ‘create database my_project’ เป็นต้น

class DATABASE_CONFIG {
   var $default = array(
     'driver' =&gt; 'mysql',
     'persistent' =&gt; false,
     'host' =&gt; 'localhost',
     'port' =&gt; '',
     'login' =&gt; 'ชื่อผู้ใช้ของ database',
     'password' =&gt; 'password',
     'database' =&gt; 'ชื่อ database',
     'schema' =&gt; '',
     'prefix' =&gt; '',
     'encoding' =&gt; ''
   );
   ...
}

จากนั้นถ้าจะใช้ acl ก็ต้องแบบแก้ source code นิดหน่อย ที่ดูแล้วคงเป็น bug (ที่ผม CakePHP ที่ผมนำมาใช้เป็น beta version ด้วย) แก้แบบไม่ยากไปตามเว็บนี้ http://seeknstrike.net/archives/20
เพียงแต่ใส่ uses(’string’) เข้าไปในบรรทัดล่างจาก uses(’set’) ในไฟล์
cake/libs/model/datasources/dbo_source.php ตามนี้

uses('set');
uses('string'); // เพิ่มเข้าไป

ตอนนี้ code ส่วน CakePHP ก็พร้อมแล้ว. แต่ว่า Apache กับ Ubuntu ก็ต้องแก้ๆ หน่อย. ปกติ mod_rewrite ที่จำเป็นสำหรับ CakePHP มากๆ ไม่ได้ถูก enable มาให้แต่แรกเราก็เลยต้องไปแก้. วิธีแก้สามารถอ่านเพิ่มเติมได้ที่ blog entry http://bact.blogspot.com/2008/04/enable-modrewrite-in-apache.html ของ bact. อย่างไรก็ตามผมก็จะเขียนสั้นๆ เท่าที่ผมเข้าใจไว้ด้วย.

เริ่มจากสั่ง sudo a2enmod rewrite

a2enmod เป็นคำสั่งของ Debian ที่ Ubuntu ก็รับมาด้วย เอาไว้แก้ configuration ให้ Apache เรียก mod_rewrite ขั้นตอนต่อไปก็แก้ไฟล์  /etc/apache2/sites-enabled/000-default ใน tag  <Directory /var/www/> …. </Directory> มีอยู่บรรทัดนึงเขียนว่า  AllowOverride None เราก็ไปแก้เป็น AllowOverride All เสีย. เพื่อที่ CakePHP จะได้ควบคุม mod_rewrite จากไฟล์ .htaccess ได้. หลังจากนั้นก็ restart Apache ด้วยคำสั่ง sudo /etc/init.d/apache restart ก็น่าจะพอใช้ได้.

หลังจากนั้นก็ย้าย my_project เข้าไปใน /var/www ( ด้วยคำสั่ง mv my_project /var/www ). และแก้ folder ของ tmp เสียหน่อย ด้วยคำสั่ง sudo chown -R www-data:www-data /var/www/my_project/app/tmp

เท่านี้ก็น่าจะพอเปิดเว็บดูได้แล้ว โดยเข้าไปดูที่ url: http://localhost/my_project ได้เลย

ถ้าไม่มีข้อความเตือนความผิดพลาด ก็เป็นสัญญาณบอกแล้วว่าพร้อมที่จะเริ่มใช้ CakePHP ในขั้นต่อไปแล้ว ;-).

ป.ล. entry หายไปซะงั้นงงเลย T_T ต้องกลับมา post ใหม่