ผมเขียน PDO แบบนี้จะได้เรื่องมั้ยครับ ?

เริ่มโดย dekmv, 13 กันยายน 2013, 17:31:53

หัวข้อก่อนหน้า - หัวข้อถัดไป

0 สมาชิก และ 1 ผู้มาเยือน กำลังดูหัวข้อนี้

dekmv

จากกระทู้นี้ แนะนำให้ผมเขียนเป็น PDO http://www.thaiseoboard.com/index.php/topic,330711.0.html

<?php
   $username = 'root';
   $password = 'xxxxxx;
   $dbname = 'igen_goods';
   
   $dbHandle = new PDO('mysql:host=localhost;dbname='.$dbname, $username, $password);
   $dbHandle->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
   // always disable emulated prepared statement when using the MySQL driver
   $dbHandle->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);



class Tag{
   //
   public function getTag($dbHandle){
      try{
         $sql = "SELECT * FROM ig_tag";
         $stmt = $dbHandle->prepare($sql);
         $stmt->execute();
      
         while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            echo $row['tg_id'].'-'.$row['tg_title'].'-'.$row['tg_keyword'];
         }
      }
      catch(PDOException $e){
         echo 'ERROR: ' . $e->getMessage();
      }
   }
}
?>

พอจะได้เรื่องมั้ยครับ แบบว่าผิดหลักอะไรตรงไหนรึป่าวครับ แล้วปกติทั่วไปเค้าเขียนยังไงครับ ?  :wanwan012:

ดูมาจาก http://codereview.stackexchange.com/questions/5735/php-pdo-mysql-connection-and-query-class-safety-and-logic

dekmv


MapTwoZa

ถามว่าผิดมั๊ย ถ้ามัน query ออกมาได้ มันก็ไม่ผิดหรอกครับ -*-
แต่ประเด็นคือ ตัวอย่างมันน้อยเกินไป

ซึ่งหลักๆ เวลาจะใช้ PDO มันควรจะเป็นแบบนี้
1. bind paramter ทุกตัวที่รับ input เข้ามาจากภายนอก (user กรอก, get/post parameters ต่างๆ )
2. 1 request ควรมี PDO instance แค่ 1 ตัว ดังนั้นควรจะออกแบบให้ทุกๆ query ใช้ pdo ร่วมกัน


แต่ถ้าจะให้ถึงกึ๋น OOP ของจริง มันต้อง design ให้เป็น OO มากกว่านี้คับ หรือที่เค้าเรียกว่า ORM

ปรกติผมทำ ผมจะแบบนี้
<ในตัวอย่างผมใช้ Doctrine ORM>

controller   --(call)-->   DaoService
DaoService   --(query from)-->   DataBase   --(put queried data into)-->   Entity Object
DaoService   --(return entity to)-->  controller

ปล. Dao = Data Access Object

ตัวอย่าง

#controller

public function imagesAction()
    {
$this->view->sharedImages = ImageService::getSharedImages($this->_myUser->getId());
$this->view->yourImages = ImageService::getYoursImages($this->_myUser->getId());
    }


#DaoService

public static function getYoursImages($uploaderId){

$em = MyEntityManagerFactory::getEntityManager();

$dql = "select i from \Models\Entities\Image i"
.' join i.uploader u'
.' where u.id = ?1'
.' order by u.id desc';

$query = $em->createQuery($dql);
$query->setParameter(1, $uploaderId);

return $query->getResult();
}


#Entity Class: Image <ผมเอา getter/setter ออกนะครับ>

namespace Models\Entities;


/** @Entity
*  @Table(name="images")
* */
class Image{

/** @Id
*  @GeneratedValue(strategy="IDENTITY")
*  @Column(name="id", type="integer") **/
private $id;

/** @Column(name="is_shared", type="boolean") **/
private $isShared;

/** @Column(name="`key`", type="string", length=6, unique=true, nullable=false) **/
private $key;

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

/** @Column(name="md5", type="string", unique=true, nullable=true) **/
private $md5;

/** @Column(name="uploaded_time", type="string") **/
private $uploadedTime;

/**
*
* @var Image
* @ManyToOne(targetEntity="Image")
* @JoinColumn(name="image_ref_id", referencedColumnName="id")
*/
private $referenceImage;

/**
*
* @var User
* @ManyToOne(targetEntity="User")
* @JoinColumn(name="uploader_user_id", referencedColumnName="id")
*/
private $uploader;

/** @Column(name="nick_name", type="string", nullable=false, length=100) **/
private $nickName;


คร่าวๆ มันก็จะประมาณนี้ ซึ่งจุดเด่นของการแบ่ง code เป็นหลายๆชั้นแบบนี้คือ มันจะอ่านง่ายมาก
ถ้าทำหลายๆคน ก็ comment เข้าไปหน่อย อ่านง่ายขึ้นมากเลย
Good code quality Developer :D

dekmv

ขอบคุณครับ ขอเก็บไปพัฒนาต่อครับผม  :wanwan012:

ossytong

ถ้าจะเขียน ในระดับนี้ มาใช้ Framework เถอะครับ ข้ามมาอีก Step ไปเลยครับ

คุ้มค่ากว่าที่จะมา Learn แบบ HardCode

วิ่งหา Framework ได้แล้วครับ ตราบใดที่ HardCode มันก็ไม่มีคำว่าอ่านง่ายหรอกครับ แล้วก็ทำ UnitTest ยากด้วย
เราออกแบบเอง ไม่คุ้มในเมื่อมันมี เครื่องมือที่มีประสิทธิภาพอยู่แล้ว ก็ใช้ให้เป้นประโยชน์ครับ

ตอนนี้ Framework ก็ต้องตัวนี้เลยครับ Laravel4 ORM ดีมาก Relation ก็สวย

zankumuro

อย่าเชื่อผมมาก ผมมันมั่ว.....ฮ่าๆ

ฝาก Like แฟนเพจหน่อยครับ
https://www.facebook.com/devsignup

ข่าวสารวงการเกมส์ ทริปทริคต่างๆ เกมส์แจกฟรี
https://www.wecanplay.in.th/

dekmv

อ้างถึงจาก: ossytong ใน 14 กันยายน 2013, 02:23:27
ถ้าจะเขียน ในระดับนี้ มาใช้ Framework เถอะครับ ข้ามมาอีก Step ไปเลยครับ

คุ้มค่ากว่าที่จะมา Learn แบบ HardCode

วิ่งหา Framework ได้แล้วครับ ตราบใดที่ HardCode มันก็ไม่มีคำว่าอ่านง่ายหรอกครับ แล้วก็ทำ UnitTest ยากด้วย
เราออกแบบเอง ไม่คุ้มในเมื่อมันมี เครื่องมือที่มีประสิทธิภาพอยู่แล้ว ก็ใช้ให้เป้นประโยชน์ครับ

ตอนนี้ Framework ก็ต้องตัวนี้เลยครับ Laravel4 ORM ดีมาก Relation ก็สวย

ขอบคุณมากครับ ,,,  :P

MapTwoZa

ลองเข้าไปดู Laravel Eloquent ORM มาแล้วครับ บอกตรงๆ ง่ายสุดๆ
แนะนำว่าไป Laravel Eloquent ORM ก็ได้ครับ ไม่ก็ไป doctrine (ง่าย กับ ยาก เลือกเอา)

แต่เข้าไปดูเบื้องต้นแล้ว สรุปให้เป็นข้อๆดังนี้

1. Eloquent เพิ่งมาใหม่ feature ยังไม่เท่า doctrine แต่ feature หลักๆ มีครบหมดแล้ว เช่น concurency ใน Eloquent  ยังไม่มี
2. Doctrine มาตรฐานกว่ามาก ในระดับโปรเจคใหญ่ๆ รู้กันเลยว่าถ้าใช้ doctrine แล้วนั้น เหมือนกันการรองรับในตัวเลยว่า database ที่ออกแบบมาต้องมาตรฐาน (ไม่งั้นมันใช้กับ doctrine ลำบากมาก error บาน เนื้องจากรูปแบบมันซับซ้อน ) เช่น ถ้ายังไม่ normalize จะเอามาใช้ลำบากมาก
3. learning curve นั้น doctrine แพ้กระจาย Eloquent ง่ายกว่า 100 เท่าได้
4. รูปแบบของ Doctrine มันเกือบจะเหมือนกัน JPA2 ใน Java เป๊ะๆ ถ้าคิดจะใช้ orm ใน java ด้วยก็หัด doctrine ก็ได้
5. document ฝั่ง doctrine สมบูรณ์และเป็นระบบมากกว่า (แต่ด้วยมันยากกว่า doc แมร่งโคตรเยอะ อย่างกะอ่าน textbook 1 เล่ม แถมไม่ใช่จะจำได้ ใช้ทีต้องมาเปิดดูที)
6. doctrine require caching อย่างน้อยนึงอย่าง ถ้าไม่มีจะช้าลงเยอะมาก (เพิ่มขึ้นประมาณ 0.4 second) แต่ว่าตรงนี้คำนึงในแง่ production พอแล้ว เปลี่ยน cache ง่ายมาก ตอน development ไม่จำเป็นต้องใช้เลย (Apc, Xcache, Memcache เป็นต้น)

ข้อดีข้อเสียแตกต่างกันไป พิจรณาเองครับว่าถ้าจะใช้ ORM เริ่มที่ตัวไหนดี
Good code quality Developer :D

dekmv

อ้างถึงจาก: MapTwoZa ใน 14 กันยายน 2013, 03:03:07
ลองเข้าไปดู Laravel Eloquent ORM มาแล้วครับ บอกตรงๆ ง่ายสุดๆ
แนะนำว่าไป Laravel Eloquent ORM ก็ได้ครับ ไม่ก็ไป doctrine (ง่าย กับ ยาก เลือกเอา)

แต่เข้าไปดูเบื้องต้นแล้ว สรุปให้เป็นข้อๆดังนี้

1. Eloquent เพิ่งมาใหม่ feature ยังไม่เท่า doctrine แต่ feature หลักๆ มีครบหมดแล้ว เช่น concurency ใน Eloquent  ยังไม่มี
2. Doctrine มาตรฐานกว่ามาก ในระดับโปรเจคใหญ่ๆ รู้กันเลยว่าถ้าใช้ doctrine แล้วนั้น เหมือนกันการรองรับในตัวเลยว่า database ที่ออกแบบมาต้องมาตรฐาน (ไม่งั้นมันใช้กับ doctrine ลำบากมาก error บาน เนื้องจากรูปแบบมันซับซ้อน ) เช่น ถ้ายังไม่ normalize จะเอามาใช้ลำบากมาก
3. learning curve นั้น doctrine แพ้กระจาย Eloquent ง่ายกว่า 100 เท่าได้
4. รูปแบบของ Doctrine มันเกือบจะเหมือนกัน JPA2 ใน Java เป๊ะๆ ถ้าคิดจะใช้ orm ใน java ด้วยก็หัด doctrine ก็ได้
5. document ฝั่ง doctrine สมบูรณ์และเป็นระบบมากกว่า (แต่ด้วยมันยากกว่า doc แมร่งโคตรเยอะ อย่างกะอ่าน textbook 1 เล่ม แถมไม่ใช่จะจำได้ ใช้ทีต้องมาเปิดดูที)
6. doctrine require caching อย่างน้อยนึงอย่าง ถ้าไม่มีจะช้าลงเยอะมาก (เพิ่มขึ้นประมาณ 0.4 second) แต่ว่าตรงนี้คำนึงในแง่ production พอแล้ว เปลี่ยน cache ง่ายมาก ตอน development ไม่จำเป็นต้องใช้เลย (Apc, Xcache, Memcache เป็นต้น)

ข้อดีข้อเสียแตกต่างกันไป พิจรณาเองครับว่าถ้าจะใช้ ORM เริ่มที่ตัวไหนดี

ขอบคุณมากครับ ... อ่านๆๆๆๆ แล้วก็อ่านๆ  :wanwan009:

dekmv

ผมเขียน

public function listTag($dbHandle,$status,$start,$total){
      try{
          $stmt = $dbHandle->prepare("SELECT tg_title,tg_keyword FROM ig_tag WHERE tg_status = ? ORDER BY tg_create_time DESC LIMIT ?,?");
          $stmt->execute(array($status,$start,$total));
       
         while ($var = $stmt->fetch(PDO::FETCH_ASSOC)) {
            include'html/tag-list-item.php';
         }
      }
      catch(PDOException $e){
         echo 'ERROR: ' . $e->getMessage();
      }
   }

ทำไมออกแบบนี้ครับ

ERROR: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0','10'' at line 1

dekmv

ผมลองแก้เป็น

$stmt = $dbHandle->prepare('SELECT * FROM ig_tag WHERE tg_status = ? LIMIT '.$start.','.$total);
$stmt->execute(array($status));

แบบนี้รันออก !!!

goldxp

ถ้าแค่การเรียกคำสั่งก็วุ่นแล้วลองเลือกใช้ framework ก็เป็นทางเลือกที่ดีนะครับ

แต่ถ้าไ่ม่ชอบทำอะไรยุ่งยากอยากได้โค้ดแบบเรียบๆ ง่ายๆ เลย ลองโค้ดตัวใหม่ตัวนี้ดูครับ (configuration-less ORM)

http://redbeanphp.com/

เพิ่ง release มาไม่นานนี้เอง ผมอ่านคร่าวๆ แล้วใช้ได้เลยสำหรับโปรเจคทั่วๆ ไป จะเขียนโค้ดสั้นลงได้เยอะครับ
[direct=http://web-programming-bookmark.blogspot.com/p/blog-page.html]รับแก้ไขเว็บ[/direct]

xvlnw.com

กระทู้นี้มีประโยชน์จริงๆครับ ต้องเก็บๆ
[direct=https://cloudhost.in.th/wordpress-hosting]ツ ⓌⓄⓇⒹⓅⓇⒺⓈⓈ ⒽⓄⓈⓉⒾⓃⒼ [/direct] :wanwan014:  :D
[direct=https://cloudhost.in.th/cloudhosting.html]Cloud Hosting[/direct] [direct=https://cloudhost.in.th/cloudvps.html]Cloud Server[/direct] [direct=https://cloudhost.in.th/vpshosting.html]Cloud VPS Hosting[/direct] [direct=https://cloudhost.in.th/windowsvps.html]Cloud Windows[/direct] Tel: 080-348-0843 LINE: ixvlnw

ossytong

#13
ตัว Laravel นี่ข้างในมี Doctrine อยู่แล้วนะครับ มันเอา Doctrine  มาใช้ เข้าใจว่ามันเอามาใช้ ใน Eloquent

ตอน  Update Composer เห็น แพคเกจ Doctrine บ่อยๆ เลยไปนั่งแกะดู ก็เข้าใจว่า มันเอาใช้

ส่วนของการออกแบบ ฐานข้อมูของ Laravel ก็มี Pattern อยู่ครับ เข้าใจว่ามีส่วนคล้าย Doctrine

tekub

ลอง framework ง่ายๆ อย่าง codeigniter ดูสิครับ ใช้ง่ายมาก ไม่ต้องมาเริ่มนับ 1 ใหม่
[direct=http://www.easysoft.co.th/products/minimart]โปรแกรมร้านมินิมาร์ท โปรแกรมขายหน้าร้าน[/direct]
[direct=http://www.easysoft.co.th/products/topup]เติมเงินมือถือออนไลน์ จุดรับชำระบิลออนไลน์[/direct]

ossytong

#15
อ้างถึงจาก: tekub ใน 14 กันยายน 2013, 19:16:51
ลอง framework ง่ายๆ อย่าง codeigniter ดูสิครับ ใช้ง่ายมาก ไม่ต้องมาเริ่มนับ 1 ใหม่

Codeigniter มันตายแล้วครับ...  ^^ คนทำ CI ย้ายมา Laravel แล้ว

อนาคตมันไม่มีแล้ว แล้ว CI3.0 ก็ไม่มีท่าทีจะมาเลย แล้วติดตามข่าวมันก็ไม่มีอะไรเด่นใน 3.0 เลยครับ

ปัจจุบันผมเจองาน CI ใน Project เก่าๆ แต่ งานใหม่ๆ เริ่มจาก Laravel หรือ Yii ซะเยอะ

xvlnw.com

สงสัยต้องหันไปทาง Laravel บ้างแล้วครับ
[direct=https://cloudhost.in.th/wordpress-hosting]ツ ⓌⓄⓇⒹⓅⓇⒺⓈⓈ ⒽⓄⓈⓉⒾⓃⒼ [/direct] :wanwan014:  :D
[direct=https://cloudhost.in.th/cloudhosting.html]Cloud Hosting[/direct] [direct=https://cloudhost.in.th/cloudvps.html]Cloud Server[/direct] [direct=https://cloudhost.in.th/vpshosting.html]Cloud VPS Hosting[/direct] [direct=https://cloudhost.in.th/windowsvps.html]Cloud Windows[/direct] Tel: 080-348-0843 LINE: ixvlnw

MapTwoZa

อ้างถึงจาก: ossytong ใน 14 กันยายน 2013, 18:10:49
ตัว Laravel นี่ข้างในมี Doctrine อยู่แล้วนะครับ มันเอา Doctrine  มาใช้ เข้าใจว่ามันเอามาใช้ ใน Eloquent

ตอน  Update Composer เห็น แพคเกจ Doctrine บ่อยๆ เลยไปนั่งแกะดู ก็เข้าใจว่า มันเอาใช้

ส่วนของการออกแบบ ฐานข้อมูของ Laravel ก็มี Pattern อยู่ครับ เข้าใจว่ามีส่วนคล้าย Doctrine

ใช่ครับ แต่ไม่ได้เอาส่วนของ doctrine orm มา

doctrine มี 3 โปรเจคย่อยข้างในคือ doctrine common, doctrine database abstract layer แล้วก็ doctrine orm

เหมือนเค้าทำมาแบบว่า ถ้าไม่ชอบ doctrine orm ก็เอาแค่ common + database abstract layer ไปใช้


ซึ่งส่วนอื่นของ doctrine มันมีเจ๋งๆเยอะนะครับ
บาง class ไม่เกี่ยวกับ database ผมยังเอามาใช้เลย อย่างเช่นพวก array collection, cache เป็นต้น
Good code quality Developer :D

ossytong

อ้างถึงจาก: MapTwoZa ใน 14 กันยายน 2013, 20:47:01
อ้างถึงจาก: ossytong ใน 14 กันยายน 2013, 18:10:49
ตัว Laravel นี่ข้างในมี Doctrine อยู่แล้วนะครับ มันเอา Doctrine  มาใช้ เข้าใจว่ามันเอามาใช้ ใน Eloquent

ตอน  Update Composer เห็น แพคเกจ Doctrine บ่อยๆ เลยไปนั่งแกะดู ก็เข้าใจว่า มันเอาใช้

ส่วนของการออกแบบ ฐานข้อมูของ Laravel ก็มี Pattern อยู่ครับ เข้าใจว่ามีส่วนคล้าย Doctrine

ใช่ครับ แต่ไม่ได้เอาส่วนของ doctrine orm มา

doctrine มี 3 โปรเจคย่อยข้างในคือ doctrine common, doctrine database abstract layer แล้วก็ doctrine orm

เหมือนเค้าทำมาแบบว่า ถ้าไม่ชอบ doctrine orm ก็เอาแค่ common + database abstract layer ไปใช้


ซึ่งส่วนอื่นของ doctrine มันมีเจ๋งๆเยอะนะครับ
บาง class ไม่เกี่ยวกับ database ผมยังเอามาใช้เลย อย่างเช่นพวก array collection, cache เป็นต้น

ครับ ขอบคุณมากครับได้รู้เพิ่มเยอะเลย ผมก็ไม่เคยใช้  doctrine เลย ผมชอบ อ่าน Comment ท่านมาก ดูรู้เลยว่าผ่านงาน ผ่านประสบการณ์มาเยอะจริง  :wanwan017: :wanwan017:

vii

อ้างถึงจาก: ossytong ใน 14 กันยายน 2013, 19:21:42
อ้างถึงจาก: tekub ใน 14 กันยายน 2013, 19:16:51
ลอง framework ง่ายๆ อย่าง codeigniter ดูสิครับ ใช้ง่ายมาก ไม่ต้องมาเริ่มนับ 1 ใหม่

Codeigniter มันตายแล้วครับ...  ^^ คนทำ CI ย้ายมา Laravel แล้ว

อนาคตมันไม่มีแล้ว แล้ว CI3.0 ก็ไม่มีท่าทีจะมาเลย แล้วติดตามข่าวมันก็ไม่มีอะไรเด่นใน 3.0 เลยครับ

ปัจจุบันผมเจองาน CI ใน Project เก่าๆ แต่ งานใหม่ๆ เริ่มจาก Laravel หรือ Yii ซะเยอะ

ขออ้างอิงคำของ Phil Sturgeon
http://philsturgeon.co.uk/blog/2012/05/laravel-is-awesome

อ้างถึงEvery single framework goes through the same trouble that every single piece of software goes through: Change.

As a framework developer you are always met with two extremes:

    1.Change a lot
    2.Don't change

framework ที่จะสร้างปัญหาให้กับ developer คือ 1. มันมีการเปลี่ยนแปลงถี่เกินไป  2. มันไม่เปลี่ยนแปลงเลย
ผมได้ทดลองใช้ Laravel มาตั้งแต่ v.3 แม้จะพบคุณสมบัติที่น่าสนใจมากมาย แต่ว่ามันออกมาถี่เกิน แล้วเราก็ต้องมาศึกษาปรับแก้โค้ดกันบ่อยเกินไป
ไปๆมาๆมันจะคล้ายๆกับแฟชั่นไปแล้ว ที่ใส่แล้วก็ออกใหม่ก็ถอดกองเปลี่ยนเอารุ่นใหม่ๆมาใส่ไปเรื่อยๆ เหนื่อยเกินไปรึเปล่า(ผมคิดนะ)

framework มันเป็นเครื่องมือ มันไม่ควรออกถี่มากขนาดนั้น (3เวอร์ชั่นหลักในปีเดียว) ควรออกมาช้าๆหน่อย แบบพอดีๆ
เพราะโปรเจ็คหนึ่งๆ มันไม่ใช่ทำแปบๆเสร็จแล้วเสร็จเลยทิ้งเลย บางทีมันมีงาน maintenance อีก
ซึ่งของเวอร์ชั่นใหม่ๆมามันก็จะมีการแก้ bug ใน framework อยู่เราก็อยากจะเอามาใช้ให้มันเพิ่มความปลอดภัยกับโปรเจ็คของเรา
พอมันออกถี่ไปการตามอัพเดทเพิ่มความปลอดภัยก็จะไม่ค่อยอยากทำกันแล้ว ก็กลายเป็น maintenance แบบขอไปที

ส่วน CI นั้น ช่วงก่อนหน้าก็ถือว่าไม่ออกมาถี่เกินไป (ช่วง 2.0 เป็นต้นมา) ซึ่งกำลังดี แต่ว่าหลังๆมานี้มันดูช้าเกินไป แล้วก็ไม่มีแผนที่แน่ชัดว่า 3.0 จะออกเมื่อไหร่
จนปัจจุบันก็นึกเหมือนกันว่ามันอาจจะตายไปแล้วรึกำลังตาย เพราะมันยังมีคนคอยจัดการ pull request ใน github อยู่เรื่อยๆ แต่ไม่มีการแจ้งอะไรเลย

ถึงแม้อย่างนั้นก็ไม่ใช่ว่าเขาจะย้ายไปใช้ Laravel กันหมดนะครับ cms ระดับเทพของ Phil Sturgeon (Pyro CMS) ก็ยังคงใช้ CI อยู่ แม้จะเป็นรุ่น Pyro 3.0 dev ตัวล่าสุดที่เขาทำกันอยู่ก็ตาม
สาเหตุก็เพราะว่า ความจริงแล้วแม้ CI จะไม่มีลูกเล่นใหม่ๆมาให้ตื่นเต้นเร้าใจโปรแกรมเมอร์หลายๆคน แต่มันยังตอบสนองความต้องการในการเขียนงานได้เป็นอย่างดีอยู่ ทั้งความเร็ว ความปลอดภัย
ถ้าเมื่อไหร่ก็ตามโปรเจ็คที่เราทำนั้น CI ไม่สามารถสนองได้ ก็สมควรที่จะมองหาตัวอื่นที่ทำได้ และไม่ออกอัพเดทถี่เกินไป :)