第1期 我在下面有这个代码,我一直在听人们谈论使用大量的课程。有什么好处,我把下面的代码作为一个类(我已经把数据转化为对象),我将如何去做呢? (我是OOP PHP的新手。)
try {
$connection = new PDO(DATA, USER, PASSWORD);
$connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $error) {
PDOcrash($error);
}
// Scrubbing remember data
$_POST['remember'] = (int)$_POST['remember'];
// Query the database for the unique salt
$query = $connection->prepare("SELECT id, salt FROM {$_SESSION['environment']->database}.system_user WHERE username = :username LIMIT 1");
$query->execute(array(':username' => $_POST['username']));
$security = $query->fetch(PDO::FETCH_OBJ);
$query->closeCursor();
// Form the hash using sha1 alrorithm
$_POST['password'] = sha1(sha1($security->salt) . sha1($_POST['password']));
$query = $connection->prepare("SELECT id, centre, reference, first_name, last_name FROM {$_SESSION['environment']->database}.system_user WHERE username = :username AND password = :password");
$query->execute(array(':username' => $_POST['username'], ':password' => $_POST['password']));
$_SESSION['user'] = $query->fetch(PDO::FETCH_OBJ);
$query->closeCursor();
第2期
对于此代码块:
try {
$connection = new PDO(DATA, USER, PASSWORD);
} catch (PDOException $error) {
PDOcrash($error);
}
我使用常量来定义我的连接细节,但是如果我直接在页面上定义它们,它们似乎只能工作。我认为常量会在整个系统中保持不变。如果我将define()
功能移动到之前遇到的页面,则它们无法正常工作。这是否意味着常量的范围是单页?我还听说你可以在一些单独的apache文件中定义连接信息,这是一种更安全的方法。我该怎么做呢?
答案 0 :(得分:1)
不写OOP代码perse没有错,但是使用正确的OOP样式编码可以获得的好处非常非常有用。它将使您的代码更易于阅读,维护,调试和测试!
PHPs变量(在这里和那里的超全局旁边)和常量仅对每个请求有效。对于你想要做的事情,我甚至不会使用常数。请记住,define()
创建的常量是全局。如果你在任何你知道的地方听到/看到全局,你可能在大多数情况下做错了OOP。
在您的情况下我会做什么(如果您想要进行OOP路由)是创建一个引导程序文件,您可以在其中设置数据库连接。之后,您可以轻松地inject the database object进入需要它们的其他类/方法。
请另外请 使用password hashing libary。这样可以防止你搞砸了。我刚刚链接到的密码lib将在PHP5.5中实现。但在运行该版本之前,请使用该库,因为您的哈希真的不那么安全。 sha1
不适合散列密码,因为它的速度很快。至少使用bcrypt
,但请再次使用链接密码库,因为它太容易搞乱密码的散列。
另外:以防您使用MySQL PDO驱动程序disable emulated prepared statements。
最后要真正回答你的问题:没有将简单的代码移到课堂上的好处。如果你这样做而不考虑你在做什么或SOLID principles你的课程只不过是一个奇特的命名空间。简单地将代码移动到一个类中并不会使魔术成为OOP。
<强>更新强>
引导程序文件是每个请求都包含的文件。它可用于设置应用程序所需的功能以便运行。此示例(对于大多数(Web)应用程序)是数据库连接。但您也可以使用引导文件来设置一些PHP设置,例如启用错误报告。非常有用的自动加载。
在我的应用程序中,引导程序文件始终是第二个被访问的文件。每个请求的第一个文件是文档根目录中的一个简单index.php
文件,它只执行一件事:加载引导程序文件。所有其他PHP文件将保留在文档根目录之外。这将阻止您的PHP代码出于任何原因出现。服务器配置错误或其他什么。此设置看起来有点像以下目录结构:
/src
/app
/public
/index.php
/bootstrap.php
doc根目录中index.php
文件唯一包含的内容是:
<?php
require __DIR__ . '/../bootstrap.php';
之后你可能有一个类似于这样的引导程序文件:
<?php
error_reporting(E_ALL);
// note that for production we would disable the displaying of errors and
// enable logging of errors
ini_set('display_errors', 1);
require_once __DIR__ . '/../src/bootstrap.php'
// btw also don't forget to set the encoding
$dbConnection = new PDO('DSN', 'username', 'password');
// now we can simply call a class and pass the database object as an argument
$user = new User($dbConnection);
$user->changePassword('new password');
// because we still have the database object we can simply reuse it for some other class
$page = new Page($dbConnection);
echo $page->render('home');
正如您所看到的,我们可以继续将数据库连接传递给需要它的类/方法。这使我们能够轻松地将数据库连接交换为其他内容,以加速我们的单元测试。这种松耦合还可以确保我们可以轻松地将数据库对象换成其他东西,以防我们需要其他存储机制。
如果您想在实践中看到上述大部分内容,可以查看我目前正在处理的the project。如果你仍然想知道为什么OOP只有好处,你应该看这些系列:
答案 1 :(得分:0)
当您计划重用代码或者能够重构代码以利用单个类的多个实例时,将现有代码转换为类非常有用。在这个例子中,不可能分辨出这样做是否真的对你有利,但我的预感是不是。
只有使类更清晰,易于维护,才能使用类。使用像PHP这样的语言,您经常编写脚本来处理与应用程序中任何其他代码完全不同的一次性事件,将它转换为类可能没有意义。
对于常量,是的,它们只对它们定义的页面有效.PHP的引擎只检查通过它运行的页面,所以它不知道你在其他地方的页面中定义的常量解析并执行页面。解决方案与您的数据库凭据问题有关。
有一个选项是定义一个包含这些常量的包含文件,然后将其包含在需要它们的每个页面中。像这样:
page1.php中
define(SOMETHING, 'value');
使page2.php
require('page1.php');
echo SOMETHING;
通过要求(包括,如果找不到文件而失败)page1.php,它在被解析和执行时被视为当前页面的一部分,因此其中包含的任何定义将适用于后面的代码页。
答案 2 :(得分:0)
对象,最基本的,只是常见功能和变量的集合,您可以将它们打包到单个单元中,以使您的生活更轻松。您的代码在数据库查询方面似乎有点重复,您可以通过在PDO周围编写/使用包装类来简化代码,从而获益。
就个人而言,我已经使用something like this几年了,而且它对我很有帮助。您可能会发现它可以作为替代品或构建您自己的示例。
我通常定义数据库凭据的方式是在专用文件的数组中,并在设置连接后立即unset()
数组。即:
<?php
$conn_info = array(
'hostname' => 'mysql.domain.com',
'username' => 'bob',
'password' => '1234',
'dbname' => 'mydb'
);
<?php
require('inc.db_cfg.php');
$uri = sprintf("mysql:host=%s;dbname=%s", $conn_info['hostname'], $conn_info['dbname']);
$this->dbh = new PDO($uri, $conn_info['username'], $conn_info['password']);
unset($conn_info, $uri);
您希望在变量中而不是直接在构造函数中定义数据库凭据的主要原因是,如果连接失败并且您的脚本抛出异常或错误,则堆栈跟踪/错误消息可能会打印出原始代码行包含您的用户名,密码,主机名以及您最有可能希望保密的其他位。
此外,您希望确保您的凭据存储在一个文件类型中,该文件类型不会以某人请求的原始文本格式输出。例如,回到“早期”,人们只需将其包含文件命名为db_cfg.inc
或类似的东西。您可以在代码中include('db_cfg.inc');
没有问题,但是如果有人要求http://mysite.com/db_cfg.inc
,则Apache的默认配置只是将文件作为纯文本提供。
最后,unset()
凭据并不是特别 ,但它并没有伤害和满足我的偏执狂。
SHA1已经基本上被破坏了一段时间,您可以使用crypt()
访问更好的算法,例如SHA256或SHA512,或者从互联网上的bcrypt实施中获取。{/ p>