【发布时间】:2015-02-24 19:27:06
【问题描述】:
我正在努力了解 OOP 原则并编写自己的类。作为一种学习方式,我决定将我在 Wordpress 中编写的几个函数转换为 OOP 类。这些函数协同工作,以便根据 URL 中设置的引用者(其中 4 个)在单个页面上输出正确的帖子链接。
这是一个基本工作流程的设置(工作流程可以随着我的进展而改变):
根据档案页面为URL设置4个查询变量,即分类页面设置1个查询变量,作者页面设置1个查询变量等等。任何页面都不能有多个自定义查询变量。这 4 个变量由我的第一个类检索并对照给定的全局变量检查,在本例中为 $_GET。我没有对班级中的 4 个变量进行硬编码,这也适用于 $_GET,以保持班级可测试。如果 URL 中存在值,则通过 has* 方法返回键/值对。如果未找到匹配项,这些方法将返回 null。 (这是原始数据,将由将使用此数据的类进行清理/转义)
这是完整的课程
<?php
namespace PG\Single\Post\Navigation;
/**
* Test set values against the super global given. Returns conditional properties
* which is boolean values. true is returned on success and false on failure.
*
* @param $superGlobalVar Super global to test the values against
* @param (string) $authorReferrer
* @param (string) $dateReferrer
* @param (string) $searchReferrer
* @param (string) $taxReferrer
*/
class RequestReferrerHandler implements RequestReferrerHandlerInterface
{
/**
* @since 1.0.0
* @access protected
* @var (array) $superGlobalVar
*/
protected $superGlobalVar;
/**
* @since 1.0.0
* @access protected
* @var (string) $authorReferrer
*/
protected $authorReferrer;
/**
* @since 1.0.0
* @access protected
* @var (string) $dateReferrer
*/
protected $dateReferrer;
/**
* @since 1.0.0
* @access protected
* @var (string) $searchReferrer
*/
protected $searchReferrer;
/**
* @since 1.0.0
* @access protected
* @var (string) $taxReferrer
*/
protected $taxReferrer;
/**
* Public constructor method.
*
* @param $superGlobalVar Super global to get data from
* @param $authorReferrer Query variable from author referrer to test
* @param $dateReferrer Query variable from date referrer to test
* @param $searchReferrer Query variable from search referrer to test
* @param $taxReferrer Query variable from taxonomy referrer to test
*/
public function __construct($superGlobalVar = null, $authorReferrer= null, $dateReferrer = null, $searchReferrer = null, $taxReferrer = null)
{
$this->superGlobalVar = $superGlobalVar;
$this->authorReferrer = $authorReferrer;
$this->dateReferrer = $dateReferrer;
$this->searchReferrer = $searchReferrer;
$this->taxReferrer = $taxReferrer;
}
/**
* Setter setSuperGlobalVar.
*
* @since 1.0.0
* @param $superGlobalVar
* @return $this
*/
public function setSuperGlobalVar($superGlobalVar)
{
$this->superGlobalVar = $superGlobalVar;
return $this;
}
/**
* Returns an array of super global variables.
*
* @since 1.0.0
* @return (array) $this->superGlobalVar
*/
public function getSuperGlobalVar()
{
return $this->superGlobalVar;
}
/**
* Setter setAuthorReferrer
*
* @since 1.0.0
* @param $authorReferrer
* @return $this
*/
public function setAuthorReferrer($authorReferrer)
{
$this->authorReferrer = $authorReferrer;
return $this;
}
/**
* Returns the value of the $authorReferrer property.
*
* @since 1.0.0
* @return (array) $this->authorReferrer
*/
public function getAuthorReferrer()
{
return $this->authorReferrer;
}
/**
* Setter setDateReferrer.
*
* @since 1.0.0
* @param $dateReferrer
* @return $this
*/
public function setDateReferrer($dateReferrer)
{
$this->dateReferrer = $dateReferrer;
return $this;
}
/**
* Returns the value of the $dateReferrer property.
*
* @since 1.0.0
* @return (array) $this->dateReferrer
*/
public function getDateReferrer()
{
return $this->dateReferrer;
}
/**
* Setter setSearchReferrer.
*
* @since 1.0.0
* @param $searchReferrer
* @return $this
*/
public function setSearchReferrer($searchReferrer)
{
$this->searchReferrer = $searchReferrer;
return $this;
}
/**
* Returns the value of the $searchReferrer property.
*
* @since 1.0.0
* @return (array) $this->searchReferrer
*/
public function getSearchReferrer()
{
return $this->searchReferrer;
}
/**
* Setter setTaxReferrer.
*
* @since 1.0.0
* @param $taxReferrer
* @return $this
*/
public function setTaxReferrer($taxReferrer)
{
$this->taxReferrer = $taxReferrer;
return $this;
}
/**
* Returns the value of the $taxReferrer property.
*
* @since 1.0.0
* @return (array) $this->taxReferrer
*/
public function getTaxReferrer()
{
return $this->$taxReferrer;
}
/**
* Test $authorReferrer against $superGlobalVar.
*
* @since 1.0.0
* @return (bool) true on success or false on failure
*/
public function isAuthorReferrer()
{
if ($this->authorReferrer && isset($this->superGlobalVar[$this->authorReferrer])) {
$isAuthorReferrer = true;
} else {
$isAuthorReferrer = false;
}
return $isAuthorReferrer;
}
/**
* Test $authorReferrer against $superGlobalVar
*
* @since 1.0.0
* @return (bool) true on success or false on failure
*/
public function isDateReferrer()
{
if ($this->dateReferrer && isset($this->superGlobalVar[$this->dateReferrer])) {
$isDateReferrer = true;
} else {
$isDateReferrer = false;
}
return $isDateReferrer;
}
/**
* Test $authorReferrer against $superGlobalVar.
*
* @since 1.0.0
* @return (bool) true on success or false on failure
*/
public function isSearchReferrer()
{
if ($this->searchReferrer && isset($this->superGlobalVar[$this->searchReferrer])) {
$isSearchReferrer = true;
} else {
$isSearchReferrer = false;
}
return $isSearchReferrer;
}
/**
* Test $authorReferrer against $superGlobalVar.
*
* @since 1.0.0
* @return (bool) true on success or false on failure
*/
public function isTaxReferrer()
{
if ($this->taxReferrer && isset($this->superGlobalVar[$this->taxReferrer])) {
$isTaxReferrer = true;
} else {
$isTaxReferrer = false;
}
return $isTaxReferrer;
}
/**
* Conditional which check if the current post is a referred post.
*
* @since 1.0.0
* @return (bool) true on success or false on failure
*/
public function isReferredPost()
{
if ($this->isAuthorReferrer() || $this->isDateReferrer() || $this->isSearchReferrer() || $this->isTaxReferrer()) {
$isReferredPost = true;
} else {
$isReferredPost = false;
}
return $isReferredPost;
}
/**
* Return the value from the super global when the current post is a post referred from
* an author archive page.
*
* @since 1.0.0
* @return (array) $authorReferrerValue
*/
public function hasAuthorReferrerValue()
{
if ($this->isAuthorReferrer()) {
$authorReferrerValue = [$this->authorReferrer => $this->superGlobalVar[$this->authorReferrer]];
} else {
$authorReferrerValue = null;
}
return $authorReferrerValue;
}
/**
* Return the value from the super global when the current post is a post referred from
* a date archive page.
*
* @since 1.0.0
* @return (array) $dateReferrerValue
*/
public function hasDateReferrerValue()
{
if ($this->isDateReferrer()) {
$dateReferrerValue = [$this->dateReferrer => $this->superGlobalVar[$this->dateReferrer]];
} else {
$dateReferrerValue = null;
}
return $dateReferrerValue;
}
/**
* Return the value from the super global when the current post is a post referred from
* a search page.
*
* @since 1.0.0
* @return (array) $searchReferrerValue
*/
public function hasSearchReferrerValue()
{
if ($this->isSearchReferrer()) {
$searchReferrerValue = [$this->searchReferrer => $this->superGlobalVar[$this->searchReferrer]];
} else {
$searchReferrerValue = null;
}
return $searchReferrerValue;
}
/**
* Return the value from the super global when the current post is a post referred from
* a taxonomy archive page.
*
* @since 1.0.0
* @return (array) $taxReferrerValue
*/
public function hasTaxReferrerValue()
{
if ($this->isTaxReferrer()) {
$taxReferrerValue = [$this->taxReferrer => $this->superGlobalVar[$this->taxReferrer]];
} else {
$taxReferrerValue = null;
}
return $taxReferrerValue;
}
}
这就是我使用这个类的方式
$b = new RequestReferrerHandler($_GET, 'aq', 'dq', 'sq', 'tq');
?><pre><?php var_dump($b->hasAuthorReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasDateReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasSearchReferrerValue()); ?></pre><?php
?><pre><?php var_dump($b->hasTaxReferrerValue()); ?></pre><?php
出于测试目的,您可以将 ['aq' => '1'] 之类的东西注入到类中,而不是 $_GET
这就是我现在陷入困境并且不知道如何继续前进的地方。我需要构造两个类,它们都将使用上述类中的相同方法,一个类将从上述类的 has* 方法构造查询参数,一个类还将从 has* 创建 query_vars上述类中的方法将用于构建新的帖子链接
因此,简而言之,两个类都将使用与上述类中完全相同的方法
hasAuthorReferrerValue();
hasDateReferrerValue();
hasSearchReferrerValue();
hasTaxReferrerValue();
仅作为示例,这里是两个类的外观示例。 (为了让代码更易管理,这里省略了一些方法)
A 类
<?php
namespace PG\Single\Post\Navigation;
class ClassA //Just a generic name for testing purposes. Will also implement ClassAInterface
{
protected $handler;
public function __construct(RequestReferrerHandlerInterface $handler)
{
$this->handler = $handler;
}
public function santizeAuthor()
{
$author = $this->handler->hasAuthorReferrerValue(); // Value will be either null or single key/value pair array. Example ['aq' => '1']
if ($author) {
$author = array_values($author);
$author = ['author' => (int)htmlspecialchars($author[0])]; //Will output ['author' => 1]
}
return $author; //Returns null or the array ['author' => 1]
}
public function santizeDate()
{
$date = $this->handler->hasDateReferrerValue();
if ($date) {
// @TODO Still to work out
}
return $date;
}
//etc
public function queryArguments() // Will be used in the controller class ClassC
{
$queryArgs = null;
if ($this->santizeAuthor()) {
$queryArgs = $this->santizeAuthor();
} elseif ($this->santizeDate) {
$queryArgs = $this->santizeDate();
} // etc
return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true
}
}
B 类
<?php
namespace PG\Single\Post\Navigation;
class ClassB //Just a generic name for testing purposes. Will also implement ClassBInterface
{
protected $handler;
public function __construct(RequestReferrerHandlerInterface $handler)
{
$this->handler = $handler;
}
public function santizeAuthor()
{
$author = $this->handler->hasAuthorReferrerValue(); // Value will be either null or single key/value pair array. Example ['aq' => '1']
if ($author) {
foreach ($author as $k=>$v)
$author[htmlspecialchars($k)] = (int)htmlspecialchars($v);
}
return $author; //Returns null or the array ['aq' => 1]
}
public function santizeDate()
{
$date = $this->handler->hasDateReferrerValue();
if ($date) {
// @TODO Still to work out
}
return $date;
}
//etc
public function queryVars() // Will be used in the controller class ClassC
{
$queryVars = null;
if ($this->santizeAuthor()) {
$queryVars = $this->santizeAuthor();
} elseif ($this->santizeDate) {
$queryVars = $this->santizeDate();
} // etc
return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true
}
}
来自ClassA 的queryArguments() 方法和来自ClassB 的queryVars() 方法将用于其他类(或一个控制器类)
我完全缺乏进入 OOP 的适当知识,对关注点分离、封装、SOLID 原则和保持类可测试感到困惑,这让我再次猜测我的代码,我确实觉得我错过了一些东西。
无论如何我可以优化上述内容。我不要求任何类型的代码重写,我所需要的只是适当的指针和想法来优化它以使其达到标准,如果不是的话。如果任何人都可以提供代码示例,例如大纲骨架,那将是一个真正的优势
【问题讨论】:
-
IMO 该帖子与 SO 无关。在 codereview.stackexchange.com 上提问,即使没有 500 赏金,您也可能得到答案
-
当我发布这个问题时,我会更感激这个评论,为什么要等待提供赏金然后发布这样的 cmets。
-
我没有等到。当我第一次看到这个问题时,我发表了评论。赏金已申请。
-
我认为如果您可以将重复的函数从
ClassA和ClassB移动到一个抽象类并从它继承,例如santizeDate()、santizeAuthor会更好...