Search code examples
laravellaravel-8faker

Laravel faker valid() should not be called staticlly, but it is not


I am trying to use the valid() method that is provided with faker in Laravel, as follow:

<?php

namespace Database\Factories;

use App\Models\Attribute;
use App\Faker\AttributeValue as AttributeValueProvider;
use App\Models\Supplier;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\AttributeValue;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;


class AttributeValueFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = AttributeValue::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition(): array
    {
        $this->faker->addProvider(AttributeValueProvider::class);
        $attribute = Attribute::orderBy('id', 'desc')->first();
        $attribute_name = $attribute->translate('en')->name;
        $attribute_value = $this->faker->valid($this->is_valid_attribute_value($this, $attribute->id))->get_attribute_values($attribute_name);
        $supplier_id = Supplier::max('id');
        return [
            'en' => $attribute_value['en'] + ['supplier_id' => $supplier_id],
            'ar' => $attribute_value['ar'] + ['supplier_id' => $supplier_id],
        ];
    }

    public function is_valid_attribute_value($attribute_value, $attribute_id): bool
    {
        $valid = Validator::make(['attribute_value_translations' => $attribute_value], [
            'attribute_value' => [Rule::unique('attribute_value_translations', 'value')->where(function($q) use ($attribute_id){
                $q->where('locale', 'en')
                    ->where('attribute_id', $attribute_id);
            })]
        ])->passes();
        return $valid;
    }
}



but it throws the following error:

call_user_func_array(): Argument #1 ($callback) must be a valid callback, non-static method App\Faker\AttributeValue::valid() cannot be called statically

as you see I am not calling it staticly, help please


Solution

  • As described in the docs example code (excerpt below), Faker requires a callback as the parameter to the valid() method.

    $evenValidator = function($digit) {
        return $digit % 2 === 0;
    };
    for ($i = 0; $i < 10; $i++) {
        $values []= $faker->valid($evenValidator)->randomDigit;
    }
    

    Yet your code is passing the result of a function to the valid() method and not the function itself.

    $attribute_value = $this->faker
        ->valid($this->is_valid_attribute_value($this, $attribute->id))
    //          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  this is a boolean value, not a callback
        ->get_attribute_values($attribute_name);
    

    To use your class' validation function, you would need to change this to something like

    $attribute_value = $this->faker
        ->valid([$this, 'is_valid_attribute_value'])
        ->yourFakeProvidedValue;
    

    followed by the provided fake value. Faker will then pass the provided value into the callback for checking whether it's valid or not.