以下是由 Zachary Brady 撰写的客座文章。Zachary 即将带我们踏上使用 PHP 进行一些前端开发人员有时需要做的事情的初学者之旅。在我看来,这种做法并不会让我们成为后端开发人员,而更像是资源丰富的 前端开发人员。Zachary 在这里也专注于 PHP,但同样的概念在任何后端语言中都是可用的。
PHP 有时会受到负面评价,但它仍然存在并蓬勃发展,不仅在一些最流行的 CMS 中,而且在诸如服务器端组件响应式设计 (RESS) 这样的新兴策略中也得到了应用。我发现,在前端开发工作流程中加入一点 PHP 可以增强代码并加快开发过程。
学习足够的 PHP 基础知识 以开始将其包含在您的工具集中并不困难或耗时。让我们直接开始探索如何在您的前端开发中混合一点服务器端脚本既简单又富有成效。
PHP 基础入门
如果您熟悉 PHP 的基础知识,那么可以直接跳到下一部分。对于我们其他人来说,可能需要稍微复习一下。
作为一种服务器端语言,PHP 文件(例如index.php 或myAwesomeCatPhotos.php)会在发送到浏览器之前由您的服务器处理成 HTML。因此,在使用 PHP 文件时,**必须**将其托管在服务器上。这可以是远程服务器,也可以是存在于您计算机上的本地服务器。由于有了像 MAMP 这样的软件,设置起来实际上相当简单。(CSS-Tricks 上的 入门视频)。
PHP 的一大优点是您可以将其与 PHP 文件中的普通 HTML 混合使用。
<?php
和 ?>
标签定义了您在文件中使用 PHP 的位置。**专业提示:**如果您发现您的页面变成了空白,首先检查一下您是否在任何地方都缺少了 PHP 结束标签。echo 函数将其后的任何内容直接打印到标记中。在本例中,“回显”的是一个包含“Hello World”字样的字符串。在 PHP 中,用分号结束语句是**必须的**;缺少分号是导致脚本失败的另一个常见原因。这段简单的 PHP 代码转换为
<code>
<code>
变量 在 PHP 中可以写成 $aWord
、$manyWords
、$a_lot_of_numbers
、$a4
等。关键要素是在变量名称开头使用$。
<code>
使用变量,我们可以这样编写前面的代码
<code>
<code>
PHP 还具有for
循环和if
语句。if
语句会提出一个问题,如果问题被证明是正确的,则执行一项任务,并且可以与else
语句结合使用,如果问题是错误的,则执行一项任务。
<code>
<code>
如果$a
等于 7,则会回显第一个字符串,但如果$a
等于 5 这样的奇怪值,则会回显第二个语句。
<code>
for
循环用于重复执行一组代码,直到满足某个条件。
<code>
<code>
这意味着我们将一个名为$d
的变量设置为 0,只要它小于 7,我们就回显$d
的值,并在每次迭代结束时将$d
加 1。这会生成“0123456”。
<code>
我们还将使用函数include()
,它获取另一个 PHP 文件的相对路径,找到路径指定的该文件,并将它的内容包含在调用它的文件中。
<code>
PHP 远不止这些,但这些基础知识将贯穿本文的其余部分。如果您仍然不确定 PHP,我建议先继续阅读,然后再稍微复习一下。在上下文中看到这些概念可能有助于您更好地理解它们。
<code>
简单的 PHP 模板
<code>
您可能会发现,在创建项目的每个页面的标记时,某些部分会重复出现。Web 项目中最常重复的部分是页眉和页脚。
<code>
通常,如果我们必须更改网站页眉中的某些内容,则必须手动编辑项目中每个文件中的页眉。这就是 PHP 提升我们的工作效率的地方。使用 PHP,我们可以将与项目页眉相关的标记存储在它自己的文件中,并使用include()
函数将代码添加到我们的文件中。当然,我们也可以对页脚元素和我们可能希望在多个页面上使用的任何其他代码段执行相同的操作。
<code>
<code>
在此示例中,header.php 和 footer.php 存储在一个名为“includes”的目录中,并在每个文件中进行引用。想象一下,仅凭此技巧就能节省多少开发时间。
<code>
根据页面提供不同的文件
<code>
在每个页面上提供相同的页眉和页脚的一个缺点是,默认情况下,我们对向不同页面提供哪些文件有较少的控制权。我们可能有一个图像滑块的 JavaScript 文件,我们只需要在主页上使用它,或者一个用于联系页面表单验证的脚本。谢天谢地,还有另一个简单的技巧可以帮助我们解决这个问题。
<code>
为了执行此技巧,我首先需要获取当前文件的名称并从中删除文件扩展名。
<code>
<code>
第一行从服务器获取文件的名称,第二行从该名称中删除文件扩展名(第二行更多是为了美观,使代码更简洁,但我仍然建议使用它)。我倾向于将这行代码放在文件的开头,甚至在打开<?php
标签之前;这使我可以将此数据用于各种目的,例如生成类名。
<code>
此技巧的第二部分,即决定为哪个页面提供哪些脚本,位于结束主体标签之前的页脚中。我们将使用 if/else 语句组合来检查当前页面是否为联系页面。如果是,则会回显一个引用我的contact.min.js 文件的脚本标签,否则我们将回显global.min.js 文件。
<code>
';
} else {
echo '<script src="js/global.min.js"></script>';
}
?>
此技术可用于您可能想要包含的任何类型的外部文件。我甚至喜欢使用 Grunt 将我的 JavaScript 组织成特定于页面或部分的文件,然后使用此技术。
一点 RESS 可以走很远
我们可以进一步利用上面的示例,并使用类似的技术来提供根据设备上下文不同的文件。这是一个非常简单的 RESS 解决方案示例。RESS,即服务器端组件响应式设计,仅仅意味着您将一些服务器端逻辑混合到响应式设计工具集中,以便执行诸如减少页面重量之类的出色操作。
为此,我们需要一个名为 Mobile Detect 的 PHP 库,它提供了一种简单的方法来发现用户使用的设备类型。在项目中的某个位置包含该库,我喜欢将其放在“scripts”目录中,然后使用require_once
函数包含它。您还必须初始化Mobile_Detect
类的实例,我喜欢在页眉文件中包含之后立即执行此操作。
<code>
现在,我可以在页脚中使用if/else 对来决定用户是否正在使用移动设备,并提供相应的 JavaScript 文件。注意:因为 Mobile Detect 将平板电脑视为移动设备,所以我也会检查设备是否不是平板电脑。
<code>
isMobile() && !$detect->isTablet()) {
echo '<script src="js/global-mobile.min.js"></script>';
} else{
echo '<script src="js/global.min.js"></script>';
}
?>
<code>
使用此技术,我们可以制作更适合移动体验的 JavaScript,并忽略来自大屏幕相关 JavaScript 的所有额外页面重量。
<code>
自动标记模式
<code>
你可能会遇到一些标记模式,它们可能不共享相同的内容,但看起来却非常相似。一个常见的情况可能是显示属于同一图库对象的一组图像。幸运的是,Lara Schenck最近在她在纽约Smashing大会Jam Session上发表的一次精彩演讲中展示了这样的解决方案。
<code>
// Function to print images
function printGalleryItem($path, $alt) {
echo '
';
}
// Loop through image directory and printGalleryItem markup for each
function printGallery($dir, $alt) {
echo '
';
}
<code>
在PHP中,就像其他语言一样,可以创建自己的自定义函数,以便更容易地重用代码。
<code>
第一个函数printGalleryItem()
,接收图像的相对路径及其alt标签的文本,并输出带有div容器的图像标签。第二个函数printGallery()
,接收包含图像的目录的相对路径和一个要用于图像alt标签的字符串。该函数首先输出图库的容器,然后使用称为foreach的for循环版本遍历由glob函数获取的图像路径数组,并将它们应用于我们的printGalleryItem()
函数。当需要遍历一个变量数组并对每个变量的值执行某些操作时,foreach函数非常有用。
<code>
这里还有一些更高级的概念,在本例中我仅是略微提及。目前,了解这些函数的作用以及它们如何帮助你的生产就足够了。不过,当你有机会时,最好进一步研究foreach
和glob
函数。尝试创建一些你自己的函数来自动化标记中一些更冗余的部分。
<code>
这仅仅是冰山一角
<code>
在你的开发中,使用一点PHP可以实现无限的可能性。大多数最有用的代码片段也很容易理解,而且你接触PHP越多,它就越容易上手。在将页面发送到浏览器之前,在服务器上进行一些逻辑处理可以节省开发时间,使你的代码更健壮,甚至可以减轻页面负担。
<code>
本文中提到的技术应该是一个很好的起点,无论你是PHP新手还是刚开始使用PHP。我强烈建议你进行更深入的研究,并且永远不要害怕尝试;损坏的代码总是可以修复的。而且,你最终可能会发现自己爱上了PHP。
我认为PHP不应该用于前端事物,例如移动设备检测。我们有媒体查询来处理这个。PHP可能对服务器端诱惑有用,但是。Node.js可能是一个更好的技术,因为它对前端开发人员来说不是一门新的语言,并且性能更好。
我同意,任何根据设备更改页面的内容都应该在前端完成,否则……缓存会让你陷入困境。如果你检测到一个移动设备,并且一些服务器缓存了该响应,那么通过该服务器的所有请求都将看到移动版本。
你可以争辩说设备检测不应该是一个因素。相反,它应该是诸如性能、屏幕空间和功能支持之类的东西。
但是,服务器端语言可以在内容呈现给客户端之前对其进行操作。这意味着即使用户没有启用JavaScript,你也可以获得一致的结果,因为你可能首先使用JavaScript来操作屏幕上事物的显示位置。
不过,我不会认为Node.js是更好的技术。我们这里讨论的不是大型任务,所以我不会认为性能会成为问题。Node的托管支持可能不可用——我知道在我工作的地方确实如此。对于像文章中所示的包含页眉和页脚之类的事情,PHP相当简单。
对于几乎所有非交互式元素,你真的应该尝试不要使用JavaScript来定位它们。CSS可以处理大多数事情。
至于Node.js,你可以每月5-10美元的价格获得托管。使用JavaScript比PHP更快,因为你不需要记住两种语言,并且可以访问像Handlebars这样的东西。正如Martin所说,使用PHP进行简单的模板化不是一个很好的模式。
对于某些事情来说确实如此。但在本地测试中,我使用了PHP来基本设计特定于移动设备的区域以及其他特定于桌面的区域。
//检查用户是否在手机上
if ( $detect -> isMobile( ) ) {
//一个简单的仅使用CSS的轮播,带小图片
include(“simple-slider.php”); }
else{
//一个带大图片的轮播
include(“fancy-slider.php”); }
因此,移动用户会获得一个非常简单的轮播,带有小图片且没有JavaScript。而桌面用户则会获得一个带有所有花哨功能的轮播。
#FACEPALM
哇。我没想到服务器缓存。
好吧,到目前为止还没有成为问题。如果/何时出现问题,将决定是否更改。
可以公平地说,你在这里让一些个人偏见妨碍了你——当然,node.js 从技术上讲是JavaScript,但其约定与前端开发人员在与任何旨在进行DOM操作和交互的大量JS库交互时使用的约定完全不同。
Node.js“只是JavaScript”似乎是一个错误的卖点。在你稍后在帖子中的观点中——每个开发人员都应该学习不止一门语言。作为一个几乎每天都使用PHP和JavaScript的人,暗示你必须“记住”一门语言才能使用它也显得有点武断。谁会记住任何语言的规范?这就是文档的作用。
顺便说一句,PHP有模板语言(我不知道你在哪里听说过)。例如,请参阅Twig,正如其他人提到的那样。
仅供参考!
在使用Node.js可以节省时间的情况下,搜索诸如“javascript indexof php等效项”之类的东西只会浪费时间
我从未说过PHP没有模板语言。Hogan(如Mustache)很好,但Handlebars.js更好。
虽然你可以使用媒体查询和JS来更改现有内容,但我同意TJ的说法,即服务器端语言在内容到达客户端之前具有操作和更改内容的优势。我在我构建的几乎每个网站上都使用了PHP移动设备检测,并且没有遇到太多问题。
至于缓存,这可以通过为移动设备和桌面设备创建单独的缓存轻松解决。对于WordPress用户,W3 Total Cache为此提供了一个简单的选项:https://wordpress.org/plugins/w3-total-cache/
@Ben B,
W3插件通过嗅探UA字符串来创建移动缓存。了解哪些UA字符串是/不是移动设备可能很困难,这使得这种缓存控制方法不可靠。你必须将这些设置与PHP代码中的UA字符串同步。
无论如何,创建两个单独的缓存的行为对于我的口味来说过于不DRY。我认为最好的方法是教育你的设计师和客户了解移动优先的理念,并努力为所有设备提供相同的内容。
本文提供了一个PHP设备检测的良好示例:http://www.smashingmagazine.com/2014/07/22/responsive-web-design-should-not-be-your-only-mobile-strategy/
自动更正让我在上面最初的评论中写成了“服务器端模板化”。对此表示歉意。
非常失望。期待基于后端的LESS/SASS编译或类似的“前端任务”,例如这个
https://github.com/kriswallsmith/assetic
“在你的开发中,使用一点PHP可以实现无限的可能性。”
我认为作者对这一点感觉非常聪明,因为它只提供了关于显而易见事物的建议。
这些“技术”相当古老。当编辑WordPress网站或类似网站时,任何前端开发人员都处理过这些问题。
更糟糕的是,css-tricks支持这些不良做法。
你做前端开发人员或处理网络相关工作有多久了?
当然,PHP不适合所有事情。也许它在任何事情上都不擅长。但它有效。在几乎所有平台上都适用。
所以真的没有理由讨厌它,它有一些非常棒的用途,比如制作模板、用户账户等等。
如果有人“感觉非常聪明”,那应该就是你了。我不忍心告诉你,虽然各种 CSS 风格可能对很多事情都有好处,但它们最终都归结为 CSS。换句话说,你不会用它们完成任何后端工作,比如与 SQL 交谈之类。
如果我是你,在我积累更多经验之前,我不会开始批评相对专家(并不是说我是其中之一,我也还在学习)。
到“简单的 PHP 模板”
我更喜欢使用像 Smarty/Twig/Dwoo 这样的模板引擎。因为解耦后端和前端内容通常很困难。
模板引擎确保您将后端与前端内容分离。
echo “变量 $a 当前为 7。”;
在这种情况下,因为您使用的是双引号,所以您不会打印
而是您将打印
可能应该更改一下;)
我注意到在编辑时,并且将其保留在那里,因为我认为有人会指出它,这将是一次很好的学习体验。从技术上讲它并没有错,只是该变量会被插值=)。
明白了;)
更多专业技巧/说明
这是**错误的**。变量名必须以
$
开头,后跟字母或下划线(不是数字),然后是零个或多个字母、数字或下划线。示例$a-lot-of-numbers
将被解释为$a
减去lot
减去of
减去numbers
,这正如您可能想象的那样,可能毫无意义,并且会导致错误。**空白页面**实际上是 PHP 配置为不将错误显示到网页时(这对“实时”站点很有用)发生的解析错误的结果。缺少结束标签或分号是常见的语法错误,但括号不匹配和其他许多事情也是如此。与其尝试“猜测”错误在哪里,不如在服务器上查找 PHP 错误日志(通常在 Web 根目录的上方目录中,或者询问您的 Web 主机)。一旦您习惯了阅读 PHP 的错误消息,它们实际上非常简单明了,这样做将节省大量的调试时间(和挫败感)。如果您不理解错误消息,只需将其复制粘贴到 Google 中即可。
PHP 和 HTML(css、javascript 等)实际上并没有“混合”。这可能看起来像是一个微不足道的区别,但对于理解实际发生的事情非常重要。当您将文件扩展名更改为
.php
时,它不再是 HTML 文件。即使它仅是 HTML 标记,没有任何 PHP 标签。PHP 在您的服务器上运行该文件,并将输出结果(包括内联 HTML)发送到浏览器。例如,在 PHP 脚本中,这与这做完全相同的事情
include
(以及require
等)使用文件系统路径查找您想要的文件,这些路径是混淆的非常常见来源。请记住,文件系统路径不是 URL。文件系统路径位于您的服务器上;URL 位于互联网上。在许多情况下,看起来这两个之间存在直接关系,但实际上并非如此。如上所述,我建议不要尝试从服务器“检测”移动浏览器。这是浏览器嗅探(主要通过 User-Agent 标头),通常不被推荐,因为它很脆弱,很快就会过时,有时甚至错误。
根据内容的类型,服务器端浏览器嗅探是可以的。
我还想添加提示
这可以节省大量的打字。
好吧,我并不是说你不能使用它,或者永远不会有适合它的情况。但是我想不出来。根据我的经验,浏览器嗅探的实现工作量很大,而且难以维护。即使是“正确”地完成,它也往往会带来比解决问题更多的机会。相反,像功能检测这样的方法工作量更少,易于维护,并且错误更少。
互联网上有许多资源讨论这个主题。css-tricks 有一篇文章,这是一个不错的起点。
关于使用
<?= $stuff ?>
而不是<?php echo $stuff; ?>
,我同意。需要注意的是,在 5.4 之前的 PHP 版本中,此功能可能不可用(取决于 PHP 配置设置)。只是需要注意的一点。您不能在 php 中的变量名中使用连字符($a-lot-of-numbers 无效)。PHP 将连字符解释为减号,并尝试从 $a 中减去 lot。
但是,您可以使用下划线
https://php.ac.cn/manual/en/language.variables.basics.php
很多聪明人在这里发表评论,然后当你查看他们的作品集时,你会笑得前仰后合,最终尿裤子。
请记住,我们这些所谓的聪明人中,很多人没有时间维护他们的作品集,因为我们太忙于工作了。我的网站已经过时 3 年了,作品集也过时了大约 1 年。
此外,就我而言,我们中的一些人不是设计师(遗憾的是我做不到),所以我们的作品集既展示了我们的设计师,也展示了我们自己。
尽管查看了迄今为止的评论,但我找不到任何一个关于响应式设计的合理示例。所以,我同意你的观点,在没有制作响应式设计的情况下评论最佳响应式设计实践是很奇怪的。
我既是后端开发人员,也是前端开发人员,我永远不会使用 php 进行移动设备检测。
对我来说,这仅仅是错误的,并且不可能不为某人提供错误的代码。
与其希望检测按预期工作,不如为某人提供一个隐藏元素(只要它不包含图像)要好得多。
但是,我还没有制作一个针对移动设备和全尺寸分别具有截然不同设计的响应式网站,但这不是重点吗?
唯一可能变得有疑问或混乱的时候是尝试让 cms 为您的客户编写符合响应式设计标准的代码。否则,尽可能使用 css,然后在 css 不能完全满足要求或为了改善用户体验时使用 javascript。
后端不应用于设备检测。
查看我的公司网站:http://www.suits-sandals.com。对于桌面和“平板电脑”设备,如果支持,我使用 Javascript 功能检测在主页上提供 HTML5 视频。但是,对于移动环境,即使提供用于检测这些功能的 Javascript 也毫无意义。
现在,如果像 Scott Fennell 指出的那样,我的服务器嗅探失败,实际上没有任何东西会中断。相反,用户只会看到“加载”图标和网站标题;这足以让用户进入网站。
服务器端嗅探对我的许多项目都有意义。不是全部,但很多。与任何技术一样,最好以不会妨碍关键内容或可用性的方式应用它。
还有关于巨魔!一些评论太糟糕了,我忍不住。
我所有的道歉zzzzzz
老实说,尽管你在网上咒骂别人让自己处于不利地位,但我同意你的基本观点。人们往往对服务器端嗅探非常教条。听到人们谴责它比听到他们解释其立场的原因要普遍得多。
(意思是,我同意对服务器端嗅探采取教条的态度是一件坏事——但这并不意味着这样做是一个好主意,正如我在上面解释的那样)
哇,围绕这个话题有很多戏剧性。我们是否同意不同意,并简单地说“视情况而定”适用于所有这些技术?这里的所有内容都可能适合您的情况,或者可能完全错误。让我们不要将我们个人的视角混淆为其他人的视角。
也就是说,很好的总结,Chris!大多数这些技术在我的特定情况下不会有用,但它们仍然值得了解。
没错,对于我的大多数网站以及我如何使用这些技术,这是有意义的。相信我,如果它们没有用,我会避免使用它们。但是,是的,上下文很重要。
我刚刚在 Twig(php 模板引擎)的帮助下完成了一个新项目,我不得不说它为我节省了很多时间。能够将内容与标记分离,能够遍历数组、包含、使用代码片段 html 等,这真的太棒了!而且你可以使用 Timber 插件立即将其集成到 WordPress 中。哦,要创建站点的构建版本,请将 php 的输出缓冲与 grunt 或 gulp 结合使用。
basename 接受第二个参数
虽然我还没有使用 PHP 进行移动设备检测,但我以类似于 assetic 的方式使用了它(感谢 Martin 分享)。通过将所有 JS 文件耦合到单个文件中,我获得的性能提升非常大。我们构建了一个完整的 Angular 应用程序,它为所有 JS 加载了 1 个文件。当然我们可以让它更智能,但与在一个大型应用程序中获取 40 多个 JS 文件相比,它的差异令人惊叹。我们使这对于其他前端开发人员完全透明,他们只需将文件添加到包含文件中(与添加标签没有什么不同),它就会包含在组合文件中。当然,调试实时版本可能会变得很混乱,但无论如何你都应该为此使用开发环境。
我理解你在做什么,我不得不说,提供一个组合的 php 文件比提供 40 多个较小的脚本更快。但是,通过使用 php 将它们组合在一起,你失去了浏览器缓存的优势。
你最好在构建阶段使用 grunt 或其他一些任务运行器将它们组合起来。然后,你还可以选择预压缩文件以减少服务器负载并使文件大小更小。此外,这使你能够使用源映射来极大地简化调试。最棒的是,你只需将一个新的 js 文件放到源目录中,grunt 就会为你处理它,并在你编辑其中一个源文件时重建组合文件。
@JacobPeters,我完全同意这个说法。唯一的问题是,我本周刚刚被人们抱怨系统升级无法工作而弄得焦头烂额。我发现 HTML 模板甚至一些 JS 文件没有在他们的浏览器上刷新(即使在按 Ctrl-F5 之后)。当然,它最终自己解决了,但收到一堆不必要的支持电话令人沮丧。
我想使用带有某些文件版本控制的 grunt 肯定可以解决这个问题。相信我,我已经知道一段时间了,我需要研究一下。不幸的是,现实让你不得不选择完成你获得报酬的工作或完成基础设施方面的工作。我相信我将在某个时候遇到速度下降的情况,这将让我花几天时间调查和实施更好的构建/部署策略。
感谢你的回复!
我身兼两职。前端和后端兼顾。主要是后端。我最近在 4 个项目中使用了移动检测功能。到了第五个项目,我太厌倦了这样一个事实,即你只能在真实的设备或模拟器上或使用良好的 UA 欺骗插件进行正确的测试。我将所有使用 Mobile Detect 的内容重构为客户端代码,我更喜欢它。
这篇文章是关于我参加 RESS 的内容
http://www.cotonti.mobi/page.php?al=Mobile_web_Slots
这是我关于移动设备检测器的文章
http://www.cotonti.mobi/page.php?al=model_style_css
HTML 和 RES 的兼容性是一项艰巨的任务。我应用了一个已知的 CMF。CMF 的处理花费了大约 4 年的时间
css 链接难道没有用于此的“media”属性吗?虽然我听说并非所有设备都支持它们=\ 我真的不喜欢混合前端和后端,除非重定向移动设备到移动网站,其他设备重定向到普通网站
理论上我同意一点 SS 逻辑可能会有所帮助,在某些情况下也不是一个坏选择。但总的来说,我觉得它的好处不足以支持在日常生产中使用它。
不过,这是一个有趣的想法,也是学习一点 PHP 的好方法!
这样做的一个大问题是,这只能在 PHP 服务器上工作。我建议使用模板语言(jade、haml 等)和构建系统(grunt、glup 等)的方法。这样你就可以获得可以在任何地方使用的 HTML。
感谢发布这篇文章,Chris。我刚刚开始研究 PHP,所以这将非常有用。
很棒的教程,可以开始学习 PHP。