Category Archive Yii

Byphunsanit

IIS: การตั้ง Virtual Directory

iis เดิมมีเว็บที่เป็น c# อยู่แล้วและไม่สะดวกที่จะเพิ่ม domain name เข้าไปใหม่ จะตั้งเป็น site ให้ใช้อีก port ก็ติด firewall ที่ยอมให้ใช้ port 80 เท่านั้น และเพื่อความปลอดภัย framework อย่าง laravel ไม่ควรวาง folder ให้สามารถเรียกใช้ php ไฟล์อื่นได้นอกจาก /public/index.php จึงเลือกที่ใช้วิธี Virtual Directory คือ การสร้าง folder ใน url ให้ชี้ไปอีก folder ที่อยู่นอก C:\inetpub\wwwroot

การตั้ง Virtual Directory

  1. เปิดโปรแกรม Internet Information Services (IIS) Manager
  2. คลิกขวาที่ site ที่ต้องการ เช่น Default Web Site
  3. Add Virtual Directory
    Alias
    คือ folder จำลอง เช่น punpun_uat
    Physical path:
    คือ path จริง ที่ทำ shortcut ชี้ไปหา เช่น C:\www\punpun_v1_uat
  4. (ไม่จำเป็น) คลิกที่ site หรือ server แล้ว restart
  5. ทดสอบโดยเรียก url เช่น http://localhost/punpun_uat

วิธีนี้จะมีข้อดีคือ

  1. สามารถติดตั้งหลายเว็บ โดยใช้ domain และ port เดียวกันได้
  2. สามารถควบคุมการเข้าถึงไฟล์ที่ไม่ต้องการได้เช่น ถ้าวาง file ของ larave ไว้ใน C:\inetpub\wwwroot ตามปกติ ผู้ไม่หวังดีสามารถเรียกใช้ไฟล์อื่นๆ นอกจากไฟล์ /public/index.php ได้โดยตรงเช่น ไฟล์ php ที่สามารถ upload ไฟล์ได้โดยไม่มีการตรวจสอบสิทธิทำให้ไม่ปลอดภัย
  3. สามารถรัน code เดียวกันโดยใช้ php หลาย version หรือมี config คนละแบบได้โดยใช้วิธี การติดตั้ง PHP หลายเวอร์ชั่น บน IIS
  4. ซ่อน หรือย้าย folder ที่เก็บงานไปไว้ไดร์อื่น
Byphunsanit

Yii2: pretty urls

โดยปกติ url ของ yii2 จะเป็นแบบ http://localhost/BanBan/1/backend/web/index.php?r=gii%2Fdefault%2Fview&id=model ซึ่งยากที่ user ทั่วไปจะจำ ทำให้ google มองว่าเว็บเราใช้งานยากจึงไม่เป็นผลดีในการทำ seo เราจึงต้องแปลง query string ให้เป็นรูปแบบ pretty urls ที่จะจำได้ง่ายและสวยงามกว่า พี่เกิ๊ลชอบ

  1. เปิดไฟล์ config\main.php จากนั้นเพิ่ม
        'components' => [
    ...
            'urlManager' => [
                'enablePrettyUrl' => true,
                'showScriptName' => false,
            ],
    ...
        ],
  2. จากนั้นสร้างไฟล์
    RewriteEngine on
    
    # if a directory or a file exists, use it directly
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    
    # otherwise forward it to index.php
    RewriteRule . index.php

    save ไปที่ backend\web และ frontend\web

เท่านี้จาก url ยาวๆ ก็จะสวยงามขึ้นกลายเป็น http://localhost/BanBan/1/backend/web/gii/model อ่านง่ายขึ้นเยอะเลย

Byphunsanit

Laravel 5 VS Yii 2 เลือกตัวไหนดี

ช่วงนี้เริ่มโปรเจคใหม่ ด้วยความที่ pm อยากจะให้ใช้ framework ตัวใหม่แทน yii2 เลยเลือกตัวยอดนิยมอีกตัวมาคือ laravel 5 ซึ่งถ้าดูใน trends ที่นิยมๆกันคือ CodeIgniter 3, joomla 3, Laravel 5, wordpress 4, Yii 2 เจ้าลั๊ลลาเวล นี่มาแรงจริงๆ

เพราะว่าคุ้นกับเจ้า yii 2 ที่สุดเลยจะเปรียบเทียบเอาง่ายๆ

  • การติดตั้ง yii2 สามารถใช้ composer ได้ และถ้าไม่มีเน็ตก็โหลดที่เป็น zip ไฟล์มาใช้ได้ แต่ laravel 5 ออกแบบให้ใช้ composer เท่านั้น
  • การใช้ command ทั้งคู่ต้องใช้ command ในการทำสิ่งต่างๆ ตั้งแต่การติดตั้งแต่ laravel 5 จะใช้เยอะกว่ามาก อย่างการ update route cache
  • การ config ตัว Yii2 จะมีความซับซ้อนยิ่งเป็น advance template จะมีการ overwrite ตามลำดับคือ common\config > site\config แล้วยังมีแยก -local สำหรับ config ที่ไม่ต้องการให้ git สนใจ เช่น connection database ในเครื่อง ไม่ต้องการให้ upload เข้าไปใน production แต่คนที่มาจับใหม่ๆ จะงงกับมันมาก ส่วน Laravel 5 ตัว config จะกระจายอยู่หลายที่ ถึงจะมีโพลเดอร์ \config แต่ตัว route ดันอยู่ใน \app\Http\routes.php แต่ config ที่เป็น local อยู่ใน .env ใช้ครั้งแรกก็งงว่าทำไม่ config แล้วมันใช้ไม่ได้
  • ด้าน structure folder ตัว Yii2 จะแยก backend / frontens / common / model / controllers / view แน่นอน เพราะว่าจะเอาไปสร้าง route ส่วน laravel 5 จะบังคับบางส่วนแต่ส่วนใหญ่จะเป็นอิสระตามแต่ท่านๆ จะวางโครงสร้างเอาเอง ขนาด model ก็ไม่บังคับว่าจะไว้ที่ไหน แค่มีตัวอย่าง \app\User.php ไว้ตัวเดียวเท่านั้น
  • ขนาดติดตั้ง Yii2 จะมีแทบทุกอย่างติดมาสำหรับงานเว็บทั่วๆไป ถ้าเอามาทำ api อาจจะต้องเอาบางอย่างที่เกินจำเป็นออก แต่ laravel 5 แทบไม่มีอะไรเลยแม่แต่ login, css, framework, grid list, form generator ต้องมาลงเองผ่านcomposer และ command
  • การลง component ต่างก็แนะนำให้ใช้ composer ทั้งคู่ แต่ การ configure ตัว laravel 5 ส่วนใหญ่จะต้องใช้ command คู่กันไปด้วย และต้องแก้หลายจุดมากกว่า YII ที่มักแค่เพิ่มรายการใน config ในไฟล์ใดไฟล์หนึ่งเท่านั้น
  • การสร้างไฟล์ใหม่ Yii จะมี Gii ให้ถ้าสร้างตารางเสร็จเรียบร้อยแล้ว มันจะสร้างให้ครบทั้ง controller, model, view ส่วน laravel 5 จะต่างกันออกไป เหมือนจะให้สร้างโครงสร้างในตัวมันเองแล้ว command สร้างตารางใน database การสร้าง model มันแทบจะสร้างแค่ชื่อ class ให้เท่านั้น
  • ตัว model ตัว laravel 5 ทำออกมาได้ง่ายมาก เพราะว่าไม่ต้องใส่ field / search condition อะไรเลย ใส่แค่ชื่อตารางมันก็ใช้ insert, delete, update ได้แล้ว (แต่อย่าลืมว่า gii ของ yii สร้างพวกนี้ให้แค่คลิก)
  • ด้านคู่มือมีทั้งคู่ แต่ yii2 ได้เปรียบตรงที่ถ้าดูรายละเอียดถึงระดับ class ทำไว้ละเอียดมาก ไม่ใช้แค่ชื่อ class กับอาร์กิวเมนต์ และจะได้อะไรออกมา แต่หลายๆจุดมีตัวอย่างให้ดูด้วย และเพราะให้มาแบบจัดเต็ม ทำให้มีเยอะจนบางครั้งก็สับสนว่าจะใช้ตัวไหนดี อย่าง grid ก็มีแบบของมันเอง กับแบบ bootstrap การสร้างฟอร์มก็มีให้เลือก สร้างจาก database, array ให้เลือก เป็นทั้งข้อดีและข้อเสีย
  • theme อันนี้ laravel 5 ดีกว่ามากต้องยกให้ blae ในด้านการ reused ส่วนต่างๆ ที่จับ mixed ได้ง่ายๆ กว่ามาก

สรุป ง่ายๆละกัน Yii 2 เหมาะกับงานที่ต้องการไปตามกรอบที่มันมีไว้แล้วจริงๆ เหมาะกับงานทั่วๆไป พวก backend ระบบต่างๆ ส่วน laravel 5 มันเหมาะกับเริ่มงานที่ต้องการปรับแต่งเอง มีเวลาที่จะปรับให้เหมาะกับงานที่ทำ มี tools หรือ library ที่ใช้อยู่เดิมเอาเข้ามาใช้

Byphunsanit

YII2: formatter

ถ้าทำระบบที่ออกแบบให้ลูกค้าจากต่างประเทศมาใช้งานได้อย่างสดวก อาจจะต้องเปลี่ยนการแสดงผลให้ตามความเคยชินของลูกค้า อย่างเช่น วันที่ คนไทยจะใช้ d/M/Y คือ วันที่/เดือน/ปี แต่คนอเมริกันจะใช้ M/d/Y คือ เดือนมาก่อน/วันที่/ปี แต่อัฟริการใต้และฐานข้อมูลส่วนใหญจะเก็บแบบ Y-M-d คือ ปี-เดือน-วัน จะสามารเรียงข้อมูลตามวันเวลา ได้ง่ายที่สุด แต่ไม่นิยมใช้กันในชีวิตประจำวัน ซึ่งถ้าไม่สังเกตุดีๆ อาจจะเข้าใจกันผิดได้

Yii2 ได้อำนวยความสดวกในส่วนนี้ให้โดยเพียงแค่ไปที่ไฟล์ \common\config\main.php เพิ่ม

    'components' => [
...
        'formatter' => [
            'currencyCode' => 'THB',
            'dateFormat' => 'd/M/Y',
            'datetimeFormat' => 'd/M/Y H:i:s',
            'defaultTimeZone' => 'Asia/Bangkok',
            'locale' => 'th-TH',
            'sizeFormatBase' => 1024,
            'timeFormat' => 'H:i:s',
        ],
...

ก็จะสามารถใช้ความสามารถนี้ได้

เริ่มจากวันและเวลากันก่อน

$date = date('c');
echo '<br>$date = '.$date,
'<br>',
'<br>dateFormat = '.Yii::$app->formatter->dateFormat,
'<br>asDate($date) = '.Yii::$app->formatter->asDate($date),
'<br>asDate($date, \'Y-M-d\') = '.Yii::$app->formatter->asDate($date, 'Y-M-d'),
'<br>',
'<br>datetimeFormat = '.Yii::$app->formatter->datetimeFormat,
'<br>asDatetime($date) = '.Yii::$app->formatter->asDatetime($date),
'<br>asTimestamp($date) = '.Yii::$app->formatter->asTimestamp($date);

ผลที่ได้คือ
$date = 2016-05-26T19:41:22+02:00

dateFormat = d/M/Y
asDate($date) = 26/5/2016
asDate($date, ‘Y-M-d’) = 2016-5-26

datetimeFormat = d/M/Y H:i:s
asDatetime($date) = 26/5/2016 19:41:22
asTimestamp($date) = 1464284482

เงินก็สามารถเปลี่ยนการแสดงผลได้เหมือนกัน

$value = 910097693;
echo '<br>$value = '.$value,
'<br>',
'<br>currencyCode = '.Yii::$app->formatter->currencyCode,
'<br>asCurrency($value) = '.Yii::$app->formatter->asCurrency($value),
'<br>asCurrency($value, \'USD\') = '.Yii::$app->formatter->asCurrency($value, 'USD');

ผลที่ได้คือ
$value = 910097693

currencyCode = THB
asCurrency($value) = THB 910,097,693.00
asCurrency($value, ‘USD’) = USD 910,097,693.00

ขนาดไฟล์ก็สามารถแปลงได้เหมือนกัน

$value = 910097693;
echo '<br>$value = '.$value,
'<br>',
'<br>sizeFormatBase = '.Yii::$app->formatter->sizeFormatBase,
'<br>asSize($value) = '.Yii::$app->formatter->asSize($value),
'<br>asShortSize($value) = '.Yii::$app->formatter->asShortSize($value),
'<br>asSize($value, 4) = '.Yii::$app->formatter->asSize($value, 4);

ผลที่ได้คือ
$value = 910097693

sizeFormatBase = 1024
asSize($value) = 867.94 mebibytes
asShortSize($value) = 867.94 MiB
asSize($value, 4) = 867.9368 mebibytes

อ่านเพิ่มเติม

Byphunsanit

YII2 : RBAC สมาชิก กลุ่มและสิทธิ

yii2 มีระบบจัดการสิทธิต่างๆ เรียกว่า Role Based Access Control (RBAC) โดยสามารถกำหนดสิทธิได้โดยใช้ กลุ่ม (role) และกำหนดสิทธิให้รายคนได้ เพื่อที่จะควบคุมให้แต่ละคนสามารถเข้าไปใช้เมนูต่างๆ ได้ตามความเหมาะสม เราคงไม่ต้องการให้ใครก็ได้ แต่มาเปลี่ยนข้อมูล ตั้งค่าของระบบใหม่ หรือลบงานของคนอื่นออกไปโดยไม่มีเหตุอันควร เริ่มจากการกำหนด role โดย

  1. เพิ่ม component authManager ในไฟล์ common/config/main.php
        'components' => [
    ...
            'authManager' => [
                'class' => 'yii\rbac\DbManager',
            ],
    ...
        ],
    
  2. สร้างตาราง auth ก่อนโดย command
    yii migrate –migrationPath=@yii/rbac/migrations/
    

    ตอบ yes รอจนเห็น Migrated up successfully. จะเป็นการสร้างตาราง auth_assignment, auth_item, auth_item_child และ auth_rule
    ถ้าเห็น Exception ‘yii\base\InvalidConfigException’ with message ‘The configuration for the “user” component must contain a “class” element.’ ให้ไป comment config ทีระบุ user components ออกไปก่อน แลัวลองใหม่

  3. สร้างไฟล์ใหม่ /backend/controllers/RbacController.php
    <?php
    namespace backend\controllers;
    
    use Yii;
    use yii\helpers\Html;
    use yii\web\Controller;
    
    /**
     * Site controller
     */
    class RbacController extends Controller
    {
    
        private $auth = [];
    
        public function init()
        {
            parent::init();
    
            $this->auth = Yii::$app->authManager;
        }
    
        public function actionIndex()
        {
            return '<h1>RBAC Snippets</h1>' .
            '<ul>' .
            '<li>' . html::a('Create Role', 'createparentsrole', ['target' => 't1']) . '</li>' .
            '<li>' . html::a('Set Child Role', 'childrole', ['target' => 't2']) . '</li>' .
            '<li>' . html::a('Assign To User', 'assignrole', ['target' => 't3']) . '</li>' .
                '</ul>';
        }
    
        public function actionAssignrole()
        {
            $administratorsRole = $this->auth->getRole('administrators');
            if (is_null($this->auth->getAssignment('administrators', 1))) {
                $this->auth->assign($administratorsRole, 1);
            }
    
            $staffsRole = $this->auth->getRole('staffs');
            if (is_null($this->auth->getAssignment('staffs', 1))) {
                $this->auth->assign($staffsRole, 1);
            }
    
            /*
            show all roles from table auth_assignment
             */
            return '<h1>Assignments of user id = 1</h1>' .
            '<pre>' . print_r($this->auth->getAssignments(1), true) . '</pre>';
        }
    
        public function actionChildrole()
        {
            $administratorsRole = $this->auth->getRole('administrators');
            $guestsRole = $this->auth->getRole('guests');
    
            if (is_null($this->auth->hasChild($administratorsRole, $guestsRole))) {
                $this->auth->addChild($administratorsRole, $guestsRole);
            }
    
            /*
            show all roles from table auth_item_child
             */
            return '<h1>Children of "administrators" Role</h1>' .
            '<pre>' . print_r($this->auth->getChildren('administrators'), true) . '</pre>';
        }
    
        public function actionCreateparentsrole()
        {
            $roles = [
                'administrators',
                'guests',
                'staffs',
                'users',
            ];
    
            foreach ($roles as $role) {
                if (is_null($this->auth->getRole($role))) {
                    $newRole = $this->auth->createRole($role);
    
                    $newRole->description = 'parent role of ' . $role;
    
                    $this->auth->add($newRole);
                }
            }
    
            /*
            show all roles from table auth_item (type = 1)
             */
            return '<h1>Lists Of All Roles</h1>' .
            '<pre>' . print_r($this->auth->getRoles(), true) . '</pre>';
    
        }
    
    }
    

    ลองเรียก link http://localhost/advanced/backend/web/rbac และดูความเปลี่ยนแปลงตามลำดับ

ดูเพิ่มเติม