Linux编程之:五个常见PHP数据库问题
揭露🗯 PHP 应用程序中出【xù zhōng chū】现的五个常见数据库【shù jù kù】📃问题🍎 —— 包括数📱据库【jù kù】模式设计、数据库【shù jù kù】📃访问和使用数【shǐ yòng shù】据库【jù kù】📃的业务逻辑代【luó jí dài】码🛏 —— 以及它🕕们的解【men de jiě】决方案。
如果只【rú guǒ zhī】有一种 方式使【fāng shì shǐ】用数据📻库是正确的📁……
您可以🗣用很多【yòng hěn duō】的方式创建数据库设【jù kù shè】计、数据库访问和【fǎng wèn hé】➕基于数【jī yú shù】🥙据库的⏹ PHP 业务逻辑代码,但最终一般以【yī bān yǐ】📮错误告🖼终。本文说明了数据库设【jù kù shè】计和访😅问数据库的⏹ PHP 代码中【dài mǎ zhōng】出现的【chū xiàn de】五个常💍见问题,以及在【yǐ jí zài】遇到这【yù dào zhè】些问题时如何修复它🧢们【men】👏。
问题 1:直接使用 MySQL
一个常【yī gè cháng】见问题是较老🌚的 PHP 代码直【dài mǎ zhí】接使用 mysql_ 函数来【hán shù lái】⚪访问数据库【jù kù】🚄。清单【qīng dān】 1 展示了如何直🕘接访问数据库【jù kù】🚄。
以下为引用的【yǐn yòng de】⛽内容: <?php $res = mysql_query( "SELECT id FROM users WHERE login='".$name."'" ); return $id; var_dump( get_user_id( 'jack' ) ); |
清单【qīng dān】🍕 1. Access/get.php
注意使🥤用了🍬 mysql_connect 函数来访问数据库【jù kù】🍾。还要注【hái yào zhù】意查询【yì chá xún】,其中使用字符【yòng zì fú】串连接来向查🍖询添加 $name 参数。
该技术🌴有两个😷很好的【hěn hǎo de】替代方案【àn】:PEAR DB 模块和【mó kuài hé】 PHP Data Objects (PDO) 类。两者都【liǎng zhě dōu】从特定🐰数据库【kù】🧐选择提供抽象【gòng chōu xiàng】。因此,您的代码无需👚太多调整就可【zhěng jiù kě】以在🚡 IBM® DB2®、MySQL、PostgreSQL 或者您想要连😔接到的任何其他数据【tā shù jù】库【kù】🧐上运行。
使用🏤 PEAR DB 模块和【mó kuài hé】 PDO 抽象层【chōu xiàng céng】的另一【de lìng yī】个价值✝在于您可以在 SQL 语句中使用🏤 ? 操作符。这样做【zhè yàng zuò】可使🏌 SQL 更加易于维护【yú wéi hù】,且可使🏌您的应🤘用程序免受 SQL 注入攻【zhù rù gōng】击🚼。
使用🍻 PEAR DB 的替代【de tì dài】⛺代码如【dài mǎ rú】下所示。
以下为【yǐ xià wéi】引用的🤥内容: <?php function get_user_id( $name ) $res = $db->query( 'SELECT id FROM users WHERE login=?', return $id; var_dump( get_user_id( 'jack' ) ); |
清单【qīng dān】⛹ 2. Access/get_good.php
注意,所有直🛳接用到【jiē yòng dào】🐧 MySQL 的地方都消除🈲了,只有【zhī yǒu】 $dsn 中的数🥩据库连接字符串除外【chuàn chú wài】👞。此外【cǐ wài】🏨,我们通过【guò】 ? 操作符【cāo zuò fú】在 SQL 中使用 $name 变量【biàn liàng】。然后,查询的【chá xún de】数据通💠过【guò】 query() 方法末尾的 array 被发送进来🎽。
问题 2:不使用自动增量功能
与大多【yǔ dà duō】数现代数据库🚞一样🤲,MySQL 能够在🚷每记录【měi jì lù】的基础【de jī chǔ】😣上创建【shàng chuàng jiàn】自动增量惟一标识符。除此之【chú cǐ zhī】♑外【wài】🍏,我们仍然会看到这样的代码,即首先👅运行一【yùn háng yī】个 SELECT 语句来找到最【zhǎo dào zuì】💝大的 id,然后将【rán hòu jiāng】该🍦 id 增 1,并找到🐰一个新【yī gè xīn】记录。清单【qīng dān】 3 展示了👻一个示例坏模式。
以下为引用的【yǐn yòng de】🎉内容: DROP TABLE IF EXISTS users; INSERT INTO users VALUES ( 1, 'jack', 'pass' ); |
清单 3. Badid.sql
这里的 id 字段被【zì duàn bèi】简单地指定为整数。所以,尽管它应该是惟一的【wéi yī de】🍌,我们还🏓是可以🗨添加任何值【hé zhí】✒,如【rú】📫 CREATE 语句后【yǔ jù hòu】面的几【miàn de jǐ】个 INSERT 语句中所示【suǒ shì】👽。清单【qīng dān】🤵 4 展示了【zhǎn shì le】将用户🕉添加到😘这种类型的模式的 PHP 代码。
以下为【yǐ xià wéi】引用的🏡内容: <?php function add_user( $name, $pass ) $dsn = 'mysql://root:password@localhost/bad_badid'; $res = $db->query( "SELECT max(id) FROM users" ); $id += 1; $sth = $db->prepare( "INSERT INTO users VALUES(?,?,?)" ); return $id; $id = add_user( 'jerry', 'pass' ); var_dump( $id ); |
清单 4. Add_user.php
add_user.php 中的代码首先执行一个查询【gè chá xún】🛐以找到【yǐ zhǎo dào】 id 的最大🍝值📬。然后文件以 id 值加⭕ 1 运行一个【gè】📱 INSERT 语句【yǔ jù】。该代码💯在负载【zài fù zǎi】很重的服务器上会在【shàng huì zài】🏇竞态条【jìng tài tiáo】件中失🧟败。另外,它也效率低下【lǜ dī xià】。
那么替代方案【dài fāng àn】是什么🤣呢?使用 MySQL 中的【zhōng de】🔳自动增【zì dòng zēng】量特性【liàng tè xìng】来自动地🍧为每个插入创【chā rù chuàng】建惟一【jiàn wéi yī】的🔳 ID。更新后🏅的模式🈂如下所👙示。
以下为【yǐ xià wéi】引用的🌄内容: DROP TABLE IF EXISTS users; INSERT INTO users VALUES ( null, 'jack', 'pass' ); |
清单 5. Goodid.php
我们添【wǒ men tiān】🍱加了 NOT NULL 标志来【biāo zhì lái】🈂指示字🍊段必须【duàn bì xū】不能为空【kōng】。我们还添加了 AUTO_INCREMENT 标志来【biāo zhì lái】🈂指示字🍊段是自😗动增量💮的【de】,添加 PRIMARY KEY 标志来【biāo zhì lái】🈂指示那个字段是一个 id。这些更【zhè xiē gèng】改加快🔽了速度【le sù dù】。清单🖤 6 展示了更新后的【de】 PHP 代码【dài mǎ】,即将用户插入表中。