iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 11
1
Software Development

輪子們,聽口令,大部分解開始!系列 第 11

Faker(6)--自己 Provider 自己來

  • 分享至 

  • xImage
  •  

一個套件好不好用,除了它本身的功能要很厲害之外,我們也能藉由擴充功能的方法來讓套件更強大,那就再好也不過了。這正是開關原則的精神,而 Faker 正是符合此精神的套件。

就讓我們一起來證明它吧!

世間情產生器

世間情是一部八點檔連續劇,我們來試看看能不能做出一個世間情產生器,可以產生世間情的角色名字。

照 Faker 的設計,我們只需要寫一個 Provider ,再加入 Generator 即可。

我們會有兩種做法,一種是全新的 Provider 與方法,另一種是繼承 Person 並覆寫原本的 name 方法。

全新 Provider

這個方法非常簡單,先寫 Provider ,並定義好公開要讓 Generator 參考的方法(loveName):

use Faker\Provider\Base;

class Love extends Base
{
    protected static $name = array(
        '杜瑞峰',
        '郭佳佳',
        '羅元浩',
        '柯展弘',
        '趙怡琇',
        // ...
    );

    public function loveName()
    {
        return static::randomElement(self::$name);
    }
}

接著在 Generator 產生後,再使用 addProvider 方法加入即可:

$generator = Faker\Factory::create('zh_TW');
$generator->addProvider(new Love($generator));

最後即可用剛剛公開的方法 loveName ,來產生世間情角色的名字:

echo $generator->loveName . PHP_EOL;

繼承原有的 Provider

全新的方法可以全都自己定義,因此可以定的非常簡單,像上面只有取得名字。而原有的 Person 有姓有名,我們必須要想辦法讓這些方法都能回傳世間情角色的名字,相對就有點麻煩。

以下讓我們一步一步達成它吧!首先先繼承台灣版的 Persion

class Love extends \Faker\Provider\zh_TW\Person
{
}

接著,我們有以下目標的行為要覆寫:

echo $generator->name;              // 產生一個角色全名
echo $generator->firstName;         // 產生一個名
echo $generator->firstNameMale;     // 產生一個男性角色名
echo $generator->firstNameFemale;   // 產生一個女性角色名
echo $generator->lastName;          // 產生一個姓

先從 lastNamefirstNamename 的關係開始。我們 name 想要角色的全名,但 lastNamefirstName 的卻是要它們拆開的,這代表我們可能需要一個二維陣列來存放這些資料:

protected static $name = array(
    array('杜', '瑞峰'),
    array('郭', '佳佳'),
    array('羅', '元浩'),
    array('柯', '展弘'),
    array('趙', '怡琇'),
    array('朱', '卉喬'),
    array('謝', '萱萱'),
    array('謝', '曉婷'),
    array('江', '曉婷'),
    array('謝', '子奇'),
    array('杜', '仁德'),
    array('方', '思瑤'),
    array('李', '雅欣'),
    ...
);

接著 name 方法就非常簡單,把陣列組合起來就行了:

public function name($gender = null)
{
    $nameArray = static::randomElement(static::$name);

    return $nameArray[0] . $nameArray[1];
}

lastNamefirstName 則是把陣列的值各別回傳:

public function firstName($gender = null)
{
    $nameArray = static::randomElement(static::$name);

    return $nameArray[1];
}

public function lastName()
{
    $nameArray = static::randomElement(static::$name);

    return $nameArray[0];
}

再來下一個課題就是要把男女分開了,直接從 $name 的資料拆分成兩種資料:

protected static $maleName = array(
    array('杜', '瑞峰'),
    array('羅', '元浩'),
    array('柯', '展弘'),
    array('謝', '子奇'),
    array('杜', '仁德'),
);

protected static $femaleName = array(
    array('郭', '佳佳'),
    array('趙', '怡琇'),
    array('朱', '卉喬'),
    array('謝', '萱萱'),
    array('謝', '曉婷'),
    array('江', '曉婷'),
    array('方', '思瑤'),
    array('李', '雅欣'),
);

namefirstName 需要做點調整,先用最蠢的方法完成:

public function name($gender = null)
{
    if ($gender === static::GENDER_MALE) {
        $nameArray = static::randomElement(static::$maleName);
    } elseif ($gender === static::GENDER_FEMALE) {
        $nameArray = static::randomElement(static::$femaleName);
    } else {
        $nameArray = static::randomElement(array_merge(static::$maleName, static::$femaleName));
    }

    return $nameArray[0] . $nameArray[1];
}

public function firstName($gender = null)
{
    if ($gender === static::GENDER_MALE) {
        $nameArray = static::randomElement(static::$maleName);
    } elseif ($gender === static::GENDER_FEMALE) {
        $nameArray = static::randomElement(static::$femaleName);
    } else {
        $nameArray = static::randomElement(array_merge(static::$maleName, static::$femaleName));
    }

    return $nameArray[1];
}

再來有相同的程式碼是一個明顯的壞味道,我們來重構,把它抽出方法再呼叫它:

protected function loveName($gender)
{
    if ($gender === static::GENDER_MALE) {
        return static::randomElement(static::$maleName);
    } elseif ($gender === static::GENDER_FEMALE) {
        return static::randomElement(static::$femaleName);
    } else {
        return static::randomElement(array_merge(static::$maleName, static::$femaleName));
    }
}

public function name($gender = null)
{
    $nameArray = $this->loveName($gender);

    return $nameArray[0] . $nameArray[1];
}

public function firstName($gender = null)
{
    $nameArray = $this->loveName($gender);

    return $nameArray[1];
}

而男女性的呼叫相信大家應該都了解了:

public static function firstNameMale()
{
    $nameArray = static::randomElement(static::$maleName);

    return $nameArray[1];
}

public static function firstNameFemale()
{
    $nameArray = static::randomElement(static::$femaleName);

    return $nameArray[1];
}

再來假設我們原本在用 Faker ,只要有這個 class ,把它放到 Generator 後,就可以產生世間情的角色名字了!

Faker 的介紹到此結束,它是一個值得參考設計的好套件,大家有空也可以翻翻。

參考資料


上一篇
Faker(5)--Provider 們不要起爭議
下一篇
Monolog(1)--死機筆記本
系列文
輪子們,聽口令,大部分解開始!17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言