首页 > 解决方案 > Laravel 5.6 - Using model functions in ModelFactory

问题描述

I am working with Laravel 5.6 and found myself a weird problem while extending the functionality of my project.

Right now i need to create two new models: order and item. It was quite easy to fill the items table with dummy data using Faker and Laravel Factories/Seeders. The biggest problem is while working with the order model.

This little fellow is related to a company with a foreign key named company_id and user with a foreign key named seller_id. The company field is okay, the trouble is behind my seller_id

This seller needs a role related to the company my factory will randomly pick for it because the user is not related to the company (directly) and i can't just look for it with a company_id.

In order to get all the users "related" to my company, i've created the next function on my Company model:

public function users()
{
    $roles = $this->roles;
    $users = [];
    foreach ($roles as $role) {
        foreach ($role->users as $user) {
            $user->makeHidden(['pivot']);
            array_push($users, $user);
        }
    }

    $users = array_unique_objects($users);
    return $users;
}

btw: I'm using laravel-permissions, a library made by Spatie.

What this functions does is get every role from a company and then it pushes it to an array of users.

This custom helper: array_unique_objects tracks any repeated user on my array and removes them.

That function works find because i've tested on a couple of controllers so i know there is no problem with it. Either way, my OrderFactory.php looks like this:

<?php

use Faker\Generator as Faker;

use App\Models\User;
use App\Models\Company;

$factory->define(App\Models\Order::class, function (Faker $faker) {
    $company = Company::get()->random(1);
    $users = $company->users();
    $user = array_random($users);
    return [
        'company_id' => $company,
        'seller_id' => $user->id,
        'code' => strtoupper(str_random(10)),
        'description' => $faker->sentence($nbWords = rand(2, 4), $variableNbWords = true),
        'created_at' => $faker->dateTimeBetween($startDate = '-1 year', $endDate = 'now', $timezone = null)
    ];
});

But when i run the php artisan db:seed command, it throws the next error in console:

BadMethodCallException : Method Illuminate\Database\Eloquent\Collection::users does not exist.

at >/home/ironman/Documentos/Sandbox/Proventas/Backend/vendor/laravel/framework/src/Illuminate/Support/Traits/Macroable.php:99 95| */ 96| public function __call($method, $parameters) 97| { 98| if (! static::hasMacro($method)) { 99| throw new BadMethodCallException(sprintf( 100| 'Method %s::%s does not exist.', static::class, $method 101| )); 102| } 103|

Exception trace:

1 Illuminate\Support\Collection::__call("users", []) /home/ironman/Documentos/Sandbox/Proventas/Backend/database/factories/OrderFactory.php:10

2 Illuminate\Database\Eloquent\Factory::{closure}(Object(Faker\Generator), []) /home/ironman/Documentos/Sandbox/Proventas/Backend/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:274

Please use the argument -v to see more details.

Is there anything I can do to fix this problem? I know that using Laravel Relationships will fix my problem but the specifications of this project says that i have to keep things just as the are.

标签: laravellaravel-5.6

解决方案


Your call to

$company = Company::get()->random(1);

does not return a single company. It returns a Collection, which does not have a users dynamic function. Try

$company = Company::get()->random(1)->first();

推荐阅读