我项目中的所有代码都是程序性的。它没有使用任何框架或任何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,我一直在阅读设计模式,但我似乎找不到任何适用于我的项目的东西。
我正在添加大量新代码块,类似于上面的块,我不想复制和粘贴,只是在这里和那里更改几个位,我有什么选择?
答案 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)
一个体面的框架将帮助您通过分离关注点来组织代码更好,但不一定强制执行最佳实践。在主观上,我说它需要亲身体验,并且在最佳实践根深蒂固之前犯了很多错误。
尝试将框架仅视为交付机制。最理想的是,您的代码不依赖于任何一个框架。这通常意味着使用组件来处理应用程序的不同方面,例如路由,验证,配置,事件,依赖性等。
我觉得你应该开始的是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 />";
}
}
}
答案 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
,如submitButton
,money
的值等于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);
}
这一切都取决于您如何定义预期的值。您可以将每个函数扩展到更具体的功能,例如将错误绑定到表单键,以便您可以在以后专门针对该输入。关键是要删除所有可能的复制,其中函数可以通过简单地要求他比较您期望的值来完成所有这些,并让他告诉实际存在哪个值。