PHP 摘要;这是使用抽象类的正确方法吗?
我只是想知道我是否走在正确的道路上。将大多数函数抽象化似乎没有必要,因为数据几乎相同。这是无效的方法吗?
<?php
abstract class Model_Tasks {
/**
* Database object
*
* @access protected
*/
protected $db;
/**
* User ID
*
* @access protected
*/
protected $uid;
/**
* Data array
*
* @access protected
*/
protected $data;
/**
* SQL Query
*
* @access protected
*/
protected $query;
/**
* __construct
*
* @access protected
*/
protected function __construct($query) {
$this->db = Model_DB::getInstance();
$this->uid = $_SESSION['uid'];
$this->query = $query;
$this->getTasks();
}
/**
* getTasks
*
* @param string
* @access abstract protected
*/
protected function getTasks() {
$result = $this->db->prepare($this->query);
$result->execute(array(
':uid' => $this->uid
));
$this->data =& $result->fetchAll();
$this->taskCount = $result->rowCount();
}
/**
* constructTask
*
* Build the HTML of a task
*
* @param int
* @param int
* @param string
* @param string
* @access protected
*/
protected function constructTask(
$id, $cost, $title, $checked = 0
) {
$cost = money_format('$%i', $cost);
$title = stripslashes($title);
return '
<label class="task">
<input type="checkbox" name="done[]" rel="'.$id.'" '.($checked?'checked="checked"':'').' />
<code>'.$cost.'</code> — '.$title.'
</label>'."\n";
}
/**
* generateOutput
*
* Call by key [pending, completed] and return the constructed tasks
*
* @param bool
* @access final public
*/
final public function generateOutput($checked) {
try {
if(!is_bool($checked)) throw new Exception('generateOutput must contain a boolean variable');
if(!isset($this->data)) throw new Exception('Array has not been set.');
else $data = $this->data;
} catch(Exception $e) {
die('<pre>'.$e->getMessage().'<hr />'.$e->getTraceAsString());
}
if(is_array($data)): foreach($data AS &$r)
$str .= $this->constructTask($r['id'], $r['cost'], $r['title'], $checked);
else:
$str = '<label class="tasks"></label>';
endif;
return $str;
}
}
// ------------------------------------------------------------------------
/**
* pendingTasks
*
* @access public
*/
class pendingTasks extends Model_Tasks {
public $taskCount;
public function __construct() {
$query = '
SELECT id, title, cost
FROM tasks
WHERE (
status IS FALSE
AND uid = :uid
) ORDER BY cost DESC
';
parent::__construct($query);
}
}
/**
* completedTasks
*
* @access public
*/
class completedTasks extends Model_Tasks {
public function __construct() {
$query = '
SELECT id, title, cost
FROM tasks
WHERE (
status IS TRUE
AND uid = :uid
) ORDER BY id DESC
LIMIT 7
';
parent::__construct($query);
}
}
它所做的只是打印出具有特定查询的任务,并返回一个关联数组。
I just want to know if I'm on the right path. Making most functions abstract didn't seem necessary as the data is just about the same. Is this an invalid approach?
<?php
abstract class Model_Tasks {
/**
* Database object
*
* @access protected
*/
protected $db;
/**
* User ID
*
* @access protected
*/
protected $uid;
/**
* Data array
*
* @access protected
*/
protected $data;
/**
* SQL Query
*
* @access protected
*/
protected $query;
/**
* __construct
*
* @access protected
*/
protected function __construct($query) {
$this->db = Model_DB::getInstance();
$this->uid = $_SESSION['uid'];
$this->query = $query;
$this->getTasks();
}
/**
* getTasks
*
* @param string
* @access abstract protected
*/
protected function getTasks() {
$result = $this->db->prepare($this->query);
$result->execute(array(
':uid' => $this->uid
));
$this->data =& $result->fetchAll();
$this->taskCount = $result->rowCount();
}
/**
* constructTask
*
* Build the HTML of a task
*
* @param int
* @param int
* @param string
* @param string
* @access protected
*/
protected function constructTask(
$id, $cost, $title, $checked = 0
) {
$cost = money_format('$%i', $cost);
$title = stripslashes($title);
return '
<label class="task">
<input type="checkbox" name="done[]" rel="'.$id.'" '.($checked?'checked="checked"':'').' />
<code>'.$cost.'</code> — '.$title.'
</label>'."\n";
}
/**
* generateOutput
*
* Call by key [pending, completed] and return the constructed tasks
*
* @param bool
* @access final public
*/
final public function generateOutput($checked) {
try {
if(!is_bool($checked)) throw new Exception('generateOutput must contain a boolean variable');
if(!isset($this->data)) throw new Exception('Array has not been set.');
else $data = $this->data;
} catch(Exception $e) {
die('<pre>'.$e->getMessage().'<hr />'.$e->getTraceAsString());
}
if(is_array($data)): foreach($data AS &$r)
$str .= $this->constructTask($r['id'], $r['cost'], $r['title'], $checked);
else:
$str = '<label class="tasks"></label>';
endif;
return $str;
}
}
// ------------------------------------------------------------------------
/**
* pendingTasks
*
* @access public
*/
class pendingTasks extends Model_Tasks {
public $taskCount;
public function __construct() {
$query = '
SELECT id, title, cost
FROM tasks
WHERE (
status IS FALSE
AND uid = :uid
) ORDER BY cost DESC
';
parent::__construct($query);
}
}
/**
* completedTasks
*
* @access public
*/
class completedTasks extends Model_Tasks {
public function __construct() {
$query = '
SELECT id, title, cost
FROM tasks
WHERE (
status IS TRUE
AND uid = :uid
) ORDER BY id DESC
LIMIT 7
';
parent::__construct($query);
}
}
All it does is to print out a task with a specific query, and return an associative array.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当从抽象类继承时,父类声明中标记为抽象的所有方法都必须由子类定义;此外,这些方法必须以相同(或较少限制)的可见性来定义。例如,如果抽象方法定义为 protected,则函数实现必须定义为 protected 或 public,但不能定义为 private。此外,方法的签名必须匹配,即类型提示和所需参数的数量必须相同。 这也适用于 PHP 5.4 的构造函数。在 5.4 之前,构造函数签名可能有所不同。
--php.net
在您的构造函数的实现签名中是不同的。 。
When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or a less restricted) visibility. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public, but not private. Furthermore the signatures of the methods must match, i.e. the type hints and the number of required arguments must be the same. This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures could differ.
--php.net
In your implementation signature of the constructors is different..
这是一个使用抽象类的真实示例:小部件。
我有一个小部件模型,它具有创建、编辑、保存或渲染小部件所需的大部分功能。然而,有两个基本指标表明我需要这个类是抽象的:
edit()
方法和一个render()
方法,如照片小部件具有不同的属性,并且应以与推文小部件不同的方式显示。Here's a real-world example of a time to use abstract classes: widgets.
I have a widget model that has MOST of the functionality needed to create, edit, save, or render a widget. However, there are 2 basic indicators that I need this class to be abstract:
edit()
method and arender()
method, as a photo widget has different properties and should be displayed differently from a tweet widget.“这是无效的做法吗?”
不,您的代码正确使用了抽象。您可以集中通用逻辑,但是通过将父类声明为抽象类,您将强制通过子类完成该类的实例化(扩展您的抽象父类),这效果很好。
一条建议:
以这种方式声明成员变量会破坏封装。我建议您通过调用代码而不是在构造函数中分配这样的成员变量。
"Is this an invalid approach?"
No. Your code is using abstract correctly. You are able to centralize common logic, but by declaring the parent class as abstract, you are forcing the instantiation of the class to be done via a child class (extends your abstract, parent class), which works well.
Piece of advice:
Declaring member variables in this fashion breaks encapsulation. I'd advise you to assign member variables like this via your calling code, and not in your constructor.