PHP和MySQL:最佳实践

6

今天我开始了解 PHP 和 MySQL 技术。基本上,我有一个空白页面,需要从数据库中查找 id 并填充一些内容。因此,在我的主页上有一个 URL,看起来像这样:

<a href="content/display.php?id=id1">

然后在我的display.php文件中,我有以下内容:

<?php
    include '../includes/header.php';
    $id = $_GET['id'];
    $mysqli = new mysqli('localhost','username','password','dbname');
    if($result = $mysqli->query("SELECT * FROM portfolio WHERE id='".$id."'"))
    {
        while($row = $result->fetch_object())
        {
            $head = $row->head;
            $img1 = $row->img1;
            $img2 = $row->img2;
            $img_url = $row->imgurl;
            $img_thumb = $row->imgthumb;
            $vid = $row->vid;
            $swf = $row->swf;
            $url = $row->url;
            $url_text = $row->urltext;
            $text = $row->text;
        }
    }
    else echo $mysqli->error;
?>

这是一个稀疏表格,因为并非所有字段都有信息(许多可能为空)。基本上它们包含文件名,然后在HTML中,我有类似以下代码:

if(isset($img1))
                    {
                        echo '<img src="images/'.$img1.'" />';
                    }

有几个问题:

  1. 这是最好的方法吗?
  2. 每次我访问display.php时,我都要重新打开数据库连接,对吧?那不太好...
  3. 我选择将文件名放在数据库中,而不是整个路径名,甚至是实际文件本身,考虑到如果我更改文件名,我可以进入数据库并更新要更改的文件。如果我更改路径,我只需在html中更改一次即可。这是最好的想法吗?

谢谢!


重新打开数据库连接是常见的做法,这应该不会有太大的影响。但我想知道为什么你想要将对象的每个属性都存储在另一个变量中? - Wrikken
我猜我不必把整个站点都包在那个while循环中...虽然我可以这样做。 - JPC
4个回答

7

1) 不是的,虽然这是初学者最容易入门的方法。当你对基础知识感到舒适后,应花些时间考虑不同的应用程序结构方法。最重要的规则是分离关注点。不要将数据库代码与业务逻辑代码混合在一起,也不要将演示代码混合其中。但像我说的,这不是你第一天就应该担心的事情。现在只需学习基础知识即可。

2) 实际上没有其他方法。对于Web应用程序,每个来自浏览器的请求都像一个单独的应用程序运行。有可能使用所谓的持久化数据库连接,但就像前面所述,这不是你第一天需要处理的问题,因为它们需要特定的Web服务器配置。目前只需使用常规连接即可。

3) 这是相当明智的想法。您还可以将图像路径定义为PHP常量,以便在需要更改时,只需更改此一个常量即可。

4) sAc在他的答案中所说的非常重要。了解SQL注入及其如何预防。


我熟悉MVC模式,但是对PHP还比较新手。我曾经用过Struts 2框架,它的设计思路是将业务逻辑、数据和表现层进行分离。为了以后的参考,我想学习如何在PHP中实现这种设计模式。请问有没有好的指南或教程可以推荐?谢谢! - JPC
哦,那样的话,我们就完全是在谈论不同的事情了 :)PHP有几个MVC框架可供选择,它们的实现细节差异很大。其中一个非常受欢迎的是Zend Framework,许多人说它实际上是一组松散耦合的类。另一方面,还有像Symfony这样实现“按约定配置”的框架。你肯定会找到适合你需求的东西。 - Mchl
@Col. Shrapnel 我还是比较新的这个网站和回答协议。我没有意识到我只能选择一个答案。 - JPC
PHP世界与Java世界有所不同。在PHP 5.3中,使用了phar文件格式,理论上可以提供与.war相同的好处。我从未见过它被使用。要在服务器上安装PHP应用程序,通常需要上传应用程序包含的所有文件。这可能是一项繁琐而棘手的任务,因此版本控制和持续集成工具非常有帮助。 Zend Framework(可能还有其他框架)有一个命令行工具,可以为您完成许多“设置新项目”的工作。您可以在几秒钟内获得一个功能齐全的应用程序。尽管它只显示一个静态页面 ;) - Mchl
这就是为什么我们做PHP工作的收入比做Java工作的收入少啦 ;) - Mchl
显示剩余2条评论

6

我已经使用过jdbc的预处理语句,但是对于php来说还不太熟悉。我会去查一下。由于我的id不是int类型,所以mysql_real_escape_string是用来做什么的呢?谢谢。 - JPC
@JPC:是的,你可以使用mysql_real_escape_string - Sarfraz

1

SQL注入和预编译语句已经被提到了。还有一个要补充的是:

else echo $mysqli->error;

将其更改为:

else trigger_error($mysqli->error,E_USER_ERROR);

为什么这样做呢?因为访问者不应该知道你的数据库,也无法修复错误,所以他们根本不应该看到它。这样,你就可以在开发时安全地使用 display_errors,而在实际网站上,display_errors 是关闭的,并且你可以将错误记录在错误日志中。


错误信息会被记录在哪里?我需要在哪里配置display_errors和log_errors吗? - JPC
我认为实际上最好的方法是将所有错误转换为 ErrorExceptions,如此处所述:http://php.net/manual/en/class.errorexception.php,但这又是一个更高级的话题。 - Mchl
1
@Mchl 异常更多地是错误处理,而 Wrikken 谈论的是错误跟踪。这是不同的世界,彼此不干扰。实际上,您可以在同一脚本中同时使用两者。 - Your Common Sense
@JPC:是的,配置display_errorslog_errorserror_log(在php.ini、Web服务器的vhost配置或.htacces文件中)。 @Mchl:如果您的应用程序设计为在另一个位置处理错误,则ErrorExceptions是可以接受的,因此它应该“向上走”。如果在这种情况下期望的结果是“如果查询失败,则不打印任何内容”,则抛出错误条件是不必要的,因为您正在现场处理它。但是,由于OP正在学习a.t.m,因此确实明智地了解异常及其使用方法。还有Col. Shrapnel所说的:) - Wrikken

1

看起来你已经对自己想做的有了很好的掌握。我不知道你有多少开发背景,但学习关于 MVC 在 PHP 中的使用是一个好主意,比如 CakePHP、Fuse,甚至 Zend Framework(呕吐!!!)。我会为你节省更强大的应用程序的时间,通过预定义所有基本的数据库接口、模板处理和会话处理,让你担心更高级别的问题,比如午餐吃什么! :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接