【问题标题】:PDO in Class good practice and guidancePDO 课堂上的良好实践和指导
【发布时间】:2012-11-02 18:10:25
【问题描述】:

大家好,我已经苦苦挣扎了一两个星期,试图了解整个 PDO、单身或非 MVC 等等。我已经编写代码 3 个月了,我想知道我是否最终做到了这一点。

我正在为班级成绩等构建一个简单的学校应用程序......并创建了一个名为 section 的课程,我现在已将 PDO 纳入其中。到目前为止,它的工作和功能与 id 一样,但在我以同样的方式制作更多课程之前,我想知道是否有任何错误以及如何改进。尽管我写了其他所有内容,但我自己并没有正确的 DB 类。

class pdoDB {

/*** Declare instance ***/
private static $db = NULL;

/**
*
* the constructor is set to private so
* so nobody can create a new instance using new
*
*/
private function __construct() {
/*** maybe set the db name here later ***/
}

/**
*
* Return DB instance or create intitial connection
*
* @return object (PDO)
*
* @access public
*
*/
public static function getInstance() {

 if (!self::$db)
{
self::$db = new PDO('mysql:host=localhost;dbname=attendance_ksu','root','root');;
self::$db-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$db;
}

/**
*
* Like the constructor, we make __clone private
* so nobody can clone the instance
*
*/
private function __clone(){
}

} /*** end of class ***/

现在是我的节课。

class Section  {


// if protected can't loop through on html page into table
    // I don't want to make getter method for each attribute.
    // all data will be coming from the db

public $id;
public $section_number;
public $subject;
public $classroom;
public $level_id;
public $shift;
public $course;
public $campus;
public $times;
public $academic_year;
public $start_date;
public $end_date;
public $max_st_number;
public $status;

// retrieve all sections in db

public static function get_all_sections() {

try {

    // maybe a waste of time doing this bit?? not sure!! the " if(!isset($db)) "

if(!isset($db)) {
$db = pdoDB::getInstance();

/*** echo a message saying we have connected for testing reasons only ***/
echo 'Connected to database <br />';
}

/*** The SQL SELECT statement ***/
$sql = "SELECT * FROM sections";
$stmt = $db->query($sql);
$objs = $stmt->fetchALL(PDO::FETCH_CLASS, 'Section');

// 1. return the complete array of data so I can loop through it later

return $objs;  

// 2. Or echo out a loop immediately where this method is called

   /*

foreach ($objs as $section) {
echo "Section:" . $section->section_number . " | " . 
     "Subject: {$section->subject}" . "<br/>";
}

    */

$db = null;   
    }

catch(PDOException $e)
{
echo $e->getMessage();
}

}


// Get the section details by id from db
// will be passed via the URL as $_GET

public static function get_section_by_id($id) {

try {

if(!isset($db)) {
$db = pdoDB::getInstance();

/*** echo a message saying we have connected ***/
echo 'Connected to database<br />';
}   
     /*** prepare the SQL statement ***/
$stmt = $db->prepare("SELECT * FROM sections WHERE id = :id");

/*** bind the paramaters ***/
$stmt->bindParam(':id', $id, PDO::PARAM_INT);

/*** execute the prepared statement ***/
$stmt->execute();

/*** fetch the results and give it a class ***/
$section = $stmt->fetchObject('section');
return $section;

$db = null;   
    }

catch(PDOException $e)
{
echo $e->getMessage();
}   

}
}

我打算只在页面上调用 get_all_sections() 方法并将结果循环到表中。其他页面也将使用此方法完成。如果不将我的学习曲线扩展到 MVC 等...这是一种可接受的方法吗?我是否朝着正确的方向前进?

EG:

<?php
// some code
$sections = Section::get_all_sections();

// any other necessary code
?>

<html> 
<body>

    <table class="table table-striped table-bordered table-highlight" id="example">
<thead>
<tr>
<th>#</th>
<th>Section Number</th>
<th>Subject</th>
<th>Course</th>
<th>Students</th>
<th>Level</th>
<th>Campus</th>
<th>Classroom</th>
<th>Shift</th>
<th>Start date</th>
<th>End date</th>
<th>Teacher</th>
<th>&nbsp;</th>
</tr>
</thead>

<tbody>
<?php 
$key =  1;
foreach($sections as $section) {
?>
<tr>
<td><? echo $key++ ?></td>
<td><a href=""><?php echo $section->section_number ?></a> </td>
<td><?php echo $section->subject ?> </td>
<td><?php echo $section->course ?> </td>
<td><?php echo $section->no_students ?> sts</td>
<td><?php echo $section->level_id ?> </td>
<td><?php echo $section->campus ?> </td>
<td> <?php echo $section->classroom ?></td>
<td><?php echo $section->shift ?> </td>
<td><?php echo date("d-M-Y",strtotime($section->start_date ))?></td>
<td><?php echo date("d-M-Y",strtotime($section->end_date ))?></td>
<td>

<?php 
if($section->username  =="")
{
echo "<a href=\"add_section_teacher.php?id=".urlencode($section->id )."&section_number=".urlencode($section->section_number )."\">Not assigned</a>";

} else {
echo "<a href=\"edit_section_teacher.php?ts_id=".urlencode($section->ts_id )."\">";
echo $section->username ; 
echo "</a>";
}       
?>  
</td>
<td><a href="delete.php?id=<?php echo $section->id ; ?>" 
onclick="return confirm('Are you sure you want to delete section <?php echo $section->section_number ; ?> ?');">Delete</a></td>
</tr>
<? }?></tbody>
</table>

提前感谢您的任何反馈和建议。我想正确地学习这一点,因此任何详细的反馈:)都会受到赞赏,因为这里的目标是学习。

【问题讨论】:

    标签: php class pdo


    【解决方案1】:

    我认为您的 PDO 工厂还可以。 您的课程部分不正确,因为它不尊重单一责任原则。

    Section 应该只是一个具有属性、getter 和 setter(如果需要)和一些计算方法的类。必须没有到数据库的链接。您应该使用 Repository 模式来放置 bdd 访问方法,如 find、findAll...

    那么你应该在你的控制器中调用你的存储库。

    class SectionRepository{
        public function findAll(){
           $db = pdoDB::getInstance();
           $result = $bd->query(SELECT * FROM sections);
           return $result->fetchAll(PDO::FETCH_CLASS,Section);  
        }
    }
    

    关于您正在使用的 PDO 工厂:

    class PDOFactory{
        private static $connection = null;
        public static function getConnection(){
            if(self::$connection === null){
                 self::$connection = new PDO();//here you can use a config file if you want
                 self::$connection -> setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
            }
            return self::$connection;
    }
    

    它不是真正的单例,因为没有私有构造(在 php 中不可能重载)并且因为 PDOFactory 不扩展 PDO 但行为完全相同。

    【讨论】:

    • 感谢您的建议,但我对存储库模式一无所知。我只想让这段代码以最容易接受的方式工作。我可能会花费数周时间阅读不同的模式,但永远无法完成或正确完成任何事情。我如何修复我的部分类以尊重单例,因为我已经看到人们在类中包含数据库连接,因为我有。他们使用什么模式?谢谢
    • 我给了你实现存储库模式的方法......这真的很简单:一方面是你的实体,另一方面是处理你的实体的存储库。在您的控制器中,您只需说 $rep = new SectionRepository(); $rep-&gt;findAll()
    • 关于单例,大多数时候,您会更喜欢确保您只有一个实例而不是单例的工厂。几乎是一样的,只是代码有点不同。 (一两个世界)我在回答中给你。
    【解决方案2】:

    虽然 Artragis 的上述回答确实是要走的路(长期),但我感到 OP'er 努力将自己的思想包裹在整个 OOP 之谜中的痛苦——我现在一直在与这个问题作斗争过去两年没有真正取得任何进展。

    我对他简单的 Section-class 的观察:

    • 单例模式没问题
    • 单例的用法不行: 单例本身被设计为“实例化”(可能是错误的 词的选择)只有一次,然后保持开放,只要它是 需要。

    我建议执行以下操作:

    • 删除测试以检查 $db isset - 如果一个连接不存在,则单例只创建一个连接
    • 移除 $db 变量的取消设置 - 让连接保持打开状态,直到垃圾收集通过
    • 一个可选步骤是将您的 $db_handle 注入到 Section-class 中(通过构造函数最简单) - 这将使您的 Section-class 仅与 pdoDB-class 松散耦合(好的,好的 - 也许您需要一个由 pdoDB 类首先实现的中间接口,但你明白了)并且更容易测试

    【讨论】:

      猜你喜欢
      • 2015-10-07
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 2011-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多