PHP 7: 真实世界的应用开发
  • 前言
  • 模块一
    • 第一章、建立基础
      • PHP 7 安装注意事项
      • 使用内置的 PHP web 服务器
      • 创建一个 MySQL 测试数据库
      • 安装 PHPUnit
      • 实现类的自动加载
      • 抓取一个网站
      • 建立一个深度网络扫描器
      • 创建一个 PHP 5 到 PHP 7 代码转换器
    • 第二章、使用 PHP 7 高性能特性
      • 了解抽象语法树
      • 理解句法分析中的差异
      • 理解 foreach() 处理中的差异
      • 使用 PHP 7 增强功能提高性能
      • 遍历海量文件
      • 将电子表格上传到数据库
      • 递归目录迭代器
    • 第三章、使用 PHP 函数
      • 函数开发
      • 数据类型提示
      • 使用返回值数据类型
      • 使用迭代器
      • 使用生成器编写自己的迭代器
    • 第四章、使用 PHP 面向对象程序设计
      • 类的开发
      • 类的扩展
      • 使用静态属性和方法
      • 使用命名空间
      • 定义可见性
      • 使用接口
      • 使用特性
      • 实现匿名类
    • 第五章、与数据库的交互
      • 使用PDO连接数据库
      • 构建一个 OOP SQL 查询生成器
      • 处理分页
      • 定义实体以匹配数据库表
      • 将实体类与RDBMS查询绑定
      • 将二次查找嵌入到查询结果中
      • 实现jQuery DataTables的PHP查找
    • 第六章、建立可扩展的网站
      • 创建通用表单元素生成器
      • 创建一个HTML单选元素生成器
      • 创建一个HTML选择元素生成器
      • 实现表单工厂
      • 链式 $_POST 过滤器
      • 链式 $_POST 验证器
      • 将验证绑定到表单
    • 第七章、访问Web服务
      • 在PHP和XML之间转换
      • 创建一个简单的REST客户端
      • 创建一个简单的REST服务器
      • 创建一个简单的SOAP客户端
      • 创建一个简单的SOAP服务器
    • 第八章、处理日期/时间和国际化方面
      • 在视图脚本中使用 emoji
      • 转换复杂字符
      • 从浏览器数据获取语言环境
      • 按地区设置数字格式
      • 按地区处理货币
      • 按地区设置日期/时间格式
      • 创建一个HTML国际日历生成器
      • 构建一个周期性事件生成器
      • 不使用gettext处理翻译
    • 第九章、开发中间件
      • 使用中间件进行认证
      • 使用中间件实现访问控制
      • 使用高速缓存提高性能
      • 实施路由选择
      • 进行框架间的系统调用
      • 使用中间件来跨语言
    • 第十章、高级算法
      • 使用 getter 和 setter
      • 实现一个链表
      • 建立冒泡排序
      • 实现一个堆栈
      • 构建一个二分法查找类
      • 实现一个搜索引擎
      • 显示多维数组并累计总数
    • 第十一章、软件设计模式的实现
      • 创建数组到对象的转化器
      • 构建对象到数组到转化器
      • 实施策略模式
      • 定义一个映射器
      • 实现对象关系映射
      • 实施发布/订阅设计模式
    • 第十二章、提高网站安全
      • 过滤$_POST数据
      • 验证$_POST数据
      • 保护PHP session
      • 用令牌保护表格的安全
      • 建立一个安全的密码生成器
      • 带有验证码的安全保护表格
      • 不使用mcrypt进行加密/解密
    • 第十三章、最佳实践、测试和调试
      • 使用特征和接口
      • 通用异常处理程序
      • 通用错误处理程序
      • 编写一个简单的测试
      • 编写测试套件
      • 生成虚假的测试数据
      • 使用session_start参数自定义会话
    • PSR-7
  • 模块二
  • 模块三
    • GoF 设计模式
      • 结构型
      • 行为型
      • 小结
    • SOLID 设计原则
      • 开闭原则
      • 里氏替换原则
      • 接口隔离原则
      • 依赖反转原则
      • 小结
    • 模块化网店应用的需求规范
      • 线框设计
      • 定义技术栈
      • 小结
    • Symfony 概述
      • 创建一个空白项目
      • 使用 Symfony 控制台
      • 控制器
      • 路由
      • 模板
      • 表单
      • 配置 Symfony
      • bundle 系统
      • 数据库和 Doctrine
      • 测试
      • 验证
      • 小结
    • 构建核心模块
    • 构建目录模块
    • 构建客户模块
    • 构建支付模块
    • 构建发货模块
    • 构建销售模块
    • 总结
由 GitBook 提供支持
在本页
  • 如何做...
  • 如何运行...
  • 更多...
  1. 模块一
  2. 第八章、处理日期/时间和国际化方面

按地区处理货币

处理货币的技术与处理数字的技术类似。我们甚至会使用相同的NumberFormatter类。然而,有一个主要的区别,它是一个引人注目的问题:为了正确地格式化货币,你需要手头有货币代码。

如何做...

1.首先要做的是以某种格式提供货币代码。一种可能性是简单地将货币代码添加为Application\I18n\Locale类构造函数参数。

const FALLBACK_CURRENCY = 'GBP';
protected $currencyCode;
public function __construct($localeString = NULL, $currencyCode = NULL)
{
  // add this to the existing code:
  $this->currencyCode = $currencyCode ?? self::FALLBACK_CURRENCY;
}

这种方法虽然明显是稳妥可行的,但往往属于所谓的半途而废或易如反掌! 这种方法也倾向于消除完全自动化,因为货币代码无法从HTTP头中获得。正如你可能已经从本书中的其他事例中收集到的,我们并不回避更复杂的解决方案,所以,正如俗话说的那样,系上你的安全带吧!我们的解决方案是:"你可以在你的网站上找到你想要的东西"。

2.我们首先需要建立某种查找机制,给定一个国家代码,我们就可以获得其主要的货币代码。在这个例子中,我们将使用适配器软件设计模式。根据这种模式,我们应该能够创建不同的类,这些类有可能以完全不同的方式进行操作,但却产生相同的结果。据此,我们需要定义所需的结果。为此,我们引入一个类,Application\I18n\IsoCodes。正如你所看到的,这个类有所有相关的属性,还有一个通用的构造函数。

namespace Application\I18n;
class IsoCodes
{
  public $name;
  public $iso2;
  public $iso3;
  public $iso_numeric;
  public $iso_3166;
  public $currency_name;
  public $currency_code;
  public $currency_number;
  public function __construct(array $data)
  {
    $vars = get_object_vars($this);
    foreach ($vars as $key => $value) {
      $this->$key = $data[$key] ?? NULL;
    }
  }
}

3.接下来我们定义一个接口,它有我们需要的方法来执行国家代码到货币代码的查询。在这种情况下,我们引入Application\I18n\IsoCodesInterface。

namespace Application\I18n;

interface IsoCodesInterface
{
  public function getCurrencyCodeFromIso2CountryCode($iso2) : IsoCodes;
}

4. 现在我们准备建立一个查找适配器类,我们将把它称为Application\I18n\IsoCodesDb。它实现了上述接口,并接受一个Application\Database\Connection实例(参见第1章,建立基础),用于执行查找。构造函数设置了所需的信息,包括连接、查找表名和代表ISO2代码的列。然后,接口所需的查找方法会发出一条SQL语句并返回一个数组,然后用这个数组来构建一个IsoCodes实例。

namespace Application\I18n;

use PDO;
use Application\Database\Connection;

class IsoCodesDb implements IsoCodesInterface
{
  protected $isoTableName;
  protected $iso2FieldName;
  protected $connection;
  public function __construct(Connection $connection, $isoTableName, $iso2FieldName)
  {
    $this->connection = $connection;
    $this->isoTableName = $isoTableName;
    $this->iso2FieldName = $iso2FieldName;
  }
  public function getCurrencyCodeFromIso2CountryCode($iso2) : IsoCodes
  {
    $sql = sprintf('SELECT * FROM %s WHERE %s = ?', $this->isoTableName, $this->iso2FieldName);
    $stmt = $this->connection->pdo->prepare($sql);
    $stmt->execute([$iso2]);
    return new IsoCodes($stmt->fetch(PDO::FETCH_ASSOC);
  }
}

5. 现在我们把注意力转回Application\I18n\Locale类。我们首先添加一些新的属性和类常数。

const ERROR_UNABLE_TO_PARSE = 'ERROR: Unable to parse';
const FALLBACK_CURRENCY = 'GBP';

protected $currencyFormatter;
protected $currencyLookup;
protected $currencyCode;

6. 我们添加新的方法,从locale字符串中获取国家代码。我们可以利用getRegion()方法,它来自于PHP Locale类(我们扩展了它)。为了以防万一,我们还添加了一个方法getCurrencyCode()。

public function getCountryCode()
{
  return $this->getRegion($this->getLocaleCode());
}
public function getCurrencyCode()
{
  return $this->currencyCode;
}

7. 与格式化数字一样,我们定义一个getCurrencyFormatter(I),就像我们定义getNumberFormatter()一样(如前所示)。注意,$currencyFormatter是用NumberFormatter定义的,但第二个参数不同。

public function getCurrencyFormatter()
{
  if (!$this->currencyFormatter) {
    $this->currencyFormatter = new NumberFormatter($this->getLocaleCode(), NumberFormatter::CURRENCY);
  }
  return $this->currencyFormatter;
}

8. 然后,如果已经定义了查询类,我们就在类的构造函数中添加货币代码查询。

public function __construct($localeString = NULL, IsoCodesInterface $currencyLookup = NULL)
{
  // add this to the existing code:
  $this->currencyLookup = $currencyLookup;
  if ($this->currencyLookup) {
    $this->currencyCode = $this->currencyLookup->getCurrencyCodeFromIso2CountryCode($this->getCountryCode())->currency_code;
  } else {
    $this->currencyCode = self::FALLBACK_CURRENCY;
  }
}

9. 然后添加适当的货币格式和解析方法。注意,解析货币与解析数字不同,如果解析操作不成功,将返回FALSE。

public function formatCurrency($currency)
{
  return $this->getCurrencyFormatter()->formatCurrency($currency, $this->currencyCode);
}
public function parseCurrency($string)
{
  $result = $this->getCurrencyFormatter()->parseCurrency($string, $this->currencyCode);
  return ($result) ? $result : self::ERROR_UNABLE_TO_PARSE;
}

如何运行...

如前几个要点中所涉及的那样,创建以下类。

Class

讨论要点

Application\I18n\IsoCodes

3

Application\I18n\IsoCodesInterface

4

Application\I18n\IsoCodesDb

5

为便于说明,我们假设我们有一个已填充的MySQL数据库表`iso_country_codes`,其结构如下。

CREATE TABLE `iso_country_codes` (
  `name` varchar(128) NOT NULL,
  `iso2` varchar(2) NOT NULL,
  `iso3` varchar(3) NOT NULL,
  `iso_numeric` int(11) NOT NULL AUTO_INCREMENT,
  `iso_3166` varchar(32) NOT NULL,
  `currency_name` varchar(32) DEFAULT NULL,
  `currency_code` char(3) DEFAULT NULL,
  `currency_number` int(4) DEFAULT NULL,
  PRIMARY KEY (`iso_numeric`)
) ENGINE=InnoDB AUTO_INCREMENT=895 DEFAULT CHARSET=utf8;

在Application\I18n\Locale类中进行添加,如前面第6至9点中所讨论的那样。然后你可以创建一个chap_08_formatting_currency.php文件,该文件设置了自动加载并使用了相应的类。

<?php
define('DB_CONFIG_FILE', __DIR__ . '/../config/db.config.php');
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');
use Application\I18n\Locale;
use Application\I18n\IsoCodesDb;
use Application\Database\Connection;
use Application\I18n\Locale;

接下来,我们创建Connection和IsoCodesDb类的实例。

$connection = new Connection(include DB_CONFIG_FILE);
$isoLookup = new IsoCodesDb($connection, 'iso_country_codes', 'iso2');

在这个例子中,创建两个Locale实例,一个用于英国,另一个用于法国。你也可以指定一个大的数量来用于测试。

$localeFr = new Locale('fr-FR', $isoLookup);
$localeUk = new Locale('en_GB', $isoLookup);
$number   = 1234567.89;
?>

最后,你可以将formatCurrency()和parseCurrency()方法包在适当的HTML显示逻辑中,并查看结果。这里是最终的输出。

更多...

上一页按地区设置数字格式下一页按地区设置日期/时间格式

最后更新于4年前

最新的货币代码列表由ISO(国际标准组织)维护。你可以用XML或XLS(即微软Excel电子表格格式)获得这份清单。这里是可以找到这些清单的网页:。

http://www.currency-iso.org/en/home/tables/table-a1.html