是否有在类中使用大量switch语句的替代方法?

时间:2016-12-06 10:37:29

标签: php switch-statement

是否有使用大量switch语句的替代方法?

我有一个可以在不同页面上工作的类,但是做同样的事情。 但是每个页面都有不同的数据要加载。 这就是我一直在做的事情(颜色仅供参考,并不是我的应用程序)。 我检查构造函数中的页面并将其放在$ this->页面变量中。然后我会有这样的功能。

private function loadTable(){
    switch($this->page){
        case "green":
            $check = $this->loadGreen();
            return $check;
        break;
        case "blue":
            $check = $this->loadBlue();
            return $check;
        break;
        case "orange":
            $check = $this->loadOrange();
            return $check;
        break;  
    }   
}

但是我可能还有另外一个功能可以做这样的事情:

public function searchRecord(){
    $name = trim(strip_tags($_POST['term']));
    switch($this->page){
        case "green":
            $query = "SELECT `green_ID`,Reason FROM `green`";
        break;
        case "blue":
            $query = "SELECT `blue_ID`,Reason FROM `blue`";
        break;
        case "orange":
            $query = "SELECT `orange_ID`,`colour`,`hat` FROM `orange`";
        break;
        default:
            return "";
    }
    //rest of code removed for sanity
}

你可以很快看到很多函数,我最终会得到很多switch语句,这只是3页。如果我有一百页,该怎么办?

我考虑过编写一个函数,其中包含整个页面的所有案例,并设置一个变量来说明我所在的页面,但是这不起作用,因为我仍然需要一个开关来检查该变量

我希望能够调用一个函数并让该函数根据我所在的页面执行不同的操作,但是我当前的系统最终会有很多switch语句,如果可能的话我想减少它。

有更好的方法吗?

5 个答案:

答案 0 :(得分:2)

正确实施的OOP是解决此问题的方法。它被称为subtyping,它是一种多态性。

您在一个课程中填写了所有页面类型的功能,这就是您最终获得大量switch语句的原因。尝试识别页面类型之间的差异,并为每个功能创建一个空的通用函数。然后扩展当前页面类,并在每个子类中实现特定于一种类型页面的功能。

这样的事情:

abstract class Page
{
    abstract public function loadTable();
    abstract protected function getSearchQuery($term);

    public function searchRecord($term);
    {
        $query = $this->getSearchQuery($term);
        // rest of search code
    }
}

class GreenPage extends Page
{
    public function loadTable()
    {
        // move the code of function Page::loadGreen() here
    }

    protected function getSearchQuery($term)
    {
         return "SELECT `green_ID`,Reason FROM `green`";
    }
}   

class BluePage extends Page
{
    public function loadTable()
    {
        // move the code of function Page::loadBlue() here
    }

    protected function getSearchQuery($term)
    {
         return "SELECT `blue_ID`,Reason FROM `blue`";
    }
}

然后你可能需要创建一个Factory对象;根据您传递的某些特征,它知道如何创建正确类型的Page对象:

class PageFactory
{
    public function createPage($name)
    {
         switch ($name)
         {
         case 'green':
             return new GreenPage();
         case 'blue':
             return new BluePage();
         case 'red':
             return new RedPage();
         default:
             // this either should never happen or you have a type of page as default
         }
     }
}


$factory = new PageFactory();
$page = $factory->createPage($name);
$page->loadTable();
$page->searchRecord(trim($_POST['term']));

答案 1 :(得分:0)

您可以根据颜色编写类名: public function searchRecordGreen() 并通过它来调用它 searchRecord$color() 应该使用php。

使其更具体:

Php.net有一个例子:

<?php
class Foo
{
    function Variable()
    {
       $name = 'Bar';
        $this->$name();      // This calls the Bar() method
    }

    function Bar()
    {
        echo "This is Bar";
    }
}

$foo = new Foo();
$funcname = "Variable";
$foo->$funcname();  // This calls $foo->Variable()

?>

您可以创建一个包含所需名称的函数,并使用$this->page作为函数名来保存exessive switch语句

答案 2 :(得分:0)

您只需按照以下方式创建查询即可构建查询而不使用切换:

$query = "SELECT `".$this->page."_ID`,Reason FROM `".$this->page."`";

答案 3 :(得分:0)

如何将查询存储在数组中并引用它?

public function searchRecord() {
    $q = [  
            'blue' => 'SELECT `blue_ID`, Reason FROM `blue`',
            'orange' => 'SELECT `orange_ID`, `colour`, `hat` FROM `orange`'
            //....
        ];
    if(array_key_exists($this->page, $q)) {
        $query = $q[$this->page];

        //insert here the code you removed for sanity
    } else {
        //nothing found
        return "";
    }
}

这样,您可以为每个页面定义一个查询,每个查询只需一行 如果您在其他地方定义该查询数组,您甚至不必编辑代码来添加或编辑单个页面。

编辑:针对不同功能的另一种方法

首先,您定义一个提供程序类,其中包含您要提供的每个页面的一个函数:

class pageProvider {
    public static function red() {}
    public static function green() {}
    //....
}

然后将您的调用显式映射到该类:

function mapToClass($page) {
    $callback = ["pageProvider", $page];
    if(is_callable($callback)) {
        return call_user_func($callback);
    } else {
        return false;
    }
}

使用用户输入来直接调用代码可以导致安全漏洞,如果你让它自由漫游,但由于我们明确地限制了对已定义类的公共可用静态方法的调用,因此它可以攻击者不可能爆发并做坏事。

另见:

答案 4 :(得分:0)

你能不能做这样的事情:

private function loadTable(){

    /* define what pages are acceptable*/
    $acceptablePages = array('green','red','blue');

    /* check if this->page is of an acceptable value*/
    if(in_array($this->page,$acceptablePages)) {

        /* if it is acceptable then load a function with the page passed as a parameter*/
        return $this->loadColour($this->page);
    }

    return false;

}