Faker 是一個虛擬數據的生成器,能夠用它填充數據庫進行壓力測試或者建立優雅的 XML 文檔。php
若是項目支持 composer ,使用如下命令安裝。不支持請到 Faker 的 Github 倉庫下載源碼,放入項目的擴展包文件夾中。git
composer require fzaninotto/faker
爲了演示功能,我使用如下命令建立了一個新項目:github
// 建立新項目文件夾 mkdir data-seeder cd data-seeder // 安裝 faker 擴展 composer require fzaninotto/faker
在根目錄下建立測試文件 test.php
,輸入如下代碼:數據庫
<?php require_once __DIR__ . '/vendor/fzaninotto/faker/src/autoload.php'; $faker = Faker\Factory::create(); echo $faker->name, "\n"; echo $faker->address, "\n"; echo $faker->text;
在 CLI 模式下運行腳本, php test.php
查看輸出結果。faker 的結果是隨機生成的:數組
Prof. Kailyn Barton 9230 Herzog Groves Suite 005 Gusikowskihaven, CO 60533-4716 Nesciunt voluptas debitis iusto consectetur possimus mollitia in quam. Vel non rem temporibus illo numquam est. Sit fugit sed fugit id eligendi eaque sunt possimus.
faker 中定義了一些專有名詞幫助咱們理解它的設計思路,明白這些概念對理解他的源碼很是有幫助。composer
除了以上三個屬性,faker 還提供了大量可供選擇的模擬數據。每一個生成器屬性(例如上面使用的 name
,address
和 lorem
)都被叫作 格式器(formatters)。dom
咱們須要填充的數據有不少種類,例如ide
Faker 將每種分類定義爲 provider,查看 data-seeder/vendor/fzaninotto/faker/src/Faker/Provider
能夠看到各類 provider 的類文件,以及分語言包的文件。學習
faker 擴展包體積雖小,五臟俱全,很是有學習價值。測試
查看 faker 生成器的工廠方法:
const DEFAULT_LOCALE = 'en_US'; protected static $defaultProviders = array('Address', 'Barcode', 'Biased', 'Color', 'Company', 'DateTime', 'File', 'HtmlLorem', 'Image', 'Internet', 'Lorem', 'Miscellaneous', 'Payment', 'Person', 'PhoneNumber', 'Text', 'UserAgent', 'Uuid'); public static function create($locale = self::DEFAULT_LOCALE) { $generator = new Generator(); foreach (static::$defaultProviders as $provider) { $providerClassName = self::getProviderClassname($provider, $locale); $generator->addProvider(new $providerClassName($generator)); } return $generator; }
參數 locale
是語言包,默認爲 en_US
美國英語。在 data-seeder/vendor/fzaninotto/faker/src/Faker/Provider
目錄中能夠查看全部支持的語言包。
默認的 providers(provider 已經在上面提到過),在以上 Provider 目錄中能夠一一對應的找到。循環數組,將對應的 provider 添加到生成器 $generator
。
protected static function getProviderClassname($provider, $locale = '') { if ($providerClass = self::findProviderClassname($provider, $locale)) { return $providerClass; } // fallback to default locale if ($providerClass = self::findProviderClassname($provider, static::DEFAULT_LOCALE)) { return $providerClass; } // fallback to no locale if ($providerClass = self::findProviderClassname($provider)) { return $providerClass; } throw new \InvalidArgumentException(sprintf('Unable to find provider "%s" with locale "%s"', $provider, $locale)); }
getProviderClassname 將按照如下邏輯尋找 provider 類,若是不存在於當前文件就到下一級文件查找,找不到就會跑出異常:
用戶傳入的語言包文件夾 -> 默認的en_US語言包文件夾 -> Provider根目錄
public function addProvider($provider) { array_unshift($this->providers, $provider); }
addProvider 就很是簡單了,只是把找到的 provider 加入數組頭部,數組存儲在將要返回的 $generator
對象的屬性中。
在使用 faker 返回的對象時,有兩種方式:調用屬性和調用方法。這些調用都會觸發魔術方法:
public function format($formatter, $arguments = array()) { return call_user_func_array($this->getFormatter($formatter), $arguments); } public function __get($attribute) { return $this->format($attribute); } public function __call($method, $attributes) { return $this->format($method, $attributes); }
二者邏輯相似,這裏說明相對麻煩一點的 __call
魔術方法,魔術方法會將調用的方法名和參數傳入 farmat
方法。
public function getFormatter($formatter) { if (isset($this->formatters[$formatter])) { return $this->formatters[$formatter]; } foreach ($this->providers as $provider) { if (method_exists($provider, $formatter)) { $this->formatters[$formatter] = array($provider, $formatter); return $this->formatters[$formatter]; } } throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter)); }
$this->formatters
中存儲的就是 faker 專有名詞那裏提到的 formatter(格式器)相關的信息。爲了方便理解,這裏以得到數組中一個隨機元素爲例,說明這些抽象的概念。
$faker->randomElement(['a', 'b', 'c']);
當調用此方法時,觸發魔術方法,而後遍歷每個 provider 類,查找是否存在此方法。直到在 Base.php
中發現存在此方法,此時要使用的提供器 provider 爲 Base.php
,格式器 formatter 就是 randomElement()
方法。
而後就須要將 Base 中存在 randomeElement() 的對應關係存儲起來,避免下次從新遍歷全部 provider,這就是 $this->formatters
實現的緣由。
此方法返回對應的 provider 和 formatters 後,經過 call_user_func_array
調用並返回結果。
至此,一個完整的 faker
對象生成和調用的過程就結束了。