0

问题 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 文档中定义连接信息,这是一种更安全的方法。我该怎么做呢?

4

3 回答 3

1

不编写 OOP 代码本身并没有错,但是通过使用正确的 OOP 样式编码获得的好处可能非常有用。它将使您的代码更易于阅读、维护、调试和测试

PHPs 变量(除了一个超全局变量)和常量仅对每个请求有效。对于您要执行的操作,我什至不会使用常量。记住由define()is global创建的常量。如果您在任何地方听到/看到 global,那么在大多数情况下,您可能做错了 OOP。

在您的情况下(如果您想采用 OOP 路线)我会做的是创建一个引导文件,您可以在其中设置数据库连接。之后,您可以轻松地将数据库对象注入到需要它们的其他类/方法中。

另一件事请使用密码散列库。这样可以防止你搞砸了。我刚刚链接的密码库将在 PHP5.5 中实现。但是在你运行那个版本之前,请使用那个库,因为你的散列真的不是那么安全。sha1不适合散列密码,因为它意味着要快。至少使用bcrypt,但请再次使用链接密码库,因为太容易搞砸密码的散列。

另外:以防万一您使用 MySQL PDO 驱动程序禁用模拟准备语句

最后要真正回答你的问题:不,简单地将代码移动到一个类没有任何好处。如果你这样做而不考虑你在做什么或SOLID 原则,那么你的类只不过是一个花哨的命名空间。简单地将代码移动到一个类中并不能神奇地使它成为 OOP。

更新

引导文件

引导文件是包含在每个请求中的文件。它可用于设置应用程序运行所需的东西。一个例子(对于大多数(Web)应用程序)是数据库连接。但您也可以使用引导文件来设置一些 PHP 设置,例如启用错误报告。以及非常有用的自动加载。

在我的应用程序中,引导文件始终是第二个被访问的文件。每个请求的第一个index.php文件是文档根目录中的一个简单文件,它只做一件事:加载引导文件。所有其他 PHP 文件将保存在文档根目录之外。这将阻止您的 PHP 代码出于任何原因出现。服务器配置错误或其他。此设置看起来有点像以下目录结构:

/src
/app
  /public
    /index.php
  /bootstrap.php

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');

如您所见,我们可以继续将数据库连接传递给需要它的类/方法。这使我们能够轻松地将数据库连接换成其他东西来加快我们的单元测试。这种松散耦合还确保我们可以轻松地将数据库对象交换为其他对象,以防我们需要其他存储机制。

如果您想在实践中看到上述大部分内容,可以查看我目前正在从事的项目。如果您仍然想知道为什么 OOP 只有好处,您应该观看这些系列:

http://www.g-truc.net/post-0182.html

于 2013-01-16T18:47:42.517 回答
0

对象

基本上,对象只是常用函数和变量的集合,您可以将它们打包成单独的单元,以使您的生活更轻松。您的代码在数据库查询方面似乎有点重复,您可能会受益于围绕 PDO 编写/使用包装类来简化代码。

就个人而言,我已经使用这样的东西几年了,它对我很有帮助。您可能会发现它可以作为直接替代品,或者作为构建您自己的示例。

证书

我通常定义我的数据库凭据的方式是在一个专用文件中的一个数组中,并在设置连接后立即创建unset()数组。IE:

inc.db_cfg.php

<?php
$conn_info = array(
  'hostname' => 'mysql.domain.com',
  'username' => 'bob',
  'password' => '1234',
  'dbname' => 'mydb'
);

索引.php

<?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');在你的代码中没有问题,但是如果有人请求,Apache 的默认配置只是将文件作为纯文本提供http://mysite.com/db_cfg.inc

最后,对凭证没有特别要求unset(),但它不会伤害并满足我的偏执狂。

密码哈希

SHA1 已经从根本上被破坏了一段时间,您可以使用它crypt()来访问更好的算法,如 SHA256 或 SHA512,或者从互联网上获取bcrypt实现。

于 2013-01-16T19:27:42.153 回答
0

当您计划重用代码或能够重构代码以利用单个类的多个实例时,将现有代码转换为类最有用。在这个例子中,无法判断这样做是否真的对你有好处,但我的直觉是它不是。

类只有在使您的代码更加清晰和易于维护时才有用。对于像 PHP 这样的语言,您经常编写脚本来处理与应用程序中的任何其他代码完全不同的一次性事情,将其转换为类可能没有意义。

至于常量,是的,它们只对定义它们的页面有效。PHP 的引擎只检查通过它运行的页面,因此它在解析和执行时不知道您在其他页面中定义的常量页面。对此的解决方案与您的数据库凭据问题有关。

一种选择是定义一个包含文件,其中定义了这些常量,然后包含在需要它们的每个页面中。像这样的东西:

page1.php

define(SOMETHING, 'value');

page2.php

require('page1.php');
echo SOMETHING;

通过要求(包括,如果找不到文件则失败)page1.php,它在被解析和执行时被视为当前页面的一部分,因此其中包含的任何定义都将应用于该页面中的后续代码。

于 2013-01-16T18:41:43.493 回答