程序PHP到哪里?

时间:2012-10-02 21:55:43

标签: php oop design-patterns frameworks

我项目中的所有代码都是程序性的。它没有使用任何框架或任何MVC结构。大多数PHP都是带有一些逻辑的表单处理程序。所以很多代码都是这样的:

<?php

require "headerFile.php";

$user = array(); // filled with user data

if (isset($_POST['submitButton'])) {
    if (isset($_POST['money'])) {
        if (is_numeric($_POST['money'])) { // I don't actually validate numbers this way
            if ($_POST['money'] <= $user['money']) {
                $query = mysql_query("SELECT * FROM someTable WHERE id={$user['id']}");

                if($result = mysql_fetch_array($query)) {
                    if ($someOtherCheck == $user['someOtherData']) {
                        /*
                         * run some queries, give user some item
                         *
                         */
                    } else {
                        echo "This isn't right.";
                    }
                } else {
                    echo "You don't have a row in some table!";
                }
            } else {
                echo "You don't have that much money!";
            }
        } else {
            echo "Enter a valid number";
        }
    } else {
        echo "Enter how much you want to wager.";
    }
}

// some hard coded form goes here

require "footerFile.php";

?>

这些表单中有超过一百个并且嵌套了处理程序,其中一些表示类似于更多/更少的条件。

我想开始使用OOP,我一直在阅读设计模式,但我似乎找不到任何适用于我的项目的东西。

我正在添加大量新代码块,类似于上面的块,我不想复制和粘贴,只是在这里和那里更改几个位,我有什么选择?

7 个答案:

答案 0 :(得分:2)

首先,如果您要复制并粘贴应该是 BIG RED FLAG 的代码。这应该是一个警告,而不是复制和粘贴,你需要编写一个可以使用的通用函数。

其次,现在是时候停止使用类似mysql_query的函数了。即使是PHP page也不鼓励使用这些功能。我会开始将你的SQL转移到更像OO的PDO。

当我继承了一个看起来你发布的代码的应用程序时,我写了一篇关于我开始处理事情的步骤的博客文章。它也可能对您有所帮助 - http://mattmccormick.ca/2011/10/13/how-to-refactor-a-php-application/

答案 1 :(得分:1)

OOP并不总是关于应用程序。它是关于可读性和结构。老实说,你在这里发布的代码有多可读?有很多事情发生,你需要花10分钟来解读它们。但是,如果您将其分解为具有类函数的类,您将能够浏览一些事物并知道发生了什么。

OOP并不是一直用于PHP,但它是你想要为几乎所有其他非静态加载语言做的事情。另外一个好处是,如果项目中有多个程序员,则可以读取代码。评论是你的朋友。

您最好选择使用带退货的功能。返回值,然后函数执行它需要做的任何事情。我个人会做类似

的事情

$类 - &GT;检查

如果错误

$这 - &GT; error_handler

并且函数错误处理程序执行你想要它做错误的任何事情,如果它的die或echo然后那样做,但你构建了错误处理程序,所以如果你想要改变它,你可能在一个地方而不是20。

答案 2 :(得分:1)

即使没有引入OOP,您也可以创建构建代码以便可读的奇迹。如果他们不相互依赖,就没有必要嵌套你的条件。

$form_is_valid = true;

if (!isset($_POST['submitButton'])) {
    echo "This isn't right.";
    $form_is_valid = false;
}

if (!isset($_POST['money'])) {
    echo "Enter how much you want to wager.";
    $form_is_valid = false;
} elseif (!is_numeric($_POST['money'])) {
    echo "Enter a valid number";
    $form_is_valid = false;
} elseif (!$_POST['money'] <= $user['money']) {
    echo "You don't have that much money!";
    $form_is_valid = false;
}

if ($form_is_valid) {
    do_stuff_here();
}

答案 3 :(得分:1)

关于框架

一个体面的框架将帮助您通过分离关注点来组织代码更好,但不一定强制执行最佳实践。在主观上,我说它需要亲身体验,并且在最佳实践根深蒂固之前犯了很多错误。

尝试将框架仅视为交付机制。最理想的是,您的代码不依赖于任何一个框架。这通常意味着使用组件来处理应用程序的不同方面,例如路由,验证,配置,事件,依赖性等。


关于OOP

我觉得你应该开始的是SOLID principle。这将帮助你,尽管不能保证,避免犯错,这会花费你很多时间。

最重要的是,您的对象应该只承担一项责任。例如 Product 对象不应该负责充当数据存储,持久化,处理订单等等。

另外一个重要的是依赖注入。这对于对您的课程进行单元测试非常重要(您应该习惯这样做)。简而言之,不要在类中构造依赖。事先构造它并通过构造函数参数或setter方法传递它。

构建应用程序的过程值得拥有自己的书籍,所以我不会尝试在这里编写所有内容。如果您遵循SOLID原则,那么您将成为更好的开发人员。


关于上面的代码

这种嵌套通常是一种气味,我可以理解为什么你会问这个问题......

步骤1是将验证分离到自己的服务中。在MVC意义上考虑这一点,至少,你的控制器只有[伪代码] if ($form->isValid()) { do something }。仅这一点就消除了你的大部分意大利面。

答案 4 :(得分:0)

看起来您的代码正在组合模型和视图层的某些组件。您正在对数据库运行查询,并且在同一个地方,您包括硬编码表单。因此,开始的一个好地方是将这些任务分成两个单独的类。例如,编写一个类来连接数据库并对其运行查询,编写另一个类来实际提供内容。

我对设计模式的建议是不要陷入细节之中。相反,尝试理解为什么某些模式非常有用,以及他们试图解决的问题。许多初学者在 how 中陷入了困境,当一个简单的解决方案足够时,他们最终会浪费这么多时间来学习框架的细微差别。

最后,当您阅读代码时,请留意可能构成类的内容。此外,请记住专业化是关键,通过构建非常专业的类,您正在构建可能在其他项目中使用的模块化组件,

答案 5 :(得分:0)

  

我想开始使用OOP而且我一直在阅读设计模式,但我似乎无法找到任何适用于我的项目。

你不必从patterns开始......了解基础知识,你可以在那里进步..

这是一个基本的例子

if (isset($_POST['submitButton'])) {

    $db = new \mysqli("localhost", "user", "pass", "db");

    $user = new User("Juddling Stack", 123456);
    $user->setMoney(500.01);

    $player = new PlayerRegister($db, $user);

    if (! isset($_POST['money']) || ! is_numeric($_POST['money']))
        $player->addError("Enter Valid Wager Money");

    if ($_POST['money'] <= $user['money']) {
        $player->addError("You don't have that much money!");
    }

    try {
        $player->doSQL();
    } catch ( BaseException $e ) {

        foreach ( $e->getError() as $error ) {
            echo $error, " <br />";
        }
    }
}

Classes Used

答案 6 :(得分:0)

让我们首先说明你遇到的问题不是使用OOP,而是调用programming-overhead或用程序员术语spaghetti-code

如果你经历了很多开销,意味着浪费时间写几乎完全相同的代码行,只有它的内容不同,但功能是相同的。然后开始切割与其功能相同的代码的每个和平,但区分其内容。

你说有更多要复制粘贴,甚至更复杂,我只会做form验证部分(我称之为第1阶段),这只是一个如何应用逻辑的简单示例通过提供预期的输入,为您完成所有工作。一个例子可能比其他例子更优雅。

以下所有代码均未经过测试

定位功能相同的代码的示例。

 // functionality on checking values is the same, but it's content is not
 if (isset($_POST['submitButton'])) {
   if (isset($_POST['money'])) {
     if (is_numeric($_POST['money'])) {

 // though every decision made by its content is only being produced once .. 
      } else
          echo "You don't have that much money!";
    } else
        echo "Enter a valid number";
} else
    echo "Enter how much you want to wager.";

现在的诀窍是找到一个逻辑上解决这个问题的解决方案。 PHP充满了内置函数,但首先要掌握如何解决它的想法。一个示例是让每个key,如submitButtonmoney的值等于not exists,如果没有设置/存在,让我们说null 。其次,您要将值与$_POST提供的密钥进行比较,因此无论如何......您的$_POST数组都是决策者。

关于如何使用jQuery方法构建$.extend()库以将默认值应用于键,可以看到一个敏锐的例子,这样一个键总是有一个值,并且始终是一个决定通过不先检查它是否存在。但PHP也是如此。

让我们默认值。

$_POST = array_merge(array(
  'submitButton' => null,
  'money' => 0,
  'etc' => '...'
, $_POST);

现在,构建一个验证此数组的函数要容易得多,因为您始终可以依赖于存在的值。

你说你有更多需要验证的表格,这个功能可以验证某些字段是否可以找到。

有效无效表单的正式表示形式可以是数组,例如

$valid_form = array(
  'submitButton' => array('not_null'),
  'money' => array('not_null','int'),
  'etc' => '...'
); 

要验证的功能是

function validateForm($values, $valid) {
  // error array to be returned
  $error = array();
  // let's iterate over each value, remember we defaulted the $_POST array with
  // all the fields it can have, so all fields should be iterated apon.
  foreach($values as $key => $value) {
    if(array_key_exist($key, $valid)) {
      // logic content can be used by different functions, switch
      // used here for simplicity
      foreach($valid[$key] as $validation) {
        switch($validation) {
          case 'not_null':
            if(is_null($value)) {
              $error[] = "error logic";
              continue; // skip rest
            }
          break;
          case 'etc':
            $error[] = "..";
          break;
        }
      }
    }
  }
  return $error ? $error : true; // true being valid
}

错误处理可以通过很多方式完成,只需要一个简单的例子(取决于该项目的扩展程度),您可以将错误内容绑定到验证密钥,例如

$vfe = $valid_form_errors = array( // $vfe for simlicity's sake
  '__no_error' => 'no error present for "%key%" validation',
  'not_null' => '%key% should not be null',
  'int' => '%key% expects to be an integer'
);

$valid_form = array(
  'submitButton' => array('not_null'),
  'money' => array('not_null','int'),
  'etc' => '...'
);

创建正式错误消息的函数

function error_msg($key, $validation) {
  global $vfe;
  // error exists?
  $eE = array_key_exists($validation,$vfe);
  return str_replace('%key%', $eE?$key:$validation, $vfe[$eE?$validation:'__no_error']);
}

在简单的开关中,错误逻辑是

  foreach($valid[$key] as $validation) {
    switch($validation) {
      case 'not_null':
        if(is_null($value))
          $error[] = error_msg($key, $validation);
      break;
      case 'etc':
        $error[] = "..";
      break;
    }
  }

那么你的代码如何使用不同的逻辑呢?

    // first stage ..
    $form_valid = validateForm($_POST, $valid_form);    
    if ($form_valid === true) {
      // second stage, same logic be applied as with validateForm, etc.
      if($_POST['money'] <= $user['money']) {
        $query = mysql_query("SELECT * FROM someTable WHERE id={$user['id']}");

        if($result = mysql_fetch_array($query)) {
            // third stage, same logic can be applied here..
            if ($someOtherCheck == $user['someOtherData']) {

            } else {
                echo "This isn't right.";
            }
        } else {
            echo "You don't have a row in some table!";
        }
    }
    else {
      $errors = $form_valid;
      // error handling here
      print_r($errors);
    }    

这一切都取决于您如何定义预期的值。您可以将每个函数扩展到更具体的功能,例如将错误绑定到表单键,以便您可以在以后专门针对该输入。关键是要删除所有可能的复制,其中函数可以通过简单地要求他比较您期望的值来完成所有这些,并让他告诉实际存在哪个值。