<?php
include "config.php";
class Users extends Config {
public function login($username, $password) {
try {
$this->db->beginTransaction();
$stmt = $this->db->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ? LIMIT 1");
$stmt->execute(array($username, $password));
if($stmt->rowCount == 1) {
while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
header("Location: index.php?p=loggedin");
exit();
}
} else {
header("Location: index.php?p=false");
exit();
}
$this->db->commit();
} catch(PDOException $ex) {
$this->db->rollBack();
echo $ex->getMessage();
}
}
}
$users = new Users();
?>
Run Code Online (Sandbox Code Playgroud)
如您所见,我的代码有两种header()方法,其中一种方法重定向到登录页面,而另一种方法重定向到错误页面.
我相信据我所知,我的脚本应该根据我的输入重新定向到登录页面,这是正确的,但它的行为方式是出乎意料的.
它会重定向到错误页面而不是登录页面.请看一看,告诉我它不起作用的原因?谢谢!此外,如果您发现我的代码中存在任何缺陷,请随意提出一些批评,因为我希望改善自己.非常感谢.
Jim*_*mbo 49
我将发布一些有希望比上面那些帖子更有用的东西.这里有几种最佳实践可以让您在编码时更轻松; 当然,当你把头包裹起来之后.
首先,这看起来像是您尝试应用程序的身份验证部分.如果用户传递了正确的用户名和密码,则需要显示正确的页面.我不知道你的申请范围,所以我不打算提出大的改变.
看起来你手动包含你的文件.PHP有spl_autoload_register,如果你正在关注PSR-0(你真的应该看一下)意味着你可以将你的目录结构映射到你的类heirachy 1:1,并在你要求时自动为你解决类.因此,当您说new Object,或者甚至(在您的情况下)extends Config,如果您的Config班级位于您的最高级别,它将自动被找到并使用.这将涉及您了解命名空间.
一旦了解了命名空间的工作方式以及自动加载如何为您节省开发时间(我的意思是长期的重要时间),您就可以转到像composer这样的依赖管理工具.Composer基本上是您运行的脚本,它为您生成自动加载器,然后您在应用程序开始时需要做的就是require_once __DIR__ . "/vendor/autoload.php".但是说真的,看看一些自动加载教程 - 一旦你使用它们,你将永远不会回去,并且基本上会在你将来编写的每个应用程序中使用它们.
您也永远不需要输入include多次 - 如果找不到您尝试包含的文件,它只会抛出警告.看起来这个文件需要配置文件,所以你应该require_once在这种情况下使用 - 这意味着如果找不到这个文件你的代码就会致命(这似乎是你想要的).
那有什么不对class Users extends Config.至少做得好,至少有一个好的命名约定(类名称的上限).基本上,extends暗示是一种关系.你不要只延伸到获得额外的功能-这是一个代码味道.你在这里说a User是a Config.事实并非如此,如果您将来将此代码交给任何其他开发人员 - 他们就像"WAIT,WTF".希望以更好的方式.
您的目标是:在类中包含配置变量.所以,将它们传递给课程.我不知道你Config班上有什么,但你应该看看依赖注入模式 ; 这是一个教程.基本上,你可以Config通过DI(通过构造函数)传递你的对象,然后解耦你的代码,这样你就可以根据它自己的优点单独测试每个对象,而不是模拟其他对象.可测试的代码.依赖注入.谷歌一下.
所以,不要延长Config.改为通过您的配置:
class Users
{
/**
* @var Config
*/
protected $config;
/**
* @constructor
*
* @param Config $config The class configuration, duh
*/
public function __construct(Config $config)
{
$this->config = $config;
}
/** Snip **/
}
Run Code Online (Sandbox Code Playgroud)
另外,请查看phpdoc语法,以帮助您编写其他开发人员可以轻松理解和解析的注释代码.
您还使用了您真正不需要使用的事务SELECT.为什么不?因为事务允许您使用commit或rollback- 但是当您执行选择时,您不会更改任何数据.因此,执行交易毫无意义.所以删除它们,然后尝试通过a检索数据SELECT.
每个类,每个对象,都应该有一个改变的理由.它所做的一项任务就是这样.如果您有一些从数据库中读取的代码,比较一些字符串并保存到文件,那么您至少应该有3个类:一个从持久性中读取,一个执行比较,另一个保存到文件.这被称为单一责任原则,您可以阅读和谷歌.
考虑到这一点,这个单独的类不应该负责发送标题.在回报true或false使用这一个做的,而不是有类.这不是这个类的责任 - 这应该只是处理身份验证.
如果你选择了一个框架,你可以在你自己Controller或你的框架中执行此操作,这View取决于你对MVC模式的接近程度- 这对于网络应用程序来说实际上是不可能的(我把它放在那里为那里的肛门人员)但实际上 - 你应该分离你的顾虑,至少在你的代码库中遵守SRP.
我绝不是一个安全专家,但你不这样做既是您的用户名和密码传递给数据库.如果要对您应该使用的密码进行哈希处理,则只需User通过用户名从数据库中检索密码,然后计算密码是否与PHP代码中的哈希值匹配.这样您就不会将密码发送到数据库,这有助于(尽管只是一点点)反对SQL注入.PHP 5.5包含一些非常有用的password_*函数来帮助您,但由于您可能没有使用PHP 5.5,请查看password_compat库.
什么是SQL注入?来自Bobby Tables的更多信息,以及下面这个非常有用的图片.

这些只是一些指示,您可以向正确的方向前进,以获得更好的代码,您可以将其传递给了解其中的其他开发人员,您可以为此感到自豪.看一下像Symfony这样的框架,这样您就不必担心身份验证,自动加载以及类似的事情 - 这一切都是为您完成的.作曲家绝对是必须的.你需要开始调试你的代码行由行,var_dump()用var_dump(),直到您看到是不是你所期望的东西.调试101,它将帮助您,并帮助我们为您提供更多帮助.