>以下文章摘自PHP&MySQL:新手到Ninja,第7版,这是学习所有工具,原理和技术的动手指南,以构建专业的Web应用程序。在该系列的最后一个教程中,您将学习如何将存储在MySQL数据库中的信息并在网页上显示供所有人查看。。
到目前为止,您已经编写了第一个PHP代码,并了解了MySQL(关系数据库引擎)的基础知识,而PHP是服务器端脚本语言。
>现在,您已经准备好学习如何一起使用这些工具来创建一个网站,用户可以从数据库中查看数据,甚至添加自己的数据。>
注意:如第3章所示,我在这里使用“ mysql”来参考数据库协议。您的PHP脚本也会做同样的事情。本章中有许多参考文献 - 在您将编写的PHP代码中,即使我们实际上是连接到MariadB数据库的“ MySQL”。。
大图
>在我们飞跃之前,值得一试,以清楚地了解我们的最终目标。我们可以使用两个强大的工具:PHP脚本语言和MySQL数据库引擎。重要的是要了解这些将如何融合在一起。>
>如上图所示,PHP脚本语言是说两种语言的介于之间。它处理页面请求并使用SQL查询从MySQL数据库中获取数据,就像您用来在第3章中创建笑话表的数据库一样。然后,它随着浏览器期望的良好格式的HTML页面而动态地吐出它。 >
>使您清楚地清楚,这是当您网站上的访问者的访问者时,会发生什么:
> >您应该创建一个新的用户帐户,只有在您的网站依赖的IJDB数据库上使用的特定特权。让我们现在就这样做。
创建用户,打开MySQL Workbench并连接到您的服务器。然后运行以下查询:CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';
第一个查询是相当自我解释的:它创建了一个名为ijdbuser的用户,并使用密码myPassword。用户名之后的%符号表示数据库可以从任何位置连接到。第二个查询可为用户提供完整的IJDB架构,因此该用户可以在IJDB架构中查看并修改所有表,列和数据,但无法访问其外部任何内容。
>现在已经创建了用户ijdbuser,我们可以使用它连接到数据库。可以与此用户在MySQL Workbench中建立连接,但是由于权限有限,因此最好使用V.JE帐户来保持MySQL Workbench。相反,我们将在从PHP脚本连接时使用新用户。>使用php
连接到mySQL 在您可以从MySQL数据库中检索内容以包含在网页中之前,您必须知道如何从PHP脚本内部建立与MySQL的连接。到目前为止,您已经使用了一个名为MySQL Workbench的应用程序来连接到您的数据库。就像MySQL Workbench可以直接连接到运行的MySQL Server一样,您自己的PHP脚本也可以。>客户端提供了标准化的方法
,因此,为了保持简单,我将在本章中使用术语
> mysql来参考数据库。 有三种从php连接到MySQL Server的方法:> mysql库
> mysqli库pdo库
>尽管大多数开发人员在发布PHP 5.0后立即看到了发生变化的原因,但尽管有实际上已经有效地是MySqli,但现在使用这些现在不存在的MySQL_*功能,网络上仍有数百个文章和代码示例。首选的图书馆已有十五年。
>遇到一个包含LINE MYSQL_CONNECT()的代码示例,请检查文章的日期。大概是从2000年代初开始,在编程中,您永远不应该相信任何古老的东西。事情一直在改变 - 这就是为什么这本书在其第七版中!
> 在PHP 5.0中,MySQLI库(代表“ MySQL改进”)被释放,以解决原始MySQL库中的某些局限性。您可以轻松地识别MySQLI的使用,因为代码将使用诸如mysqli_connect()和mysqli_query()。 在PHP 5.0中发布MySQLI库后不久,PHP 5.1发行了,并进行了大量更改,有助于塑造我们今天编写PHP的方式(主要是针对对象的编程,您会看到的本书的后期很多)。 PHP 5.1的主要变化之一是它引入了第三个库PDO(PHP数据对象),用于连接MySQL数据库。 PDO和MySQLI之间存在几个区别,但主要的是您可以使用PDO库将几乎所有数据库服务器连接到任何数据库服务器(例如Oracle Server或Microsoft SQL Server)。对于开发人员而言,这种通用方法的最大优势是,一旦您学习了如何使用库与MySQL数据库进行交互,那么与另一家数据库服务器进行交互非常简单。 可以说,为PDO编写代码更简单,并且有些细微差别可以使PDO代码更可读性 - 准备好语句中的参数为主要好处。 (不用担心,我将稍后解释这意味着什么。)>
由于这些原因,最近的PHP项目使用PDO库,这是我将向您展示如何在本书中使用的库。有关差异的更多信息,请查看SitePoint文章“重新引入PDO - 正确访问PHP数据库的正确方法”。>在那段小历史课之后,您可能渴望回到编写代码。这是您使用PDO建立与MySQL Server的连接的方式:
>>目前,将新的PDO视为内置功能,就像我们在第2章中使用的RAND函数一样。如果您在想“嘿,函数在他们的范围内就不可能具有
名字!”,您比普通的熊聪明,我将在稍后确切地说明这里发生了什么。无论如何,它需要三个参数:
>您可能可以查看最后两个参数的情况:它们是您本章之前创建的用户名和密码。
>CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';第一个论点有点复杂。 dbName = ijdb part告诉PDO使用数据库(也称为a
架构
),称为ijdb。从PHP运行的任何查询都将默认为该模式中的表。从笑话中选择 * *将从ijdb架构中的笑话表中选择记录。> >即使您已经熟悉PHP,PDO和MySQL,主机= mysql部分看起来令人困惑。通常,这将是host = localhost(参考本地计算机,运行php的同一台计算机)或指向数据库所在的特定域名,例如host = sitepoint.com。 为什么它是主机= mysql,MySQL在这里指的是什么?在docker中,每个
>服务被赋予一个名称。如果您检查配置服务器的Docker-compose.yml文件,则数据库服务称为MySQL,在Docker中,一个服务可以使用另一个服务的名称连接到另一个服务。 除了参数之外,这里重要的是,新PDO返回的值存储在名为$ pdo的变量中。
> MySQL Server是与Web服务器完全独立的软件。因此,我们必须考虑由于网络中断而导致服务器可能无法使用或无法访问的可能性,或者因为您提供的用户名/密码组合被服务器拒绝,或者是因为您只是忘记启动MySQL Server!在这种情况下,新的PDO不会运行,并且会抛出PHP例外。> >
注意:至少在默认情况下,可以配置PHP,以使其无例外,并且根本不会连接。这通常不是理想的行为,因为它使得弄清楚出了什么问题变得更加困难。>如果您想知道“抛出PHP例外”意味着什么,请自己做好准备!您将要发现PHP语言的更多功能。
> php例外是当您告诉PHP执行任务并且无法执行任务时,会发生什么。 PHP会尝试做所讲的事情,但会失败;为了告诉您失败,它会给您带来例外。一个例外仅仅是PHP仅带有特定的错误消息崩溃。当抛出例外时,PHP停止。将执行错误之后没有代码行。
>作为负责任的开发人员,您的工作是捕获该异常并做些事情以使程序可以继续。
>注意:如果您没有捕获异常,则PHP将停止运行您的PHP脚本并显示出惊人的丑陋错误消息。该错误消息甚至会揭示脚本的代码,这些代码引发了错误。在这种情况下,该代码包含您的MySQL用户名和密码,因此避免用户看到的错误消息尤其重要! 为了捕获异常,您应该包围可能会尝试尝试的代码。
>您可以尝试一个尝试…像if…else语句一样捕获语句,除了第二个代码块是第一个代码无法运行的情况。>困惑了吗?我知道我正在向您扔很多新概念(没有双关语),但是如果我把它们放在一起并向您展示我们拥有的东西,那将是更有意义的:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';如您所见,此代码是一个尝试…catch语句。在顶部的尝试块中,我们尝试使用新PDO连接到数据库。如果成功成功,我们将所得的PDO对象存储在$ PDO中,以便我们可以使用新的数据库连接。如果连接成功,则将$输出变量设置为稍后显示的消息。
>重要的是,在尝试……捕获语句中,抛出异常后的任何代码都不会被执行。在这种情况下,如果连接到数据库会引发异常(也许密码是错误的,或者服务器未响应),则$输出变量永远不会设置为“已建立数据库连接”。
如果我们的数据库连接尝试失败,PHP将抛出PDOException,这是新PDO投掷的例外类型。因此,我们的捕获块说,它将捕获PdoException(并将其存储在名为$ e的变量中)。在该块内部,我们设置了变量$输出以包含有关出了什么问题的消息。> 但是,此错误消息并不是特别有用。它告诉我们的只是PDO无法连接到数据库服务器。最好有一些有关为什么这样的信息 - 例如,因为用户名和密码无效。
>new PDO('mysql:host=hostname;dbname=database', 'username', 'password')$ e变量包含有关发生的异常的详细信息,包括描述问题的错误消息。我们可以使用串联将其添加到输出变量:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';
>注意:$ e变量不是字符串,而是对象。我们将不久的将来意味着什么。但是,目前,您需要知道的是,代码$ e-> getMessage()基于发生的特定异常获取错误消息。 > if…else语句,一个尝试的两个分支之一…catch语句可以运行。 TRY块中的代码将成功执行,或者捕获块中的代码将运行。不管数据库连接是否成功,$输出变量中都会有一条消息 - 错误消息或说明连接成功的消息。
>最后,无论尝试块是成功的还是捕获块运行,都包括模板输出。html.php。这是一个通用模板,仅在页面上显示一些文本:>
可以在示例中找到完整的代码:mysql-connect。
>new PDO('mysql:host=hostname;dbname=database', 'username', 'password')当包含模板时,它将显示错误消息或“建立数据库连接”消息。
我希望上述代码现在对您有意义。随意回到本节的开始,如果您迷路了,请再次阅读全部,因为其中有一些棘手的概念。但是,一旦您对代码有坚定的抓地力,您可能会意识到,我仍然留下了一个无法解释的神秘:PDOS。新的PDO到底是什么,当我说它返回一个“ PDO对象”时,一个对象到底是什么?
>>
注意:所有下载的示例代码都包含一个名为ijdb_sample的架构和一个称为ijdb_sample的用户,以便您能够运行它,无论您所谓的架构和用户如何。将包含数据库的文件作为数据库.sql提供,您可以导入。>
如果您使用提供的基于Web的示例代码查看器,则在加载示例时将创建IDBJ_Sample数据库,但是当您查看另一个示例时,该模式的任何更改都将丢失。 (您可以弄乱事情,然后切换到另一个样本并将其重置,但是如果要保留任何更改,请将它们制作在您创建的模式中。) 如果要使用MySQL Workbench将示例数据加载到您的架构中,请通过选择数据导入/还原来从项目目录中导入database.sql。然后从独立文件中选择导入,浏览到database.sql,然后在默认目标架构中选择您的架构名称。如果您创建了任何具有相同名称的表格,它们将被覆盖并且所有记录都丢失了。>面向对象的编程中的速成课程 >您可能已经注意到“对象”一词开始在上一节中渗入我的词汇。 PDO是php数据
对象扩展,而新的PDO返回PDO对象。在本节中,我想解释哪些对象是有意义的。
>>也许您在自己的PHP或编程中遇到了术语面向对象的编程(OOP)。 OOP是一种先进的编程风格,特别适合用很多部分构建真正复杂的程序。当今有效使用中的大多数编程语言都支持OOP。他们中的一些人甚至需要
创建对象很像调用函数。实际上,您已经看过如何做:
> >新关键字告诉PHP您要创建一个新对象。然后,您离开空间并指定一个类名称,该名称告诉PHP您要创建哪种类型的对象。一类是PHP将遵循的一组指令来创建对象。您可以将班级视为食谱,例如蛋糕,而物体是遵循食谱产生的实际蛋糕。不同的类可以产生不同的物体,就像不同的食谱可以产生不同的菜肴一样。 当PHP带有可以调用的一堆内置功能时,PHP带有可以从中创建对象的类库。因此,新的PDO告诉PHP创建一个新的PDO对象 - 即内置PDO类的新对象。
在PHP中,对象是一个值,就像字符串,数字或数组一样。您可以将对象存储在变量中,也可以将其作为参数传递给函数 - 所有与其他PHP值相同的事情。但是,对象具有一些有用的其他功能。>
首先,一个对象的行为与数组相似,因为它充当了其他值的容器。正如我们在第2章中看到的那样,您可以通过指定其索引来访问数组内部的值(例如,$生日['Kevin'])。当涉及对象时,概念相似,但名称和代码不同。我们不是访问存储在数组索引中的值,而是说我们正在访问对象的属性。我们使用箭头符号( - >) - 例如,$ myObject-> someproperty:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';>通常用于存储
值的列表(例如生日的数组),而对象则用于存储>相关>值的列表(例如,例如,数据库连接的属性)。不过,如果这是所有对象都可以的,那么它们对它们没有太大的意义:我们可能会使用一个数组来存储这些值,对吗?当然,对象会做更多的。 除了存储属性及其值集合外,对象还可以包含一组函数,旨在带来更多有用的功能。存储在对象中的函数称为一种方法(如果您问我,编程世界中更令人困惑的名称之一)。方法只是类中的功能。更令人困惑的是,当我们开始编写自己的课程时,使用函数关键字定义方法!即使是经验丰富的开发人员,也经常错误地使用函数
和方法互换。
要调用一种方法,我们再次使用箭头符号 - $ myobject-> somemethod():
> 但是,目前,我们将坚持使用PHP随附的类。让我们继续使用我们创建的PDO对象,并通过调用其方法之一来查看我们可以做什么。
>new PDO('mysql:host=hostname;dbname=database', 'username', 'password')配置连接
到目前为止,我向您展示了如何创建PDO对象以与您的MySQL数据库建立连接,以及当出现问题时如何显示有意义的错误消息:
但是,假设连接成功,则需要在使用之前对其进行配置。您可以通过调用新PDO对象的某些方法来配置连接。>在将查询发送到数据库之前,我们需要配置数据库连接的字符编码。正如我在第2章中简要提到的那样,您应该在网站中使用UTF-8编码的文本,以最大程度地提高用户在填写网站上表格时可以使用的字符范围。默认情况下,当PHP连接到MySQL时,它使用更简单的ISO-8859-1(或Latin-1)编码而不是UTF-8。如果我们要保持原样,我们将无法轻易插入中文,阿拉伯语或大多数英语角色。
>
>即使您100%确定您的网站只能由英语说话者使用,但没有设置角色集引起的其他问题。如果您的网页未设置为UTF-8,那么当人们将某些字符(例如卷曲引号)写入文本框时,您会遇到问题,因为它们会以不同的字符出现在数据库中。因此,我们现在需要设置我们的新PDO对象以使用UTF-8编码。
>我们可以指示PHP通过附加; charset = utf8mb4询问数据库时使用UTF-8。只要您的PHP脚本也以UTF-8发送到浏览器(这是最近的PHP版本中的默认值):
>
注意:如果您去搜索,您会找到不同的方法来设置Charset,并且本书的早期版本指示您使用此代码:CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';
这是因为在PHP 5.3.6之前,PHP无法正确应用Charset选项。由于您实际上要使用的任何PHP版本都解决了这一点,因此将Charset设置为连接字符串的一部分是首选选项。 我们用来连接到mySQL的完整代码,然后配置该连接,如下所示。
>new PDO('mysql:host=hostname;dbname=database', 'username', 'password')>示例:mysql-connect-complete
>在您的浏览器中启动此示例。 (如果您将数据库代码放入index.php中的public Directory和output.html.php文件中的模板目录中,则页面的URL为https://v.je/。)
>如果您的服务器启动并运行,并且一切正常,则应看到一条表示成功的消息。>
$pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword');>如果PHP无法连接到您的MySQL Server,或者提供的用户名和密码不正确,则将看到与下面显示的类似屏幕。为了确保您的错误处理代码正常运行,您可能需要故意拼写密码以测试它。
>多亏了我们的捕获块,数据库中的错误消息已包含在页面上:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';
方法getMessage()返回一条消息,描述发生的异常。还有一些其他方法(包括getFile()和getline())用于返回抛出异常的文件名和行号。您可以生成一个非常详细的错误消息:
new PDO('mysql:host=hostname;dbname=database', 'username', 'password')
>如果您有一个包含数十个文件的大型网站,这将非常有用。错误消息将准确地告诉您要查看哪个文件以及错误在哪一行中。
如果您很好奇,请尝试在数据库连接代码中插入其他一些错误(例如,拼写错误的数据库名称),并观察结果的详细错误消息。完成后,数据库连接正常工作,请返回简单的错误消息。这样,如果您的数据库服务器出现了真正的问题,您的访问者就不会被技术gobbledygook轰炸。>
>有了建立的连接并选择了数据库,您就可以开始使用存储在数据库中的数据。>
>您可能想知道脚本完成执行后,与MySQL Server的连接会发生什么。如果您真的愿意,则可以通过丢弃代表您连接的PDO对象来强迫PHP与服务器断开连接。您可以通过设置包含对象为null的变量来做到这一点:> 也就 >使用php
发送SQL查询 在第3章中,我们使用MySQL Workbench连接到MySQL数据库服务器,这使我们能够键入SQL查询(命令)并立即查看这些查询的结果。 PDO对象提供了类似的机制 - EXEC方法:$pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword');
>在这里,$ QUERY是一个字符串,包含您要执行的任何SQL查询。> 如您所知,如果执行查询存在问题(例如,如果您在SQL查询中犯了打字错误),则此方法将为您添加PDOException供您捕获。>
考虑以下示例,该示例试图产生我们在第3章中创建的笑话表请注意,我们使用相同的尝试…捕获语句技术来处理查询产生的可能的错误。可以使用多次尝试…捕获块显示不同的错误消息 - 一条用于连接,其中一条用于查询 - 但这可能会导致相当多的额外代码。
try { ⋮ do something risky } catch (ExceptionType $e) { ⋮ handle the exception }> 相反,我选择使用相同的尝试语句来包含连接和查询。尝试…捕获块一旦发生错误就会停止执行代码,因此,如果在数据库连接期间发生错误,则$ pdo-> exec($ run)行将永远不会运行,以确保如果将查询发送到数据库,必须建立连接。
>这种方法使我们对显示的错误消息的控制权更少,但是节省了每个数据库操作的键入语句。在本书的稍后,我们将将它们分解为不同的块,但就目前而言,将所有数据库操作保留在同一尝试块中。
此示例还使用GetMessage方法从MySQL Server检索详细的错误消息。下图显示了例如,笑话表已经存在时显示的错误。>
对于删除,插入和更新查询(用于修改存储的数据),EXEC方法返回受查询影响的表行(条目)的数量。考虑以下SQL命令,我们在第3章中使用的命令来设置包含“程序员”一词的所有笑话的日期。
>示例:mysql-update
>通过存储从$ aventedrows中的Exec方法返回的值,我们可以在$ output变量中使用变量在模板中打印。
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';下图显示了此示例的输出,假设您的数据库中只有一个“程序员”笑话。
>如果您刷新页面以再次运行相同的查询,则应看到消息更改,如下图所示。这表明没有排的更新,因为将新日期应用于笑话与现有日期相同。
>选择的查询对待有所不同,因为它们可以检索大量数据,而PHP提供了处理该信息的方法。
>
>处理选择结果集
对于大多数SQL查询,EXEC方法工作正常。该查询对您的数据库有所作为,您会从方法的返回值中获得受影响的行(如果有)。但是,选择查询需要比执行更奇特的东西。您会记得,精选查询用于在数据库中查看存储的数据。 SELECT查询不仅只影响数据库,还具有结果 - 我们需要一种返回它们的方法。
查询方法看起来就像EXEC一样,因为它接受SQL查询作为要发送到数据库服务器的参数。但是,它返回的是一个pdostatement对象,它表示一个结果集,其中包含从查询中返回的所有行(条目)的列表:提供处理查询时没有遇到错误,该代码将将结果集(以Pdostatement对象的形式)存储到变量$结果中。此结果集包含笑话表中存储的所有笑话的文字。由于数据库中的笑话数量没有实际限制,因此结果集可能很大。
>>我在第2章中提到,当我们需要循环时,while循环是一个有用的控制结构,但不知道多少次。我们不能将循环使用,因为我们不知道返回的查询有多少记录。实际上,您可以在此处使用一段时间循环来处理结果的行一次设置:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';while循环的条件可能与您习惯的条件有所不同,因此让我解释一下它的工作原理。将条件本身视为陈述:
new PDO('mysql:host=hostname;dbname=database', 'username', 'password')pdostatement对象的获取方法将结果集中的下一行返回为数组(我们在第2章中讨论了数组)。当结果集中没有更多的行时,Fetch返回false。 (这是一种要求pdo对象做某件事的情况 - 因为结果集中没有行剩下时,fetch不能返回下一行 - 将
> not 。 现在,上面的语句将值分配给$ ROW变量,但同时,该语句总体上具有相同的值。这就是让您在循环中使用该语句作为条件的原因。由于段循环将继续循环直到其条件评估为false,因此此循环将与结果集中的行一样多次发生,每次循环执行时,$ row都会占据下一行的值。每次循环运行时,剩下的所有要弄清楚的是如何从$行变量中检索值。
> 由Fetth返回的结果集的行表示为关联阵列,其指数以结果集中的表列命名。如果我们的结果集中$ row是一行,则$ row ['joketext']是该行的joketext列中的值。
>我们在此代码中的目标是存储所有笑话的文本,以便我们可以将其显示在PHP模板中。最好的方法是将每个笑话作为新项目存储在数组中,
>随着笑话从数据库中撤出,我们现在可以将它们传递到PHP模板笑话.html.php。
总而言之,这是到目前为止的控制器的代码:$pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword');>
$笑话变量是存储笑话列表的数组。如果您在PHP中写下了数组的内容,则看起来像这样:
但是,数据已从数据库中检索到数据,而不是在代码中手动输入。
>您会注意到,设置了两个不同的变量 - $笑话和$错误 - 具体取决于是否成功执行了Try Block。 在jokes.html.php模板中,我们需要显示$ jokes数组的内容或$错误变量中包含的错误消息。>检查是否已分配了一个变量,我们可以使用以前使用的ISSET函数来检查是否已提交表单。该模板可以包括一个if语句以确定是显示错误还是笑话列表:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';>这里没有什么新的,但是要显示笑话,我们需要显示$笑话阵列的内容。与我们使用的其他变量不同,到目前为止,$ jokes数组不仅包含一个值。
>
处理PHP中数组的最常见方法是使用循环。我们已经在循环和循环时已经看到。 foreach循环特别有助于处理数组:
new PDO('mysql:host=hostname;dbname=database', 'username', 'password')而不是条件,括号在foreach循环的顶部包含一个数组,然后是关键字为AS,然后是新变量的名称,该名称将用于依次存储数组的每个项目。然后,为阵列中的每个项目执行循环的主体。每当该项目存储在指定变量中,以便代码可以直接访问它。
>
>通常,在php模板中使用foreach循环依次显示阵列的每个项目。这可能是如何寻找我们的$笑话阵列的方式:
$pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword');>使用PHP代码的这种混合物来描述循环和HTML代码以显示它,代码看起来不整洁。因此,通常使用另一种方法来编写模板中的foreach循环:
>
try { ⋮ do something risky } catch (ExceptionType $e) { ⋮ handle the exception }>这两个代码在功能上是相同的,但是与HTML代码混合时,后者看起来更友好。这是代码的这种形式在模板中的外观:
> if语句可以完成同样的事情,通过避免括号来查看内部HTML模板内部更好。
try { $pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', ’mypassword’); $output = 'Database connection established.'; } catch (PDOException $e) { $output = 'Unable to connect to the database server.'; } include __DIR__ . '/../templates/output.html.php';
>使用这些新工具,我们可以编写模板以显示笑话的列表。
try { $pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword'); $output = 'Database connection established.'; } catch (PDOException $e) { $output = 'Unable to connect to the database server: ' . $e->getMessage(); } include __DIR__ . '/../templates/output.html.php';>示例:mysql-listjokes
$要么在页面上显示$错误文本,要么在块引用(
)中显示的每个笑话都显示在段落()中,因为我们在此中有效地引用了每个笑话的作者页。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Script Output</title> </head> <body> <?php echo $output; ?> </body> </html>>由于笑话可能包含可以解释为HTML代码的字符(例如,或&),因此我们必须使用htmlspecialchars来确保它们被翻译成HTML字符实体(即,&lt;&gt;&gt;&gt;&gt;&gt; ;下面的图像显示了此页面一旦您在数据库中添加了几个笑话后的外观。
>
记得我们如何在控制器中使用一个时循环以一次设置一个行中的行中的行?
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';事实证明,pdostatement对象的行为就像阵列一样,当您将它们传递到foreach循环时。因此,您可以使用foreach循环而不是while循环稍微简化数据库处理代码:>
new PDO('mysql:host=hostname;dbname=database', 'username', 'password')>我将在本书的其余部分中使用此整形词。 PHP提供的另一种整洁的工具是调用Echo命令的速记方式,如您已经看到的那样,我们需要经常使用。我们的回声陈述看起来像这样:>我们可以使用以下方式:
>这完全是相同的。 $pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', 'mypassword'); 这是一个使用速记回声的更新模板。
>示例:mysql-listjokes-shorthand
try { ⋮ do something risky } catch (ExceptionType $e) { ⋮ handle the exception }>从此适用时,我将使用速记符号。
> 注意:在5.4之前的PHP版本中,此速记符号需要启用相当不常见的PHP设置,因此出于兼容的原因而劝阻它。使用速记符号可能会导致您的代码从启用的服务器移动到没有的服务器时停止工作。 >try { $pdo = new PDO('mysql:host=mysql;dbname=ijdb', 'ijdbuser', ’mypassword’); $output = 'Database connection established.'; } catch (PDOException $e) { $output = 'Unable to connect to the database server.'; } include __DIR__ . '/../templates/output.html.php';截至PHP 5.4(因此,您实际上将遇到这些天的任何版本),无论PHP设置如何。提前思考 在我们刚刚查看的示例中,我们创建了一个模板jokes.html.php,其中包含显示页面所需的所有HTML。但是,随着我们网站的增长,我们将添加更多页面。当然,我们当然希望人们能够在网站上添加笑话,我们还需要一个带有一些介绍性文本的主页,一个带有所有者的联系方式的页面,并且随着网站的增长,也许甚至可能人们可以登录到网站的页面。
>>我在这里跳了很多,但是考虑到项目的发展始终值得一提。如果我们应用方法,我们只是将jokes.html.php用于其余模板 - addjoke.html.php,home.html.php,contact.html.php,login.html.php等等 - 我们'最终有很多重复的代码。> 网站上的每个页面都需要一个模板,看起来像这样的模板:
>作为程序员,重复代码是您可以做的最糟糕的事情之一。实际上,程序员通常是指干燥原则,该原则代表“不要重复自己”。如果您发现自己重复了代码的部分,几乎可以肯定有一个更好的解决方案。
>所有最好的程序员都是懒惰的,重复代码意味着重复工作。使用此副本/粘贴方法作为模板,该网站非常难以维护。想象一下,我们要在每个页面上出现一个页脚和一个导航部分。现在,我们的模板看起来像这样:
CREATE USER 'ijdbuser'@'%' IDENTIFIED BY 'mypassword'; GRANT ALL PRIVILEGES ON `ijdb`.* TO 'ijdbuser'@'%';>我们将在2022年遇到问题!如果网站上所有页面的模板 - 例如,jokes.html.php addjoke.html.php,home.html.php,contact.html.php andlogin.html.php-将版权通知中的年份更新为“ 2022”,您需要打开每个模板并更改日期。
>我们可能会很聪明,并从服务器的时钟(echo date('y');如果您很好奇!)动态读取日期,以避免此问题,但是如果我们想添加<script> tag,该怎么办每个页面都包含在内吗?还是向菜单添加新链接?我们仍然需要打开每个模板文件并将其更改!</script>
>更改五个或六个模板可能有点烦人,但这不会带来很多问题。但是,如果网站生长到数十个或数百页,该怎么办?每次您想添加链接到菜单时,您都必须打开每个模板并更改它。
这个问题可以用一系列包含语句来解决。例如:
new PDO('mysql:host=hostname;dbname=database', 'username', 'password')>但是,这种方法需要千里眼:我们需要准确地预测将来可能需要进行的更改,并且使用相关的陈述包括我们预见的更改的位置。 例如,在上面的示例中,通过将它们添加到nav.html.php中添加新的菜单条目很容易,但是在每个页面中添加