Skip to content

Instantly share code, notes, and snippets.

@obiconbig
Created March 9, 2013 03:43
Show Gist options
  • Select an option

  • Save obiconbig/5122400 to your computer and use it in GitHub Desktop.

Select an option

Save obiconbig/5122400 to your computer and use it in GitHub Desktop.
How to use Doctrine 2.3.x for CodeIgniter 2.1.3

How to use Doctrine 2.3.x for CodeIgniter 2.1.3

Environment

บทความนี้จะ setup codeigniter 2.1 เพื่อให้ใช้งาน Doctrine 2.3.0 โดยใช้

OS: Windows 7
Server: WAMP (Apache: 2.2.22, PHP 5.3.13, MySql 5.2.24)

เป็นรูปแบการใช้งาน Doctrine ผ่าน hook ข้อดีก็คือเอาออกได้ทุกเวลา ข้อเสียคือเอาออก app ก็ error ทั้ง App ไม่มีการ buidin ลงไป หากต้องการที่จะใช้งานแบบ Library ให้อ่านที่ Integrating with CodeIgniter

Install the CodeIgniter

ขั้นแรกให้เราเอา code ของ Codeigniter มาก่อน โดย

  • fork Codeigniter มาจาก Github เมื่อได้มาให้ set brance เป็น 2.1 stable แล้ว clone ลงเครื่อง หรือ
  • download มาจากเว็บของ Codeigniter สามารถทำได้ทั้งสองวิธี และไม่มีวิธีใหนดีกว่ากัน เพราะได้ source ออกมาเหมือนกัน (ที่ทำใช้ fork มาเพราะจะได้มีตัวอย่างเก็บไว้เป็น path ให้ดูบน git ให้ด้วย)

Setup vhost

ในการติดตั้งครั้งนี้คงอยากรันเพื่อทดสอบว่าทำงานได้หรือไม่ ให้ setup vhost ไว้ก่อนเลยล่วงหน้า โดยการ set virtual host ให้ webserver รัน CodeIgniter ได้ตัวอย่างเช่น

Add local DNS ลงใน

C:\Windows\System32\drivers\etc\hosts

ว่า

127.0.0.1       codeigniter-doctrine.local

เพิ่ม config นี้ลงใน config ของ apache (หากงงให้หาวิธีการ setup virtual host ของ apache)

<virtualhost *:80>
    DocumentRoot "C:/wamp/www/codeigniter-doctrine-2.3.0"
    ServerName codeigniter-doctrine.local
    ServerAlias codeigniter-doctrine.local
</virtualhost>

ให้ลองเข้า

http://codeigniter-doctrine.local/

ผ่านเว็บ browser หากได้ก็จะเจอหน้า Welcome to CodeIgniter!

Install the doctrine

จากนั้นเราจะติดตั้ง Doctrine ลงมา โดยเราเลือก version 2.3.0(ล่าสุดตอนที่เขียน) ลงมาด้วยการใช้ composer ช่วยเรา เพราะเวลา Install แล้ว composert จะทำ autoload library ให้เราด้วย

เข้าไปที่ codeigniter folder ที่เราได้มา แล้วสร้าง file ชื่อ composer.json แล้วเขียนใน file แบบนี้

{
    "require": {
        "doctrine/orm": "2.3.0"
    }
}

เมื่อได้ file composer ว่าเราต้องการใช้ doctrine เราก็ไป get composer ด้วยการเปิด command line แล้วเข้าไปที่ folder ที่เราทำงานอยู่นี้

แล้วเรียก composer มาใช้งานด้วย

curl -s https://getcomposer.org/installer | php

หากเครื่องไม่มี CURL ติดตั้งไว้ให้ใช้ PHP แทนก็ได้(อันนี้ยังไงก็ติดตั้งไว้แน่นอน)

php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"

เมื่อได้ composer มาแล้วให้เรา run composer ด้วย

php composer.phar install

รอสักพัก composer จะ download Doctrine ORM และสิ่งที่ Doctrine ต้องการทั้งหมดให้ รวมทั้งทำ autoload file ให้เราด้วย

folder ที่ composer ติดตั้งไว้นั้นจะ default ไว้ที่ folder vendor ตรงจุดที่ composer.phar ทำงาน

จากตรงนี้เราก็ได้ library ของทั้ง Codeigniter และ Doctrine 2.3.0 มาใช้งานแล้ว แต่ว่ายังไม่ได้เขียนให้ Codeigniter ใช้งาน Doctrine

Load Doctrine

ขั้นตอนต่อไปเราจะทำให้ Codeigniter ใช้งาน Doctrine ได้ด้วยการเขียน hook ให้ Codeigniter ไปเรียก library ของ Doctrine มาใช้งาน

ในกรณีนี้เราใช้งาน composer ให้ install Doctrine มาให้เรา แล้ว composer ได้ทำ file autoload ให้เราด้วยเราแค่เรียก autoload ตัวนี้มาใช้งานก็ได้สามาถที่จะใช้งานได้แล้ว

แนวทางของเราก็คือเราจะเขียน hook ให้กับ Codeigniter ไปเรียก autoload ของ composer ขั้นตอนตามนี้

enable hook in codeigniter-doctrine-2.3.0\application\config.php

/*
 |--------------------------------------------------------------------------
 | Enable/Disable System Hooks
 |--------------------------------------------------------------------------
 |
 | If you would like to use the 'hooks' feature you must enable it by
 | setting this variable to TRUE (boolean).  See the user guide for details.
 |
 */
$config['enable_hooks'] = TRUE;

add hook โดยการเพิ่มลงใน codeigniter-doctrine-2.3.0\application\hooks.php ในช่วง pre_controller เราจะตั้งชื่อว่า load_composer.php และมี function ชื่อ load_composer

$hook['pre_controller'] = array(
    'function' => 'load_composer',
    'filename' => 'load_composer.php',
    'filepath' => 'hooks'
);

สร้าง hook ใน codeigniter-doctrine-2.3.0\application\hooks ชื่อ load_composer.php มีเนื้อ file คือ

/**
 * Include Composer Autoload
 * 
 * @return void
 */
function load_composer(){
    require_once FCPATH . "vendor/autoload.php";
}

Config doctrine connection

เมื่อถึงตรงนี้ เราจะสามารถใช้งาน Doctrine ได้แล้ว ให้เราทำ hook เพื่อ config path ของ Entities ต่างๆของเราด้วย

add hook โดยการเพิ่มลงใน codeigniter-doctrine-2.3.0\application\hooks.php ในช่วง pre_controller ต่อจากของเดิม หากเรา hook ที่เดียวกันมากกว่า 1 อันก็ให้สร้างเป็น array แทน เราจะตั้งชื่อว่า doctrine_connection_configuration.php และมี function ชื่อ doctrine_connection_configuration()

$hook['pre_controller'][] = array(
    'function' => 'load_composer',
    'filename' => 'load_composer.php',
    'filepath' => 'hooks'
);

$hook['pre_controller'][] = array(
    'function' => 'doctrine_connection_configuration',
    'filename' => 'doctrine_connection_configuration.php',
    'filepath' => 'hooks'
);

สร้าง folder Entiries ใน applicaion เพื่อเก็บ Entities (ไม่ใช้ folder models เพราะลดการงง)

สร้าง hook ใน codeigniter-doctrine-2.3.0\application\hooks ชื่อ doctrine_connection_configuration.php มีเนื้อ file คือ

<?php

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;

/**
 * Config the Dcotrine connection
 * 
 * @return array return config at index 0 and entities manager at index 1
 */
function doctrine_connection_configuration(){

    include_once(APPPATH . 'config/database.php');

    $paths = array(APPPATH . "Entities");
    $isDevMode = ENVIRONMENT == 'development';

    // the connection configuration
    $dbParams = array(
        'driver'   => 'pdo_' . $db[$active_group]['dbdriver'],
        'user'     => $db[$active_group]['username'],
        'password' => $db[$active_group]['password'],
        'dbname'   => $db[$active_group]['database'],
    );

    $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
    $em = EntityManager::create($dbParams, $config);

    return array($config, $em);
}

หากต้องการให้ Entities อยู่นอก application เราสามารถ set Entities ให้อยู่ที่อื่นได้ ตาม path ที่ต้องการได้ (กรณีอยากให้ หลายๆ application อยู่ใน Entities เดียวกัน)

หากต้องการการปรับแต่ง config ที่มากกว่านี้ สามารถดูได้ที่ Doctrine configuration reference.

Doctrine CLI

เวลาที่จะรัน CLI ของ Doctrine บน LINUX, UNIX เราจะรันที่

vendor/bin/doctrine

หรือ Windows

vendor\bin\doctrine\doctrine.php.bat

Doctrine จะทำการหา file cli-config.php ตรงจุดที่เรารันอยู่เพราะฉนั้นต้องหาที่อยู่ให้ file นี้ ในที่นี้จะให้อยู่ที่

application\bin\cli-config.php

โดยข้างในคือ

<?php

define('ENVIRONMENT', 'development');

define('APPPATH', dirname(getcwd()) . '/');
define('BASEPATH', dirname(APPPATH) . '/');

include_once(APPPATH . 'hooks/doctrine_connection_configuration.php');

list($config, $em) = doctrine_connection_configuration();

$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
    'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
    'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));

หาก นำ file ไปอยู่ที่อื่น ก็ให้ set APPPATH และ BASEPATH ให้ตรงตามที่ต้องการจะ run ก็จะรันได้

Test CLI

มาทดสองตัวอย่างของ Doctrine กัน :)

สร้าง Article.php ใน \application\Entities\

<?php
/** @Entity */
class Article
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @Column(type="string") */
    private $headline;

    /** @ManyToOne(targetEntity="User") */
    private $author;

    /** @OneToMany(targetEntity="Comment", mappedBy="article") */
    private $comments;

    /** @Column(type="boolean") */
    private $isDisable;

    public function __construct() {
        $this->comments = new ArrayCollection();
    }

    public function getAuthor() { return $this->author; }
    public function getComments() { return $this->comments; }
}

จากนั้นเข้า command line ไปยัง

\application\bin\

จะเห็น cli-config.php ที่เราได้ทำการเขียนไว้ เราจะทำการรัน cli จากตรงนี้โดยใช้ command

C:\wamp\www\codeigniter-doctrine-2.3.0\application\bin>..\..\vendor\bin\doctrine.php.bat orm:generate-entities ..\..\application\Entities

Doctrine จะช่วยสร้าง set get ให้เราจนได้เป็นแบบนี้

<?php
/** @Entity */
class Article
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @Column(type="string") */
    private $headline;

    /** @ManyToOne(targetEntity="User") */
    private $author;

    /** @OneToMany(targetEntity="Comment", mappedBy="article") */
    private $comments;

    /** @Column(type="boolean") */
    private $isDisable;

    public function __construct() {
        $this->comments = new ArrayCollection();
    }

    public function getAuthor() { return $this->author; }
    public function getComments() { return $this->comments; }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set headline
     *
     * @param string $headline
     * @return Article
     */
    public function setHeadline($headline)
    {
        $this->headline = $headline;
    
        return $this;
    }

    /**
     * Get headline
     *
     * @return string 
     */
    public function getHeadline()
    {
        return $this->headline;
    }

    /**
     * Set isDisable
     *
     * @param boolean $isDisable
     * @return Article
     */
    public function setIsDisable($isDisable)
    {
        $this->isDisable = $isDisable;
    
        return $this;
    }

    /**
     * Get isDisable
     *
     * @return boolean 
     */
    public function getIsDisable()
    {
        return $this->isDisable;
    }

    /**
     * Set author
     *
     * @param User $author
     * @return Article
     */
    public function setAuthor(\User $author = null)
    {
        $this->author = $author;
    
        return $this;
    }

    /**
     * Add comments
     *
     * @param Comment $comments
     * @return Article
     */
    public function addComment(\Comment $comments)
    {
        $this->comments[] = $comments;
    
        return $this;
    }

    /**
     * Remove comments
     *
     * @param Comment $comments
     */
    public function removeComment(\Comment $comments)
    {
        $this->comments->removeElement($comments);
    }
}

ถือว่าสามารถใช้งาน CLI ได้

Unix socket error in MAMP

หากคุณใช้งาน MAMP ใน OSX คุณต้องปรับตรงนี้เพิ่มเติมด้วย

ใน codeigniter project/config/database.php ให้เติม unix sockpath ลงไปด้วย เพราะ MAMP ย้ายจาก /var/mysql/mysql.sock ไปไว้ที่ /Applications/MAMP/tmp/mysql/mysql.sock ตัวอย่างคือ

...
...
...
$active_group = ENVIRONMENT;
$active_record = TRUE;


$db['development']['hostname'] = 'localhost';
$db['development']['username'] = 'root';
$db['development']['password'] = 'root';
$db['development']['database'] = 'gopress';
$db['development']['dbdriver'] = 'mysql';
$db['development']['dbprefix'] = '';
$db['development']['pconnect'] = TRUE;
$db['development']['db_debug'] = TRUE;
$db['development']['cache_on'] = FALSE;
$db['development']['cachedir'] = '';
$db['development']['char_set'] = 'utf8';
$db['development']['dbcollat'] = 'utf8_general_ci';
$db['development']['swap_pre'] = '';
$db['development']['autoinit'] = TRUE;
$db['development']['stricton'] = FALSE;
$db['development']['unix_socket'] = '/Applications/MAMP/tmp/mysql/mysql.sock';


$db['production']['hostname'] = 'localhost';
$db['production']['username'] = '';
$db['production']['password'] = '';
$db['production']['database'] = '';
$db['production']['dbdriver'] = 'mysql';
$db['production']['dbprefix'] = '';
$db['production']['pconnect'] = TRUE;
$db['production']['db_debug'] = TRUE;
$db['production']['cache_on'] = FALSE;
$db['production']['cachedir'] = '';
$db['production']['char_set'] = 'utf8';
$db['production']['dbcollat'] = 'utf8_general_ci';
$db['production']['swap_pre'] = '';
$db['production']['autoinit'] = TRUE;
$db['production']['stricton'] = FALSE;
$db['production']['unix_socket'] = '/var/mysql/mysql.sock';
...
...
...

จากนั้นไปเพิ่ม unix socket ใน function doctrine_connection_configuration() ตัวแปล $dbParams ของ doctrine

...
...
...
    // the connection configuration
    $dbParams = array(
        'driver' => 'pdo_' . $db[$active_group]['dbdriver'],
        'user' => $db[$active_group]['username'],
        'password' => $db[$active_group]['password'],
        'dbname' => $db[$active_group]['database'],
        'unix_socket' => $db[$active_group]['unix_socket'],
    );
...
...
...

เราก็จะต่อผ่าน socket path อื่น ได้

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment