Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Tempest wants to load a relationship for a model property #869

Open
Treggats opened this issue Dec 21, 2024 · 1 comment
Open

[Bug]: Tempest wants to load a relationship for a model property #869

Treggats opened this issue Dec 21, 2024 · 1 comment
Labels
Bug Something isn't working Database

Comments

@Treggats
Copy link
Contributor

Tempest Version

dev-main

PHP Version

8.4

Operating System

MacOS

Description

I was working with migrations and models and I wanted to dump data. However Tempest seems to want to load a relation, though I asked for a property. I also don't have any relations yet.

Didn't do a deep dive yet, so not sure how/where to debug this.

Steps to Reproduce

Migration

<?php

declare(strict_types=1);

namespace App\Migrations;

use App\Models\User;
use Tempest\Database\DatabaseMigration;
use Tempest\Database\QueryStatement;
use Tempest\Database\QueryStatements\CreateTableStatement;
use Tempest\Database\QueryStatements\DropTableStatement;

final class CreateUserTable implements DatabaseMigration
{
    public string $name = '2024-12-17_create_users_table';

    public function up(): QueryStatement
    {
        return CreateTableStatement::forModel(User::class)
            ->primary()
            ->varchar(User::NAME)
            ->varchar(User::EMAIL)
            ->unique(User::EMAIL)
            ->raw(sprintf('`%1$s` TIMESTAMP DEFAULT CURRENT_TIMESTAMP', User::CREATED_AT))
            ->raw(sprintf('`%1$s` TIMESTAMP DEFAULT CURRENT_TIMESTAMP', User::UPDATED_AT));
    }

    public function down(): QueryStatement
    {
        return DropTableStatement::forModel(User::class);
    }
}

Model

<?php

declare(strict_types=1);

namespace App\Models;

use Carbon\Carbon;
use Tempest\Database\DatabaseModel;
use Tempest\Database\IsDatabaseModel;
use Tempest\Validation\Rules\DateTimeFormat;
use Tempest\Validation\Rules\Email;
use Tempest\Validation\Rules\Length;

final class User implements DatabaseModel
{
    use IsDatabaseModel;

    final public const string
        NAME = 'name',
        EMAIL = 'email',
        CREATED_AT = 'created_at',
        UPDATED_AT = 'updated_at';

    public function __construct(
        #[Length(min: 1, max: 120)]
        public string $name,
        #[Email()]
        public string $email,
        #[DateTimeFormat('Y-m-d H:i:s')]
        public Carbon $created_at,
        #[DateTimeFormat('Y-m-d H:i:s')]
        public Carbon $updated_at,
    ) {
        //
    }
}

Command

<?php

declare(strict_types=1);

namespace App\Commands;

use App\Models\User;
use Carbon\Carbon;
use Tempest\Console\Console;
use Tempest\Console\ConsoleCommand;

final readonly class InteractiveCommand
{
    public function __construct(
        private Console $console,
    ) {
        //
    }

    #[ConsoleCommand('hello:world')]
    public function __invoke(): void
    {
        $this->console->writeln('Hello World!');
        $user = User::query()->first() ?? User::create(
            name: 'foobar',
            email: '[email protected]',
            createdAt: Carbon::now(),
            updatedAt: Carbon::now(),
        );
        $this->console->writeln('Hello ' . $user->name . '!');
        if ($user = User::query()->first()) {
            dump([
                'id' => $user->getId(),
                'name' => $user->name,
                'email' => $user->email,
                'createdAt' => $user->created_at->toDateTimeString(),
                'updatedAt' => $user->updated_at->toDateTimeString(),
            ]);

        }
    }
}

Result

~/P/tempest-cms ❯❯❯ tempest hello:world -v

Hello World!
Hello foobar!

 ×  Tempest\Database\Exceptions\MissingRelation
 ×  Could not access App\Models\User::created_at, did you forget to load it?
@Treggats Treggats added Bug Something isn't working Triage New issues that need to be reviewed by the Tempest team. labels Dec 21, 2024
@innocenzi innocenzi added Database and removed Triage New issues that need to be reviewed by the Tempest team. labels Dec 24, 2024
@Treggats
Copy link
Contributor Author

I did some digging, the following (very crude) changes output the expected data.

@brendt / @innocenzi there's probably a better way to go about this. Haven't put any thought into it yet, as I just wanted my data 😋

git diff

diff --git a/src/Tempest/Database/src/Mappers/QueryToModelMapper.php b/src/Tempest/Database/src/Mappers/QueryToModelMapper.php
index 8930987b..83cee0a2 100644
--- a/src/Tempest/Database/src/Mappers/QueryToModelMapper.php
+++ b/src/Tempest/Database/src/Mappers/QueryToModelMapper.php
@@ -4,6 +4,7 @@
 
 namespace Tempest\Database\Mappers;
 
+use Carbon\Carbon;
 use Tempest\Database\DatabaseModel;
 use Tempest\Database\Query;
 use Tempest\Mapper\Casters\CasterFactory;
@@ -130,6 +131,12 @@ private function parseProperty(PropertyReflector $property, DatabaseModel $model
             return $model;
         }
 
+        $propertyType = $property->getType()->getName();
+        $value = match($propertyType) {
+            Carbon::class => Carbon::parse($value),
+            default => $value,
+        };
+
         $property->set($model, $value);
 
         return $model;
diff --git a/src/Tempest/Reflection/src/TypeReflector.php b/src/Tempest/Reflection/src/TypeReflector.php
index 3b6d5ad2..939208b4 100644
--- a/src/Tempest/Reflection/src/TypeReflector.php
+++ b/src/Tempest/Reflection/src/TypeReflector.php
@@ -4,6 +4,7 @@
 
 namespace Tempest\Reflection;
 
+use Carbon\Carbon;
 use Exception;
 use Generator;
 use ReflectionClass as PHPReflectionClass;
@@ -33,6 +34,7 @@
         'never' => null,
         'true' => null,
         'void' => null,
+        Carbon::class => 'is_a',
     ];
 
     private string $definition;

Which gives me this

~/P/tempest-cms ❯❯❯ tempest hello:world -v
Hello World!
Hello foobar!
array:5 [
  "id" => Tempest\Database\Id {#1267
    +id: 1
  }
  "name" => "foobar"
  "email" => "[email protected]"
  "createdAt" => "2024-12-24 21:38:35"
  "updatedAt" => "2024-12-24 21:38:35"
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Database
Projects
None yet
Development

No branches or pull requests

2 participants