我试图了解OOP原则并编写自己的类.作为一种学习方法,我决定将我在Wordpress中编写的一些函数转换为OOP类.这些功能一起工作,以便根据URL中设置的引用(其中4个)在单个页面上输出正确的帖子链接.
这是具有基本工作流程的设置(工作流程可以随着我的进展而改变):
根据归档页面将4个查询变量设置为URL,即,分类页面的一个查询变量,为作者页面设置的一个查询变量等等.任何页面都不能有多个自定义查询变量.在这种情况下,这4个变量由我的第一个类检索并针对给定的全局变量进行检查$_GET
.我没有硬编码我的类中的4个变量,这$_GET
也是为了保持类可测试.如果URL中存在该值,则通过has*
方法返回键/值对.null
如果未找到匹配项,则返回这些方法.(这是将使用此数据的类清理/转义的原始数据)
这是完整的课程
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'); ?>hasAuthorReferrerValue()); ?>hasDateReferrerValue()); ?>hasSearchReferrerValue()); ?>hasTaxReferrerValue()); ?>出于测试目的,您可以将类似的东西注入
['aq' => '1']
到类中而不是$_GET
这就是我现在被困住的地方,不知道如何继续前进.我需要构造两个类,它们都使用上面类中的相同方法,一个类
has*
将从上面的类中的方法构造查询参数,并且一个类query_vars
也将从has*
上面将要使用的类的方法创建构建新的帖子链接因此,简而言之,两个类都将使用与上述类中的方法完全相同的类
hasAuthorReferrerValue(); hasDateReferrerValue(); hasSearchReferrerValue(); hasTaxReferrerValue();举个例子,这里有两个类应该是什么样子的例子.(我在这里省略了一些方法来使代码更易于管理)
ClassA的
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 } }ClassB的
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 } }在
queryArguments()
从方法ClassA
和queryVars()
从方法ClassB
将在其他类(或一个控制器类)一起使用我完全缺乏适当的知识进入OOP,混淆分离关注点,封装,SOLID原则和保持类可测试让我第二次猜测我的代码,我觉得我错过了一些东西.
无论如何,我可以优化上述内容.我不是要求任何类型的代码重写,我需要的是关于优化这一点的正确指针和想法,如果不是,则将其提升到标准.如果任何人都可以提供代码示例,例如大纲骨架,这将是一个真正的加分
1> Crackertasti..:查看您的代码,您肯定是一个良好的开端.在OOP编程时,您已经使用了一个好的经验法则 - 编程到接口,而不是实现. 通过术语接口,我不是仅指实际接口,而是指抽象类.
因此,在您的问题的核心,您希望有两个类,
ClassA
并且ClassB
都使用常用方法RequestReferrerHandler
.您已经完成了基于界面的基础工作RequestReferrerHandlerInterface
.所以我们会说你有一个如下所示的界面:interface RequestReferrerHandlerInterface { public function hasAuthorReferrerValue(); public function hasDateReferrerValue(); public function hasSearchReferrerValue(); public function hasTaxReferrerValue(); }So long as this interface is implemented by the
RequestReferrerHandler
you can type hint the interface as the constructor requirements forClassA
andClassB
. But this isn't anything new because you were already doing this.There are two things in particular that stand out at me as potential sore thumbs. First, since you want the responsibilities of your classes to be small, you should take the responsibility of providing data to the
RequestReferrerHandler
away from itself and give it to yourController
. In other words, do not inject$_GET
into your class. Make sure yourController
has all the information it needs to properly create theRequestReferrerHandler
Let's take a look at yourRequestReferrerHandler
class, flushed with all of the methods it will need.class RequestReferrerHandler implements RequestReferrerHandlerInterface { private $author; private $date; private $search; private $tax; public function __construct($author = null, $date = null, $search = null, $tax = null) { $this->setAuthorReferrer($author); $this->setDateReferrer($date); $this->setSearchReferrer($search); $this->setTaxReferrer($tax); } public function hasAuthorReferrerValue() { return $this->author !== null ? true : false; } public function hasDateReferrerValue() { return $this->date !== null ? true : false; } public function hasSearchReferrerValue() { return $this->search !== null ? true : false; } public function hasTaxReferrerValue() { return $this->tax !== null ? true : false; } public function getAuthorReferrer() { return $this->author; } public function getDateReferrer() { return $this->date; } public function getSearchReferrer() { return $this->search; } public function getTaxReferrer() { return $this->tax; } public function setAuthorReferrer($author) { $this->author = $author; } public function setDateReferrer($date) { $this->date = $date; } public function setSearchReferrer($search) { $this->search = $search; } public function setTaxReferrer($tax) { $this->tax = $tax; } }第二件事就是
santize()
方法.你看他们是如何在这两个复制ClassA
和ClassB
?该sanitizeAuthor()
是两个阶级之间的不同,但对其余的怎么样?这是DRY (不要重复自己)原则可以帮助的情况.由于多个类可能必须以类似的方式清理数据,因此从类中抽象出来是有意义的.让我们来看看如何做到这一点然后我们将回到你的具体课程.首先创建一个新接口,该接口将指定必须由可以清理数据的对象公开的方法.
interface SanitizerInterface { public function sanitizeAuthor(); public function sanitizeDate(); public function sanitizeSearch(); public function sanitizeTaxonomy(); }现在,如果您拥有的每个对象
ClassX
以不同的方式实现这四种方法,您就可以开始在不同的类中实现它,只需清理数据.但是,对于这个例子,我们会说并非如此.让我们作一个假设,sanitizeAuthor()
可能是中不同的ClassA
和ClassB
(它是在你的代码)和所有其他方法将被执行完全一样的.这种情况下我们可以使用一个实现清理方法的抽象类.abstract class AbstractSanitizer implements SanitizerInterface { protected $handler; public function __construct() {} public function setHandler(RequestReferrerHandlerInterface $handler) { $this->handler = $handler; } /* For this example we are saying that sanitizeDate(), sanitizeTaxonomy() and * sanitizeSearch() will be the same no matter what. So let's implement them * and leave the child classes to implement sanitizeAuthor(). * * Implement the details of the sanitizer function to fit your needs. */ public function sanitizeDate() { if($this->handler !== null) { //Perform whatever tasks to sanitize the date $sanitized = strtoupper($this->handler->getDateReferrer()); echo "Sanitize date -> switch to uppercase letters.\n"; $this->handler->setDateReferrer($sanitized); } } public function sanitizeSearch() { if($this->handler !== null) { //Perform whatever tasks to sanitize the search $sanitized = strtolower($this->handler->getSearchReferrer()); echo "Sanitize search -> switch to lowercase letters.\n"; $this->handler->setSearchReferrer($sanitized); } } public function sanitizeTaxonomy() { if($this->handler !== null) { //Perform whatever tasks to sanitize the taxonomy $sanitized = str_replace(" ", "_", $this->handler->getTaxReferrer()); echo "Sanitize Taxonomy -> convert spaces to underscores.\n"; $this->handler->setTaxReferrer($sanitized); } } }Some things to take note of right off the bat. First, you'll notice there is the
setHandler()
method which accepts an instance of theRequestReferrerHandlerInterface
. Why is this there? Convenience for the most part. Since we have taken the sanitizing behavior and encapsulated it into its own class it would be nice it we gave the sanitizer a way to update the concreteRequestReferrerHandler
it is using with the updated output from a sanitize method.接下来,我们使用的是
RequestReferrerHandler
类中未指定的方法RequestReferrerHandlerInterface
.这不是一个现实的问题本身,因为我们知道,像getter和setter方法是在类.但是,如果您决定使用不同的具体对象实现该接口,则单独对接口进行类型提示并不能保证这些方法可用.因此,我们需要更新RequestReferrerHandlerInterface
将保证其可用性的方法.interface RequestReferrerHandlerInterface { public function hasAuthorReferrerValue(); public function hasDateReferrerValue(); public function hasSearchReferrerValue(); public function hasTaxReferrerValue(); public function getAuthorReferrer(); public function getDateReferrer(); public function getSearchReferrer(); public function getTaxReferrer(); public function setAuthorReferrer($author); public function setDateReferrer($date); public function setSearchReferrer($search); public function setTaxReferrer($tax); }现在,回到那些消毒剂.我们知道
ClassA
并且ClassB
将以sanitizeAuthor()
不同方式实施他们的方法.抽象类AbstractSanitizer
是按照它的方式制作的,因为sanitizeAuthor()
来自它的方法SanitizerInteface
没有实现,AbstractSanitizer
因此我们必须扩展它以提供功能.我们需要以下两个类来执行此操作:class SanitizerForClassA extends AbstractSanitizer { /* This class must provide an implementation for how ClassA will * handle the sanitizeAuthor() method. */ public function sanitizeAuthor() { if($this->handler !== null) { //Perform whatever tasks to sanitize the for ClassA $sanitized = array("author" => $this->handler->getAuthorReferrer()); echo "Sanitize author -> ClassA makes author an array.\n"; $this->handler->setAuthorReferrer($sanitized); } } } class SanitizerForClassB extends AbstractSanitizer { /* This class must provide an implementation for how ClassB will * handle the sanitizeAuthor() method. */ public function sanitizeAuthor() { if($this->handler !== null) { //Perform whatever tasks to sanitize the for ClassB $sanitized = new stdClass(); $sanitized->author = $this->handler->getAuthorReferrer(); echo "Sanitize author -> ClassB makes author an object property. \n"; $this->handler->setAuthorReferrer($sanitized); } } }这两个具体类可以与将要传递给它们的具体方法中的数据一起使用
ClassA
和ClassB
清理RequestReferrerHandler
.继续,让我们来看看规格
ClassA
和ClassB
.我们知道ClassA
将需要该方法queryArguments()
,ClassB
将需要该方法,queryVars()
并且这两个类将需要允许和实例aRequestReferrerHandlerInterface
和SanitizerInterface
在其构造函数中.我们将使用一个接口处理构造函数需求,然后另外两个接口将扩展它以提供ClassA
和所需的所有方法需求ClassB
.interface SanitizableHandlerInterface { public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer); } interface QueryVarsInterface extends SanitizableHandlerInterface { public function queryVars(); } interface QueryArgumentsInterface extends SanitizableHandlerInterface { public function queryArguments(); }由于我们现在开始讨论它,让我们来看看那些将使用它们的类.
class ClassA implements QueryArgumentsInterface { private $handler; private $sanitizer; public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer) { $this->handler = $handler; $this->sanitizer = $sanitizer; $this->sanitizer->setHandler($this->handler); } public function queryArguments() // Will be used in the controller class ClassC { $queryArgs = null; if($this->handler->hasAuthorReferrerValue()) { $this->sanitizer->sanitizeAuthor(); $queryArgs = $this->handler->getAuthorReferrer(); } if($this->handler->hasDateReferrerValue()) { $this->sanitizer->sanitizeDate(); $queryArgs = $this->handler->getDateReferrer(); } if($this->handler->hasSearchReferrerValue()) { $this->sanitizer->sanitizeSearch(); $queryArgs = $this->handler->getSearchReferrer(); } if($this->handler->hasTaxReferrerValue()) { $this->sanitizer->sanitizeTaxonomy(); $queryArgs = $this->handler->getTaxReferrer(); } return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true } } class ClassB implements QueryVarsInterface { private $handler; private $sanitizer; public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer) { $this->handler = $handler; $this->sanitizer = $sanitizer; $this->sanitizer->setHandler($this->handler); } public function queryVars() // Will be used in the controller class ClassC { $queryVars = null; if($this->handler->hasAuthorReferrerValue()) { $this->sanitizer->sanitizeAuthor(); $queryVars = $this->handler->getAuthorReferrer(); } if($this->handler->hasDateReferrerValue()) { $this->sanitizer->sanitizeDate(); $queryVars = $this->handler->getDateReferrer(); } if($this->handler->hasSearchReferrerValue()) { $this->sanitizer->sanitizeSearch(); $queryVars = $this->handler->getSearchReferrer(); } if($this->handler->hasTaxReferrerValue()) { $this->sanitizer->sanitizeTaxonomy(); $queryVars = $this->handler->getTaxReferrer(); } return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true } }There you have it, the ground work is built. You'll notice that in the constructors properties are set for the handler and sanitizer class that was given and then the sanitizer is given the reference to the handler. (Remember, the sanitizers have a reference to the handler so that sanitized properties in the handler are automatically updated. The individual classes don't need to worry about that now.)
So now the million dollar question is how to use this. Well, you need a controller that can accept
ClassA
andClassB
. We will type hint these by their respective interfaces as well.class Controller { public function __construct() {} public function doStuff(QueryArgumentsInterface $argsClass, QueryVarsInterface $varsClass) { var_dump($argsClass->queryArguments()); var_dump($varsClass->queryVars()); } }在您的版本
queryArguments()
和queryVars()
您期望的退货值的清理数据.让我们插入一些数据,看看我们得到了什么. (注意:正如您已经发现我使用的所有消毒方法都没有做您正在做的事情,它们只是说明性的.)//TEST DRIVE //Create a controller that will use the classes $cOntroller= new Controller(); //Now make use of your new shiny handlers and sanitizers $controller->doStuff( new ClassA(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassB()) );这是输出:
Sanitize author -> ClassA makes author an array. array (size=1) 'author' => string 'Mark Twain' (length=10) Sanitize date -> switch to uppercase letters. string 'JANUARY 1ST, 1999' (length=17) Sanitize search -> switch to lowercase letters. string 'ok google now!' (length=14) Sanitize Taxonomy -> convert spaces to underscores. string 'Super_Awesome_Taxonomy_Tables' (length=29) Sanitize date -> switch to uppercase letters. string 'JANUARY 1ST, 1999' (length=17) Sanitize author -> ClassB makes author an object property. object(stdClass)[15] public 'author' => string 'Mark Twain' (length=10) Sanitize Taxonomy -> convert spaces to underscores. string 'Super_Awesome_Taxonomy_Tables' (length=29) Sanitize search -> switch to lowercase letters. string 'ok google now!' (length=14)那么所有这些都让你付出了代价呢?简短的回答 - 复杂性.它花了4个接口,1个抽象类和一些具体的类来向屏幕输出一些数据.
What do you gain? Short answer - flexibility. In the future you may wish to add more classes that implement either the
QueryVarsInterface
orQueryArgumentsInterface
. Consider these classesClassC
,ClassD
andClassE
. All of these classes will need a sanitizer class to go with them (that is ifSanitizerForClassA
orSanitizerForClassB
do not fit the bill) and it would be tedious to keep having to write sanitizer classes. Well, good thing for you, since you were programming to an interface all along, you won't have that problem. You can easily make aGenericSanitizer
with a default implementation of thesanitizeAuthor()
method. Use can use this class withController::doStuff()
in any case where you don't need a specialized sanitizer class. You could just as easily implement different concrete classes ofQueryArgumentInterface
orQueryVarsInterface
to test out experimental features you want to add without tampering with your current classes.Hopefully this has given you some insight on some OOP principles. Here is a complete copy of all of the code above. Slap this in an empty PHP file and run it to see everything in action. Happy programming!
handler = $handler; } /* For this example we are saying that sanitizeDate(), sanitizeTaxonomy() and * sanitizeSearch() will be the same no matter what. So let's implement them * and leave the child classes to implement sanitizeAuthor(). * * Implement the details of the sanitizer function to fit your needs. */ public function sanitizeDate() { if($this->handler !== null) { //Perform whatever tasks to sanitize the date $sanitized = strtoupper($this->handler->getDateReferrer()); echo "Sanitize date -> switch to uppercase letters.\n"; $this->handler->setDateReferrer($sanitized); } } public function sanitizeSearch() { if($this->handler !== null) { //Perform whatever tasks to sanitize the search $sanitized = strtolower($this->handler->getSearchReferrer()); echo "Sanitize search -> switch to lowercase letters.\n"; $this->handler->setSearchReferrer($sanitized); } } public function sanitizeTaxonomy() { if($this->handler !== null) { //Perform whatever tasks to sanitize the taxonomy $sanitized = str_replace(" ", "_", $this->handler->getTaxReferrer()); echo "Sanitize Taxonomy -> convert spaces to underscores.\n"; $this->handler->setTaxReferrer($sanitized); } } } /* * CONCRETE CLASSES */ class RequestReferrerHandler implements RequestReferrerHandlerInterface { private $author; private $date; private $search; private $tax; public function __construct($author = null, $date = null, $search = null, $tax = null) { $this->setAuthorReferrer($author); $this->setDateReferrer($date); $this->setSearchReferrer($search); $this->setTaxReferrer($tax); } public function hasAuthorReferrerValue() { return $this->author !== null ? true : false; } public function hasDateReferrerValue() { return $this->date !== null ? true : false; } public function hasSearchReferrerValue() { return $this->search !== null ? true : false; } public function hasTaxReferrerValue() { return $this->tax !== null ? true : false; } public function getAuthorReferrer() { return $this->author; } public function getDateReferrer() { return $this->date; } public function getSearchReferrer() { return $this->search; } public function getTaxReferrer() { return $this->tax; } public function setAuthorReferrer($author) { $this->author = $author; } public function setDateReferrer($date) { $this->date = $date; } public function setSearchReferrer($search) { $this->search = $search; } public function setTaxReferrer($tax) { $this->tax = $tax; } } class SanitizerForClassA extends AbstractSanitizer { /* This class must provide an implementation for how ClassA will * handle the sanitizeAuthor() method. */ public function sanitizeAuthor() { if($this->handler !== null) { //Perform whatever tasks to sanitize the for ClassA $sanitized = array("author" => $this->handler->getAuthorReferrer()); echo "Sanitize author -> ClassA makes author an array.\n"; $this->handler->setAuthorReferrer($sanitized); } } } class SanitizerForClassB extends AbstractSanitizer { /* This class must provide an implementation for how ClassB will * handle the sanitizeAuthor() method. */ public function sanitizeAuthor() { if($this->handler !== null) { //Perform whatever tasks to sanitize the for ClassB $sanitized = new stdClass(); $sanitized->author = $this->handler->getAuthorReferrer(); echo "Sanitize author -> ClassB makes author an object property. \n"; $this->handler->setAuthorReferrer($sanitized); } } } class ClassA implements QueryArgumentsInterface { private $handler; private $sanitizer; public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer) { $this->handler = $handler; $this->sanitizer = $sanitizer; $this->sanitizer->setHandler($this->handler); } public function queryArguments() // Will be used in the controller class ClassC { $queryArgs = null; if($this->handler->hasAuthorReferrerValue()) { $this->sanitizer->sanitizeAuthor(); $queryArgs = $this->handler->getAuthorReferrer(); } if($this->handler->hasDateReferrerValue()) { $this->sanitizer->sanitizeDate(); $queryArgs = $this->handler->getDateReferrer(); } if($this->handler->hasSearchReferrerValue()) { $this->sanitizer->sanitizeSearch(); $queryArgs = $this->handler->getSearchReferrer(); } if($this->handler->hasTaxReferrerValue()) { $this->sanitizer->sanitizeTaxonomy(); $queryArgs = $this->handler->getTaxReferrer(); } return $queryArgs; //Will return null if all 4 conditions fail or return the value from the one that returns true } } class ClassB implements QueryVarsInterface { private $handler; private $sanitizer; public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer) { $this->handler = $handler; $this->sanitizer = $sanitizer; $this->sanitizer->setHandler($this->handler); } public function queryVars() // Will be used in the controller class ClassC { $queryVars = null; if($this->handler->hasAuthorReferrerValue()) { $this->sanitizer->sanitizeAuthor(); $queryVars = $this->handler->getAuthorReferrer(); } if($this->handler->hasDateReferrerValue()) { $this->sanitizer->sanitizeDate(); $queryVars = $this->handler->getDateReferrer(); } if($this->handler->hasSearchReferrerValue()) { $this->sanitizer->sanitizeSearch(); $queryVars = $this->handler->getSearchReferrer(); } if($this->handler->hasTaxReferrerValue()) { $this->sanitizer->sanitizeTaxonomy(); $queryVars = $this->handler->getTaxReferrer(); } return $queryVars; //Will return null if all 4 conditions fail or return the value from the one that returns true } } class Controller { public function __construct() {} public function doStuff(QueryArgumentsInterface $argsClass, QueryVarsInterface $varsClass) { var_dump($argsClass->queryArguments()); var_dump($varsClass->queryVars()); } } /* * TEST DRIVE */ //Create a controller that will use the classes $cOntroller= new Controller(); //Now make use of your new shiny handlers and sanitizers $controller->doStuff( new ClassA(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, "January 1st, 1999", null, null), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler("Mark Twain", null, null, null), new SanitizerForClassB()) ); $controller->doStuff( new ClassA(new RequestReferrerHandler(null, null, null, "Super Awesome Taxonomy Tables"), new SanitizerForClassA()), new ClassB(new RequestReferrerHandler(null, null, "OK Google Now!", null), new SanitizerForClassB()) );