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

Relationships manyToOne NULL #97

Closed
ElGigi opened this issue Oct 31, 2018 · 8 comments
Closed

Relationships manyToOne NULL #97

ElGigi opened this issue Oct 31, 2018 · 8 comments

Comments

@ElGigi
Copy link

ElGigi commented Oct 31, 2018

Hi,

I have a problem with relationships manyToOne with capacity to be null.

The relation key return FALSE if the relation is NULL. I can understand that.
But the problem, it's with Atlas.Transit, the Transit object throw an exception.

For example :

Entities:

  • class Thread
  • class Author

Thread can have an author or anonymous (without author).
In the case of anonymous. The field "author" is FALSE instead NULL.
Atlas.Transit works fine with existent relation, but throw an exception if relation is NULL:

TypeError: Argument 2 passed to Atlas\Transit\Transit::newDomainEntity() must be an instance of Atlas\Mapper\Record, boolean given

Thanks.

@ElGigi
Copy link
Author

ElGigi commented Nov 6, 2018

The same problem for oneToOne relationship.

A track for resolution?

class OneToOne extends DeletableRelationship
{
    protected function stitchIntoRecord(
        Record $nativeRecord,
        array $foreignRecords
    ) : void {
        $nativeRecord->{$this->name} = false;
        if ($this->onDelete === static::SET_NULL) {
            $nativeRecord->{$this->name} = null;
        }

        foreach ($foreignRecords as $foreignRecord) {
            if ($this->recordsMatch($nativeRecord, $foreignRecord)) {
                $nativeRecord->{$this->name} = $foreignRecord;
            }
        }
    }

    // ...
}

So if reference column can be null, the value must not be false but null?

@pmjones
Copy link
Contributor

pmjones commented Nov 6, 2018

/me ponders

Can you tell me a little about the domain object that is being built from the record?

@ElGigi
Copy link
Author

ElGigi commented Nov 6, 2018

Yes.

For example:

class Author
{
    // ...

    public function __construct(?int $author_id, ?string $name)
    {
        $this->author_id = $author_id;
        // ...
    }
}

class Thread
{
    public function __construct(?int $article_id, ?string $title, ?string $content, ?Author $author)
    {
        $this->article_id = $article_id;
        // ...
    }
}

And the relationships in DataSource:

class AuthorRelationships extends MapperRelationships
{
    protected function define()
    {
        $this->oneToMany('threads',
                         Thread::CLASS,
                         [
                             'author_id' => 'author_id',
                         ]);
    }
}

class ThreadRelationships extends MapperRelationships
{
    protected function define()
    {
        $this->manyToOne('author',
                        Author::CLASS,
                        [
                            'author_id' => 'author_id',
                        ])
             ->onDeleteSetNull();
    }
}

@pmjones
Copy link
Contributor

pmjones commented Nov 6, 2018

And the problem is that sometimes, when you fetch a ThreadRecord from the data source with('author'), the author field is false because there is no related author row?

@ElGigi
Copy link
Author

ElGigi commented Nov 6, 2018

Yes is that.
If no author, for anonymous thread (for example), the field is false instead null.

@pmjones
Copy link
Contributor

pmjones commented Nov 6, 2018

All right, I think I understand now.

Some background: the false is there to indicate that you tried to fetch a relationship, but there was nothing related (as vs null which means you never tried to fetch the relationship in the first place).

The most expedient solution I can think of is to modify Atlas Transit to accept both "false" and "null" to mean "null" when the target domain property is an object. Would that work for you here?

@ElGigi
Copy link
Author

ElGigi commented Nov 6, 2018

Yes of course, that will works for me if it's implemented in Transit.

@pmjones
Copy link
Contributor

pmjones commented Nov 6, 2018

@ElGigi please examine atlasphp/Atlas.Transit#7 and see if it works for you!

@ElGigi ElGigi closed this as completed Feb 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants