框架的其它功能

大多数框架所具备的功能并不仅仅是我们在上一节中描述的那些,尽管这些功能足以让你自己构建简单的应用程序。不过,大多数网络应用程序都有许多更常见的功能,因此框架都试图为每种功能提供通用的解决方案。正因为如此,我们才不必重新发明轮子,来实现几乎所有大中型网络应用程序都需要的功能。我们将尝试描述一些最有用的功能,以便您在选择框架时有一个更好的主意。

认证和角色

大多数网站都要求用户通过身份验证才能执行某些操作。这样做的原因是让系统知道试图执行某些操作的用户是否有权这样做。因此,管理用户及其角色很可能是你最终要在所有网络应用程序中实施的事情。如果有太多的人试图攻击你的系统,以获取其他用户的信息或以其他人的身份执行操作,问题就来了,这就是所谓的冒名顶替。因此,您的身份验证和授权系统应尽可能安全,这绝非易事。

有几种框架采用了相当安全的方式来管理用户、权限和会话。大多数情况下,您可以通过配置文件来管理用户、权限和会话,方法可能是将凭证指向数据库,框架可以在数据库中添加用户数据、自定义角色和其他一些自定义功能。缺点是每个框架都有自己的配置方式,所以此时你必须深入研究你正在使用的框架的文档。不过,这比你自己实现要节省更多时间。

ORM

对象关系映射(ORM)是一种将数据库或任何其他数据存储的数据转换为对象的技术。其主要目的是尽可能将业务逻辑与数据库结构分开,降低代码的复杂性。使用 ORM 时,您可能永远不会在 MySQL 中编写查询;相反,您将使用一系列方法。在幕后,ORM 会在每次调用方法时编写查询。

使用 ORM 有好有坏。一方面,您不必总是记住所有的 SQL 语法,只需记住要调用的正确方法即可,如果您使用的集成开发环境可以自动完成方法,这就会变得更容易。此外,从存储系统类型中抽象出代码也是个好办法,因为尽管存储系统不是很常见,但您以后可能会想改变它。如果使用 ORM,可能只需更改连接类型,但如果编写的是原始查询,则需要做大量工作才能迁移代码。

使用 ORM 的一个可论证的缺点可能是,使用方法链编写复杂的查询可能会相当困难,最终只能手动编写。为了提高查询的性能,您还得听从 ORM 的摆布,而在手动编写查询时,您可以更好地选择查询的内容和方式。最后,OOP 的纯粹主义者经常抱怨的一点是,使用 ORM 会在代码中填入大量的虚对象,类似于你已经知道的域对象。

正如您所看到的,使用 ORM 并不总是一个简单的决定,但为了以防万一,大多数大型框架都包含 ORM。请慢慢决定是否在应用程序中使用 ORM;如果使用,请明智选择。您最终需要的 ORM 可能与框架提供的不同。

Cache

书店是一个很好的例子,可以帮助描述缓存功能。它有一个书籍数据库,每次有人列出所有书籍或询问特定书籍的详细信息时,都会对该数据库进行查询。大多数情况下,与图书相关的信息都是相同的,唯一的变化是图书的库存。我们可以说,我们的系统读取的次数远远多于写入的次数,读取指的是查询数据,写入指的是更新数据。在这种系统中,每次访问数据库似乎都是在浪费时间和资源,因为我们知道大多数时候都会得到相同的结果。如果我们对检索到的数据进行一些昂贵的转换,这种感觉就会更加强烈。

缓存层允许应用程序将临时数据存储在比数据库更快的存储系统中,通常是内存而不是磁盘。尽管缓存系统越来越复杂,但它们通常允许你像在数组中一样按键值对存储数据。

这样做的目的是为了节省时间和资源,不访问我们知道与上次访问相同的数据。实现方式可以有很多不同,但主要流程如下:

  1. 您第一次尝试访问某个数据。我们会询问高速缓存是否存在某个键,但它并不存在。

  2. 查询数据库,得到结果。在对结果进行处理—​或许将其转换为您的域对象—​之后,将结果存储到缓存中。键与第 1 步中使用的相同,而值则是您生成的对象/数组/JSON。

  3. 再次尝试访问相同的数据。您会询问缓存中的键是否存在;在这里,键是存在的,所以您根本不需要访问数据库。

看起来很简单,对吗?当我们需要使某个键失效时,缓存的主要问题就来了。我们应该怎么做,什么时候做呢?有几种方法值得一提:

  • 您将为缓存中的键值对设置一个过期时间。过了这个时间,缓存会自动删除键值对,因此你必须再次查询数据库。尽管这种系统可能适用于某些应用,但对我们的应用却不适用。如果在缓存过期前库存变为 0,用户就会看到无法借阅或购买的图书。

  • 数据永远不会过期,但每次我们对数据库进行更改时,我们都会确定缓存中哪些键会受到这次更改的影响,然后清除它们。这样做是最理想的,因为数据会一直保留在缓存中,直到不再有效,不管是 2 秒还是 3 周。缺点是,根据数据结构的不同,识别这些键可能是一项艰巨的任务。如果错过删除其中一些键,缓存中的数据就会损坏,这就很难调试和检测了。

由此可见,缓存是一把双刃剑,因此我们建议您只在必要时才使用缓存,而不要因为框架自带缓存就不使用。与 ORM 一样,如果您不满意框架提供的缓存系统,使用其他缓存系统并不困难。事实上,除了在创建连接对象时,您的代码不应该知道您使用的是哪种缓存系统。

国际化

英语不是世界上唯一的语言,您也希望自己的网站尽可能便于访问。根据您的目标,将您的网站翻译成其他语言也是一个好主意,但如何翻译呢?我们希望您现在还没有回答: "复制粘贴所有模板并进行翻译"。这样做效率太低;在模板中做一点改动,就需要将改动复制到所有地方。

有一些工具可以与控制器和/或模板引擎集成,以便翻译字符串。您通常会为每种语言保存一个文件,在其中添加所有需要翻译的字符串及其翻译。最常见的格式之一是 PO 文件,其中包含一个键值对映射表和最初翻译的键值对。稍后,您将调用翻译方法发送原始字符串,该方法将根据您选择的语言返回翻译后的字符串。

在编写模板时,每次要显示一个字符串时都要调用翻译可能会很累,但最终只会有一个模板,这比其他选项更易于维护。

通常,国际化与您使用的框架有很大关系;不过,如果您有机会使用自己选择的系统,请特别注意它的性能、它使用的翻译文件以及它如何管理带参数的字符串—​也就是说,我们如何要求系统翻译诸如 "Hello %s, who are you?" 这样的消息,其中每次都需要注入"%s"。