kitar / laravel-dynamodb

A DynamoDB based Eloquent model and Query builder for Laravel.
MIT License
178 stars 26 forks source link

Support for Factories #44

Open joelatgrayv opened 5 months ago

joelatgrayv commented 5 months ago

Should the Factories work? I get this error:

Call to undefined method Illuminate\Database\Query\Builder::usingModel()

The entry ends up in the local dynamodb but an error is thrown.

Model


 use Kitar\Dynamodb\Model\Model as DynamoModel;

 class ExampleDynamoDbModel extends DynamoModel
{
    use HasFactory;

   protected $connection = 'dynamodb';

    protected $table = 'example_table';
    protected $primaryKey = 'my_primary_key';
    protected $sortKey = 'my_sort_key';
    protected $fillable = [
        'my_primary_key',
        'my_sort_key',
    ];
}
create table '{
  "TableDescription": {
    "AttributeDefinitions": [
      {
        "AttributeName": "my_primary_key","AttributeType": "N"
      },{
        "AttributeName": "my_sort_key","AttributeType": "N"
      }
    ],"TableName": "local_example_table",
    "KeySchema": [
      {
        "AttributeName": "my_primary_key","KeyType": "HASH"
      },{
        "AttributeName": "my_sort_key","KeyType": "SORT"
      }
    ],
    "ProvisionedThroughput": {
      "ReadCapacityUnits": 1,"WriteCapacityUnits": 1
    },
    "TableClassSummary": {
      "TableClass": "STANDARD"
    }
  }
}';

Factory

<?php

namespace Database\Factories\DynamoDb;

use Illuminate\Database\Eloquent\Factories\Factory;

class ExampleDynamoDbModelFactory extends Factory
{

    public function definition(): array
    {
        return [
            'my_primary_key' => $this->faker->randomNumber(),
            'my_sort_key' => $this->faker->randomNumber(),
        ];
    }
}

Seeder

<?php

namespace Database\Seeders;

use App\Models\DynamoDb\ExampleDynamoDbModel;
use Illuminate\Database\Seeder;

class ExampleDynamoDbModelSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        // This works
        $model = new ExampleDynamoDbModel();
        $model->my_primary_key = rand();
        $model->my_sort_key = rand();
        $model->save();

        // This throws the error
        $data = ExampleDynamoDbModel::factory()->count(1)->create();
    }
}

Error Message


 sail debug db:seed --class "Database\Seeders\ExampleDynamoDbModelSeeder"

   INFO  Seeding database.  

[2024-02-02 00:52:26] local.ERROR: Call to undefined method Illuminate\Database\Query\Builder::usingModel() {"exception":"[object] (BadMethodCallException(code: 0): Call to undefined method Illuminate\\Database\\Query\\Builder::usingModel() at /var/www/html/vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:67)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(3967): Illuminate\\Database\\Query\\Builder::throwBadMethodCallException()
#1 /var/www/html/vendor/kitar/laravel-dynamodb/src/Kitar/Dynamodb/Model/Model.php(97): Illuminate\\Database\\Query\\Builder->__call()
#2 /var/www/html/vendor/kitar/laravel-dynamodb/src/Kitar/Dynamodb/Model/Model.php(154): Kitar\\Dynamodb\\Model\\Model->newQuery()
#3 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php(338): Kitar\\Dynamodb\\Model\\Model->save()
#4 /var/www/html/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(240): Illuminate\\Database\\Eloquent\\Factories\\Factory->Illuminate\\Database\\Eloquent\\Factories\\{closure}()
#5 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php(333): Illuminate\\Support\\Collection->each()
#6 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php(291): Illuminate\\Database\\Eloquent\\Factories\\Factory->store()

#7 /var/www/html/database/seeders/ExampleDynamoDbModelSeeder.php(21): Illuminate\\Database\\Eloquent\\Factories\\Factory->create()

#8 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Database\\Seeders\\ExampleDynamoDbModelSeeder->run()
#9 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#10 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#11 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#12 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
#13 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Seeder.php(184): Illuminate\\Container\\Container->call()
#14 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Seeder.php(193): Illuminate\\Database\\Seeder->Illuminate\\Database\\{closure}()
#15 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeedCommand.php(70): Illuminate\\Database\\Seeder->__invoke()
#16 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php(155): Illuminate\\Database\\Console\\Seeds\\SeedCommand->Illuminate\\Database\\Console\\Seeds\\{closure}()
#17 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeedCommand.php(69): Illuminate\\Database\\Eloquent\\Model::unguarded()
#18 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Database\\Console\\Seeds\\SeedCommand->handle()
#19 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#20 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()
#21 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\\Container\\BoundMethod::callBoundMethod()
#22 /var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\\Container\\BoundMethod::call()
#23 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\\Container\\Container->call()
#24 /var/www/html/vendor/symfony/console/Command/Command.php(326): Illuminate\\Console\\Command->execute()
#25 /var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php(180): Symfony\\Component\\Console\\Command\\Command->run()
#26 /var/www/html/vendor/symfony/console/Application.php(1096): Illuminate\\Console\\Command->run()
#27 /var/www/html/vendor/symfony/console/Application.php(324): Symfony\\Component\\Console\\Application->doRunCommand()
#28 /var/www/html/vendor/symfony/console/Application.php(175): Symfony\\Component\\Console\\Application->doRun()
#29 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(201): Symfony\\Component\\Console\\Application->run()
#30 /var/www/html/artisan(35): Illuminate\\Foundation\\Console\\Kernel->handle()
#31 {main}
"} 

   BadMethodCallException 

  Call to undefined method Illuminate\Database\Query\Builder::usingModel()

  at vendor/laravel/framework/src/Illuminate/Support/Traits/ForwardsCalls.php:67
     63▕      * @throws \BadMethodCallException
     64▕      */
     65▕     protected static function throwBadMethodCallException($method)
     66▕     {
  ➜  67▕         throw new BadMethodCallException(sprintf(
     68▕             'Call to undefined method %s::%s()', static::class, $method
     69▕         ));
     70▕     }
     71▕ }

  i   Bad Method Call: Did you mean Illuminate\Database\Query\Builder::useIndex() ? 

      +7 vendor frames 

  8   database/seeders/ExampleDynamoDbModelSeeder.php:21
      Illuminate\Database\Eloquent\Factories\Factory::create()
      +22 vendor frames 

  31  artisan:35
      Illuminate\Foundation\Console\Kernel::handle()
``
bjugan commented 5 months ago

I have a feeling your model is not using the DynamoDb connection. Try to hard code the connection in your model

protected $connection = 'dynamodb';

joelatgrayv commented 5 months ago

Sorry, I should have included my base model. It does have protected $connection = 'dynamodb';. I'll revise the example. You can see that the single model creation works in the seeder class but the factory create function throws the error.

       // This works
        $model = new ExampleDynamoDbModel();
        $model->my_primary_key = rand();
        $model->my_sort_key = rand();
        $model->save();

        // This throws the error
        $data = ExampleDynamoDbModel::factory()->count(1)->create();
joelatgrayv commented 5 months ago

The Factory was overriding the $connection in the model. For me I additionally had to revise the setConnection method to prevent this:

    protected $connection = 'dynamodb';

    public function setConnection($name)
    {
        // Don't override the $connection
        // $this->connection = $name;
        return $this;
    }