phplaraveleloquentneo4jneoeloquent

Relationship mapping with NeoEloquent


I'm tinkering with Neo4j 2.3.0 and Laravel 5.1 using NeoEloquent. I've set up a couple of dummy nodes and some relationships between them:

image of Neo4j model - apologies, I cannot insert images directly yet :)

So articles can use a template. The inverse of this relationship is that a template is used by an article.

I've set up the classes like so:

Class Template extends Model
{
    public function articles()
    {
        return $this->hasMany('App\Article', 'USED_BY');
    }
}

And:

Class Article extends Model
{
    public function template()
    {
        return $this->belongsTo('App\Template', 'USES');
    }
}

So far, so good, I think.

I have a page where I am wanting to eventually list all of the articles in the system, along with some useful metadata, like the template each ones uses. For this, I have set something up in the controller:

$articles = array();

foreach (Article::with('template')->get() as $article) {
    array_push($articles, $article);
}

return $articles;

Not the most elegant, but it should return the data for both the article and it's associated template. However:

[{"content":"Some test content","title":"Test Article","id":28,"template":null},{"content":"Some flibble content","title":"Flibble","id":31,"template":null}]

So the question is - why is this returning null?

More interestingly, if I set up the relationship to the same thing in BOTH directions, it returns the values. i.e. if I change the USED_BY to USES, then the data is returned, but this doesn't make sense from an architectural point of view - a template does not 'use' an article.

So what am I missing?


Solution

  • More interestingly, if I set up the relationship to the same thing in BOTH directions, it returns the values.

    That's correct, because this is how it operates. It is worth knowing that the relationship methods you have defined represent the relationship itself, which means for both models Template and Article to target the USED_BY relationship from any side it has to be the same in articles() and template.

    The solution would be to use something like USES (or any notion you like) on both sides. This reference should help you make good decisions regarding your relationships.

    On the other hand, if you still wish to have different relations on the sides then kindly note that in your model (image) both relationships are in outgoing direction. i.e. Fibble-[:USES]->Template and Template-[:USED_BY]->Fibble which means template() should be an outgoing relationship such as hasOne instead of belongsTo which is incoming.