jeudi 31 janvier 2019

How to create a Class or Trait on package with autoload charging other path

Well, I'm create a package provider for extended fzaninotto/faker

For this I needs use this in the package's composer.json so that my package can become a provider of the Faker package

"autoload": {
    "psr-4": {
      "Faker\\Provider\\": "src"
    }
},

That's is no path for my package (real path package\abkrim\fake-ads\src)

When create a new faker class is easy (in path package\abkrim\fake-ads\src):

<?php

namespace Faker\Provider;

use Faker\Generator;

class MyFakerClass extends Base
{
    public function __construct(Generator $generator)
    {
        parent::__construct($generator);
    }
    ...
    // My own functions
}

And create a class file for data in same path

<?php

namespace Faker\Provider;

class MyFakerDataClass
{
    // My own code
}

Use code and work

$faker = (new \Faker\Factory())::create();
$faker->addProvider(new \Faker\Provider\Fakecar($faker));

echo $faker->someMethodOfMyFakerClass;

But I like create multiples classes (new providers in same package).

I don't know how to create a base class, because extend of Faker\Generator and name space is not my own dir.

So, I create a Helpers Class in my own dir

<?php

namespace Faker\Provider;

class Helpers
{
    /**
     * @param array $values
     * @return string
     * @throws \Exception
     */
    public static function getWeighted(array $values) :string
    {
        $currentTotal = 0;
        $firstRand = random_int(1, 100);

        $total = array_sum($values);

        $rand = ($firstRand / 100) * $total;

        foreach ($values as $key => $weight) {
            $currentTotal += $weight;

            if ($rand <= $currentTotal) {
                return $key;
            }
        }

        return '';
    }
}

For use in my provider use for example and works:

/**
 * @return string
 * @throws \Exception
 */
public static function flat() : string
{
    return Helpers::getWeighted(MyFakerDataClass::getStateTypeFlat());
}

I think taht is not best and correct method.

Plus, when I try to create a test, I can't.

<?php

namespace Faker\Tests\Provider;

use Faker\Factory;
use Faker\Generator;
use Faker\Provider\FakerRealState;
use Faker\Provider\RealStateData;
use Faker\Provider\Helpers;
use PHPUnit\Framework\TestCase;

class FakeAdsRealStateTest extends TestCase
{
    /**
     * @var Generator
     */
    private $faker;

    private $helpers;

    public function setUp()
    {
        $faker = Factory::create();
        $faker->addProvider(new FakerRealState($faker));
        $this->faker = $faker;
    }

    /**
     * @param $property
     * @param null $class
     * @return mixed
     * @throws \ReflectionException
     */
    public function getProtectedProperty($property, $class = null)
    {
        if( is_null($class))
        {
            $class = new FakerRealState($this->faker);
        }
        $reflection = new \ReflectionClass($class);
        $reflection_property = $reflection->getProperty($property);
        $reflection_property->setAccessible(true);
        return $reflection_property->getValue($class, $property);
    }

    public function testGetWeighted()
    {
        $data = [
            'key1' => 80,
            'key2' => 19,
            'key3' => 1,
        ];

        $result = array_fill_keys(array_keys($data), 0);

        for($i = 0; $i<1000; $i++)
        {
            $result[$this->faker->getWeighted($data)]++;
        }

        $this->assertGreaterThan($result['key2'], $result['key1']);
        $this->assertGreaterThan($result['key3'], $result['key2']);
        $this->assertGreaterThan($result['key3'], $result['key1']);

        $this->assertEquals('', $this->faker->getWeighted([]));
    }
}

Error

There was 1 error:

1) Faker\Tests\Provider\FakeAdsRealStateTest::testGetWeighted
InvalidArgumentException: Unknown formatter "getWeighted"

I think the difficulty lies in the fact that I do not know how to create a class to extend the rest of the suppliers under the prism of fzaninotto / Faker, or even create a Trait.

Aucun commentaire:

Enregistrer un commentaire