ความคืบหน้า PHP Hoffman Framework (3)

จากตอนที่แล้ว ความคืบหน้า PHP Hoffman Framework (2) ได้ปรับเปลี่ยนการ config จาก ini มาเป็น array ใน php แทนแล้ว ได้ทำการปรับ routing จากตั้งใน xml มาเป็น array ใน php เช่นกัน ทำให้ลดเวลาในการ parse ข้อมูลได้

เป็นแบบนี้ครับ

$Rounting['keywords'] = array(
    ':controller' => '[a-zA-Z][a-zA-Z0-9_\-]*', // Default
    ':action' => '[a-zA-Z][a-zA-Z0-9_\-]*' // Default
);

$Rounting['map'] = array(
    'login' => 'user/login',
    'userdetail' => 'user/detail',
    ':controller/:action' => null // Default
);

เหตุผลต่อมาในการทำแบบนี้เพราะ เราสามารถนำไปทำ cache ได้ง่ายขึ้นด้วยครับ

หลาย ๆ คนถามมาว่าทำไมเปลียนแปลงส่วน config ใหม่ ทั้ง ๆ ที่น่าจะดีอยู่แล้ว เหตุผลง่าย ๆ ก็คือลดการประมวลผลที่ไม่จำเป็นในการประมวลผลส่วนการตั้งค่าระบบไปซะ อีกอย่าง array ใน php ก็ทำความเข้าใจไม่ยากนัก ทำให้การปรับมาใช้ไม่ทำให้สวยความง่ายลงไปครับ

อาจจะทำ tools สำหรับ generate ตัว routing ด้วยก็ไม่ยากนักครับ

ความคืบหน้า PHP Hoffman Framework (2)

หลังจาก ความคืบหน้า PHP Hoffman Framework มีข้อเสนอแนะมาเกี่ยวกับ routing ที่เป็น xml กับ config ที่เป็น ini ทั้ง ทาง im และ comment (แต่ใน comment มีแค่ 4 คน)

จาก comment ของคุณ kaze เรื่อง config แบบ ini เมื่อเอามานั่งไล่ดู แล้วเห็นตรงกันกับคุณ kaze ตอนนี้เลยทำการปรับเปลี่ยนไปใช้ array และ convert ตัว array เป็น object แทน ซะ แต่ยังคงความสามารถ inherit ตัว config ไว้เพื่อความสะดวกในการขึ้น production app ได้ ตอนนี้เลยปรับเปลี่ยนจาก ini เป็น Array ใน php แทน

ตอนนี้เลยใช้เป็นแบบนี้ครับ

$Config['Production']['WebHost'] = 'http://localhost';
$Config['Production']['UseCleanUrl'] = true;
$Config['Production']['UseRoutesCache'] = false;
$Config['Production']['BaseUrl'] =  '/PHM2';
$Config['Production']['RenderViewDebugging'] = false;
$Config['Production']['RenderViewCompileCheck'] = false;
$Config['Production']['RenderViewCache'] = false;
$Config['Production']['ArgSeparator'] = ';';

$Config['Production']['Database']['Default'] = 'mysqli://root:1234@localhost:3007/production_album';
$Config['Production']['Database']['ReadServer'] = 'mysqli://root:1234@localhost:3008/production_album';
$Config['Development']['Database']['Default'] = 'mysqli://root:1234@localhost:3008/development_album';
$Config['Test']['Database']['Default'] = 'mysqli://root:1234@localhost/test_album';

โดน Dimension แรกเป็นตัวกำหนด config ว่าจะเป็น environment ไหน ส่วนตัวต่อมาก็เป็น dimension ของ ตัวที่เอาไปตั้งค่าจริง ๆ ส่วน ของ database จะเรื่องมากกว่าหน่อยตรงที่มีหลาย ๆ profile เผื่อในกรณีที่มีการใช้งานข้าม database หรือข้าม server กัน

อันนี้คือการเปลี่ยนส่วนของ config อีกรอบนึง แต่ดู ๆ แล้วน่าจะดีกว่าเดิมในแง่ของการไม่ต้อง parse ตัว ini ออกมา

ส่วน routing กำลังคิด ๆ อยู่ว่าจะเอาไงดี อาจจะปรับมาใช้แบบเดียวกันเลย เพื่อลดเวลาการ parse ข้อมูลลอง xml ด้วย

ส่วนเวลาเรียกใช้ก็ อ้างอิงแบบ Object ซะ โดยตัวอย่างด้านล่างก็ต้องเอาข้อมูล user ของ Database ที่เป็น Default ออกมา

echo $applicationConfigurations->Database->Default->user;

[Update 08/02/2007 00:21]

ตอนนี้ลดรูปลงมาให้ดูง่ายขึ้น (หรือเปล่า) มาเป็นแบบนี้ครับ

$Config['Production'] = array(
    'WebHost'=>'http://localhost',
    'UseCleanUrl'=>true,
    'UseRoutesCache'=>false,
    'BaseUrl'=>'/PHM2',
    'RenderViewDebugging'=>false,
    'RenderViewCompileCheck'=>false,
    'RenderViewCache'=>false,
    'ArgSeparator'=>';',
    'Database'=> array(
        'Default'=>'mysqli://root:1234@localhost:3007/production_album',
        'ReadServer'=>'mysqli://root:1234@localhost:3008/production_album'
    )
);

$Config['Development'] = array(
    'Database'=> array(
        'Default'=>'mysqli://root:1234@localhost:3007/development_album'
    )
);

$Config['Test'] = array(
    'Database'=> array(
        'Default'=>'mysqli://root:1234@localhost:3007/test_album'
    )
);

ความคืบหน้า PHP Hoffman Framework

  • ทำการ redesign ตัว clean url ใหม่อีกรอบ ด้วยการกลับมาใช้แบบเดิมเมื่อตอนออกแบบครั้งแรกคือ controller/action แทน ส่วนต้องการแก้ไข url ใหม่ ก็เพิ่มลงไปใน xml เอา โดย default คือ <map pattern=”:controller/:action” /> ถ้าต้องการใช้ user/login เป็น login เฉย ๆ ก็ <map pattern=”login” action=”user/login” /> แทนซะ หรือถ้าต้องการ rewrite ตัว url ที่มีการส่ง value ด้วยก็ <map pattern=”news” action=”page/show/1″ /> แทนก็ได้เช่นกัน โดยในรุ่นต่อไปจะมี plugin เสริมสำหรับการ hook ตัว xml ตัวนี้ให้ไปใช้ database ได้ แบบเดียวกับ drupal แทนช้าลงและโหลด db มากขึ้น กำลังจุดลงตัวในส่วนนี้ โดย clean url นี้มีประสิทธิภาพเพิ่มขึ้นเยอะกว่าเดิมมาก และลดความซับซ้อนในการตั้งค่าลงไปเยอะด้วย แต่ต้องแลกกับความยืดหยุ่นบางส่วนไป แต่ถ้าว่า ok กว่าเดิมมาก ๆ ในตอนนี้
  • หน้า error handler page นั้น ok แล้ว เพื่อดักข้อผิดพลาดในกรณีไฟล์ของ controller หรือ view ไม่มี รวมถึง arguments ไม่ครบเมื่อ controller ไป handle ตัว action
  • ตัว config ไฟล์ใน .ini file และสามารถทำ inherit config ได้ด้วย เช่น
[production]
database.default.type=mysql
database.default.hostname=localhost
database.default.username=root
database.default.password=1234
database.default.name=album

[development : production]
database.default.hostname = localhost
database.default.username = root
database.default.password = 1234
  • เมื่อเราเลือก production เป็น environment มันจะไปดึงตัว config มาของ production มา แต่ถ้าใช้  development ก็จะไปดึงส่วนของ development ที่ override ตัว production มาใช้เท่านั้น ทำให้ลดการตั้งค่าลงไปเยอะ
  • ในส่วนของ Model layer มี 3 ทางเลือกให้ extends มาใช้งานได้ คือ Zend_Db, Doctrine หรือ LogicModel (ตัวนี้ผมเขียนเอง สนับสนุนแค่ MySQL เท่านั้น) โดยใครถนัดแบบไหนก็ใช้แบบนั้นได้เลย เพียงแค่ตั้งค่าใน Model แต่ละตัวว่าจะใช้แบบไหน กำลังหาจุดลงตัวเพื่อให้เราสามารถใช้ Model ได้หลากหลายรูปแบบการ extends จาก 3 ทางเลือก บางครั้ง Model บางตัวอาจจะเหมาะกับ Doctrine มากกว่า 2 ตัวที่เหลืออะไรแบบนั้น และอาจจะรองรับการเขียนด้วย function mysql(i) เดิม ๆ ได้ด้วย โดยผมมองว่า Model นั้นเป็น Business logic ซึ่งควรมี performance สูงที่สุดในการเขียนและนำไปใช้งานครับ
  • การส่งข้อมูลจาก controller ไปหา view นั้นใช้การ return ของ action ใน controller นั้น โดยการส่งข้อมูลแบบตัวแปรเดียวก็ได้ หรือส่งเป็น array ออกไปก็ได้ โดยส่งเป็น array จะทำการ fetch ข้อมูลให้ชั้นนึงเพื่อส่งผ่านเป็นตัวแปรนึงใน view ให้เลย โดยใช้การ map key เป็นชื่อตัวแปรใน dimension ที่ 1 ของ array ซะ
  • พยายามเอา ORM หลาย ๆ ตัวมาใช้ร่วมกันใน Model เพื่อลดการยึดติดของระบบกับรูปแบบ ORM ของตัวใดตัวหนึ่ง
  • ยังคงใช้ Zend แบบหลักในการพัฒนาระบบภายในเช่นเดิม

ตอนนี้โดยรวมพยายาปั้นตัวแรกออกมาให้ได้ก่อน เพื่อเอามารับคำติของทุกท่านครับ เพื่อเอามาพัฒนาต่อไปครับผม

PHPHoffman Framework Diagram

จาก entry ที่แล้ว ก็นั่งคิด ๆ ว่าตัว Framework จะมีส่วนหลัก ๆ อะไรบ้าง ตอนนี้ก็ได้ข้อสรุปในการสร้างออกมาแล้ว นั่งคิด และปรับว่าจะเอายังไงอยู่หลายวันอยู่ เพราะบางอย่างมันก็รักพี่เสียดายน้อง แต่หลัก ๆ คือใช้ PHP5.2 และใช้ Extension ต่าง ๆ ของ PHP หลายตัวซึ่งการที่ใช้ Extension ของ PHP เยอะ ด้วยเหตุที่เอา Zend Framework เข้ามาอยู่ใน Core ระบบ ทำให้ข้อกำหนดหลายอย่างต้องหนักไปทาง Zend หลายเ่รื่อง แต่ผลที่ได้รับคือตัว code ต่าง ๆ นั้นมีระเบียบและตามรูปแบบเพิ่มขึ้นเยอะ สวนตัว Extension Components ได้แนวคิดจาก Firefox ที่อยากได้อะไรเิพิ่มก็เอามาใส่นั้นแหละ นอกเหนือจากที่ตัว Zend และ Component หลัก แต่จะยังคงแนวคิดที่ว่าจำเป็นต้องใช้อะไรก็จะโหลดระหว่างตอนทำงานแค่นั้น ทำให้ตัว Controller ต้องไล่ทำใหม่ทำให้ ทุก ๆ action นั้นมีรายละเอียดในการตั้งค่าเพิ่มขึ้น แต่จะเห็นว่า Permission Control นั้นหายไป เพราะคิดไว้ว่าจะเป็นส่วนของ Routing แทน ตอนนี้ขอดูความเหมาะสมก่อน ส่วนที่ผู้เขียนนั้นต้องใส่ใจจะมีอยู่ในส่วนนอกของ Core ทั้งหมด

เหตุที่ใช้ Component ของ Zend Framework ก็จากเหตุผลเก่าจาก entry ที่แล้ว และเพราะมีระเบียบแบบแผนการพัฒนาในชุมชนที่แข็งมาก

ตอนนี้พยายามเคลียร์ ๆ งานที่จำประจำ แล้วลงมาทำส่วน Framework ให้มันออกมาเป็น public เสียที คนบ่นอยากใช้กันแย่แล้ว T_T

อ่อ ผมได้แนวคิดส่วน View จาก Sixhead Template ของคุณปีโป้ หลายส่วน ซึ่งตอนนี้เอาไว้ public plan ที่ 2 แล้วกันเพราะได้ดูแนวคิดแล้ว ช่วยทีมออกแบบกราฟฟิกได้เยอะ

อ่อ ตัว private version ที่เป็น alpha รุ่นแรก ถูกเขียนเป็น Shop Cart อยู่ที่ http://shop.thaiadmin.org แต่ผมมองว่ารุ่นนั้นก็ปล่อยได้แล้วแหละ แต่ว่ามองอีกมุม ยังยากอยู่อีก -_-‘ อยากให้มันง่ายกว่านี้ในการใช้งานเพิ่มขึ้น

แค่คิดก็นั่งลง coding มันแล้ว …….

[Update] – เหตุผลต่อมาในการใช้ PHP5 เพราะตัว MySQL Improved Extension นั้นทำงานได้ดีกว่ากับ MySQL ใน version ใหม่ ๆ ด้วย คือมีแล้วไม่ได้ใช้มันเสียดาย -_-‘

Redesign PHPHoffman Framework Architecture

เป็นปัญหาหนักอกอย่างรุนแรงที่จำเป็นต้อง redesign ตั้งแต่ยังไม่ออก beta การ redesign ในระดับ core นี่มันสุด ๆ จริง ๆ เพราะว่าอย่างที่หลาย ๆ entry ที่ผ่านมาเนี่ยกะว่าก็คงรู้ว่าผมกำลังทำ Framework ที่ออกไปทาง Conponent Base แทน และผสมตัว Automate เฉพาะที่จำเป็น ทำให้ไอ้ที่ทำ ๆ ตอนแรก ๆ ในแบบ Automate ทั้งหมดตั้งแต่แรก มันต้อง drop ไปหมดเลย เพราะเริ่มคิดว่า การทำเล็ก ๆ แล้วเอา plug-in มาใส่น่าจะตอบโจทย์มากกว่า เพราะอย่างแรกมันเป็นเรื่องของการโหลดตัวระบบที่มาก หรือน้อยขึ้นอยู่กับ component ที่ใช้ ไม่ใช่จะใช้แค่นี้แต่ดันเอาไส้ในออกมาเสียหมด มันเปลื้องเกินความจำเป็น แถมลอง monitor ตัว framework ที่เขียนในปัจจุบันนี่มันก็ใช้ memmory ไปพอสมควร แต่คิดว่ามันน่าจะน้อยกว่านี้ได้อีก แถมนี่จะเกือบปีแล้วยังไม่ได้ออก beta เลย แถมมีแต่คนถามว่าเมื่อไหร่จะให้โหลด ต้องบอกว่าตัวที่เป็น production ของ Framework ตัวนี้ก็อยู่ที่ shop.thaiadmin.org ครับ ส่วนตัวใหม่นี่จะเปลี่ยนภายในทั้งหมด พวก app ที่เขียน ๆ อยู่อาจต้อง recode ใหม่ด้วย แต่มันจำเป็นจริง ๆ แต่จะพยายาม backward ให้มากที่สุด

อ่อ ลืมบอกไปว่า PHPHoffman ตัวนี้ตามข้อกำหนดของ GoPHP5 ครับ ใครใช้ PHP 4 อดนะครับ (แล้ว Host ที่ใช้อยู่นี่จะเอาไงหล่ะเนี่ย -_-")