Php 接口注入和公共类
我正试图了解OOP原则,并编写自己的类。作为学习的一种方式,我决定将我在Wordpress中编写的两个函数转换为OOP类。这些函数协同工作,以便根据URL中设置的引用者(其中4个)在单个页面上输出正确的帖子链接 这是带有基本工作流程的设置(工作流程可以随操作而更改): 根据归档页面为URL设置了4个查询变量,即一个用于分类页面的查询变量,一个用于作者页面的查询变量,等等。任何页面都不能有多个自定义查询变量。这4个变量由我的第一个类检索,并根据给定的全局变量进行检查,在本例中为Php 接口注入和公共类,php,wordpress,oop,Php,Wordpress,Oop,我正试图了解OOP原则,并编写自己的类。作为学习的一种方式,我决定将我在Wordpress中编写的两个函数转换为OOP类。这些函数协同工作,以便根据URL中设置的引用者(其中4个)在单个页面上输出正确的帖子链接 这是带有基本工作流程的设置(工作流程可以随操作而更改): 根据归档页面为URL设置了4个查询变量,即一个用于分类页面的查询变量,一个用于作者页面的查询变量,等等。任何页面都不能有多个自定义查询变量。这4个变量由我的第一个类检索,并根据给定的全局变量进行检查,在本例中为$\u GET。我
$\u GET
。我没有在我的类中硬编码这4个变量,这也有助于$\u 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;
}
}
作为一个示例,下面是两个类的外观示例。(为了使代码更易于管理,我省略了这里的一些方法)
甲级
如果您想将RequestReferrerHandler
类的同一对象用于ClassA和ClassB,那么您的策略是正确的。只需要使用RequestReferrerHandler
类的对象来实例化ClassA和ClassB。然后您可以访问特定的方法。i、 e.ClassA.queryArguments()
或ClassB.queryVars()
如果要为ClassA和ClassB创建单独的requestReferreHandler
类对象,可以将requestReferreHandler
类扩展到ClassA和ClassB,而无需定义构造函数。因此,当您创建ClassA的对象时,它会自动继承RequestReferrerHandler
类的构造函数方法,您可以通过parent:
关键字访问属性和方法。例如:
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);
}
}
}
// Standard OOP
$car = new Car();
$buyer = new Person();
$store = new Store();
// Many solutions to buy a car!
$buyer->buy($car, $store);
// or
$store->sell($car, $buyer);
// or
// ...
你可以做和B类一样的事情。现在,您可以为类a和类B创建对象,在类C中为它们的基类指定构造函数的参数,并使用它们的对象的返回值ClassA.queryArguments()
或ClassB.queryVars()
。查看代码,您肯定有了一个良好的开始。在使用OOP编程时,您已经使用了一个很好的经验法则-编程到接口,而不是实现。接口这个术语不仅指实际接口,也指抽象类
// Composition
class Car implements VehicleInterface
{
private $motor;
}
class Motor implements MotorInterface
因此,在问题的核心,您希望有两个类,ClassA
和ClassB
,它们都使用requestrefererhandler
中的常用方法。您已经为您的接口requestReferreHandlerInterface
做了准备工作。我们可以说,您有一个如下所示的界面:
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);
}
只要此接口是由requestrefererhandler
实现的,您就可以键入提示接口作为ClassA
和ClassB
的构造函数要求。但这并不是什么新鲜事,因为你已经在这么做了
有两件事在我看来特别突出,那就是潜在的拇指酸痛。首先,由于您希望类的责任很小,因此您应该负责将数据提供给requestrefererhandler
,而不是提供给控制器。换句话说,不要将$\u GET
注入到您的类中。确保您的<代码>控制器<代码>拥有正确创建<代码> RequestReferrerHandler < /代码>所需的所有信息。让我们看一下您的<代码> RequestReferrerHandler <代码>类,用它需要的所有方法刷新。
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);
}
}
}
第二件突出的事情是santize()
方法。您是否看到它们在ClassA
和ClassB
中是如何复制的?两个类中的sanitizeAuthor()
是不同的,但是其余的呢?在这种情况下,干燥(不要重复自己)原则可以提供帮助。由于多个类可能必须以类似的方式清理数据,因此将其从类中抽象出来是有意义的
让我们看看如何做到这一点,然后我们将回到您的具体课程。首先创建一个新接口,该接口将指定可以清理数据的对象必须公开的方法
interface SanitizableHandlerInterface
{
public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer);
}
interface QueryVarsInterface extends SanitizableHandlerInterface
{
public function queryVars();
}
interface QueryArgumentsInterface extends SanitizableHandlerInterface
{
public function queryArguments();
}
现在,如果您拥有的ClassX
的每个对象都以不同的方式实现了这四个方法,那么您可以开始在不同的类中实现它,这些类只是清理数据。然而,对于这个例子,我们会说情况并非如此。让我们假设sanitizeAuthor()
在ClassA
和ClassB
(在您的代码中)之间可能不同,并且所有其他方法的实现都完全相同。在这种情况下,我们可以使用一个抽象类来实现sanitizer方法
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
}
}
有些事情需要立即注意。首先,您会注意到有一个setHandler()
方法,它接受requestReferreHandlerInterface
的实例。这是为什么?大多数情况下都很方便。由于我们已经采取了清理行为并将其封装到自己的类中,因此我们为清理器提供了一种方法来更新具体的requestrefererhandler
,它正在使用清理方法的更新输出
接下来,我们将使用requestrefererhandler
类中未在requestrefererhandler接口中指定的方法。这不是一个好主意
interface SanitizerInterface
{
public function sanitizeAuthor();
public function sanitizeDate();
public function sanitizeSearch();
public function sanitizeTaxonomy();
}
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);
}
}
}
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);
}
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);
}
}
}
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
}
}
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())
);
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)
<?php
/*
* INTERFACES
*/
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);
}
interface SanitizerInterface
{
public function sanitizeAuthor();
public function sanitizeDate();
public function sanitizeSearch();
public function sanitizeTaxonomy();
}
interface SanitizableHandlerInterface
{
public function __construct(RequestReferrerHandlerInterface $handler, SanitizerInterface $sanitizer);
}
interface QueryVarsInterface extends SanitizableHandlerInterface
{
public function queryVars();
}
interface QueryArgumentsInterface extends SanitizableHandlerInterface
{
public function queryArguments();
}
/*
* ABSTRACT CLASSES
*/
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);
}
}
}
/*
* 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())
);
// Composition
class Car implements VehicleInterface
{
private $motor;
}
class Motor implements MotorInterface
// Inheritance
class Car extends MotorVehicle
{
}
// Composition
class Car implements VehicleInterface
{
private $motor;
private $movement;
}
class Motor implements MotorInterface
class Drive implements MovementInterface
// Inheritance
class Car extends MotorVehicle, DriveVehicle
{
}
class Car implements VehicleInterface
{
private $motor;
}
class PetrolMotor implements MotorInterface
class DieselMotor implements MotorInterface
class Car implements VehicleInterface
{
private $motor;
public function __construct(MotorInterface $motor)
{
$this->motor = $motor;
}
}
class PetrolMotor implements MotorInterface
{
}
class DieselMotor implements MotorInterface
{
}
$motor = new PetrolMotor();
$car = new Car($motor);
// Standard OOP
$car = new Car();
$buyer = new Person();
$store = new Store();
// Many solutions to buy a car!
$buyer->buy($car, $store);
// or
$store->sell($car, $buyer);
// or
// ...
// SOA
$car = new Car();
$buyer = new Person();
$store = new Store();
$saleHandler = new SaleHandler();
$saleHandler->sell($car, $buyer, $store);