Code Monkey home page Code Monkey logo

eloquent-has-many-deep's Introduction

Eloquent HasManyDeep

CI Code Coverage Scrutinizer Code Quality Latest Stable Version Total Downloads License

This extended version of HasManyThrough allows relationships with unlimited intermediate models.
It supports many-to-many and polymorphic relationships and all their possible combinations. It also supports some third-party packages.

Supports Laravel 5.5+.

Installation

composer require staudenmeir/eloquent-has-many-deep:"^1.7"

Use this command if you are in PowerShell on Windows (e.g. in VS Code):

composer require staudenmeir/eloquent-has-many-deep:"^^^^1.7"

Versions

Laravel Package
11.x 1.20
10.x 1.18
9.x 1.17
8.x 1.14
7.x 1.12
6.x 1.11
5.8 1.8
5.5–5.7 1.7

Usage

The package offers two ways of defining deep relationships:
You can concatenate existing relationships or specify the intermediate models, foreign and local keys manually.

Concatenating Existing Relationships

Consider this example from the Laravel documentation with an additional level:
Country → has many → User → has many → Post → has many → Comment

You can define a HasManyDeep relationship by concatenating existing relationships:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeepFromRelations($this->posts(), (new Post())->comments());
    }

    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Define a HasOneDeep relationship with hasOneDeepFromRelations() if you only want to retrieve a single related instance.

Constraints

By default, constraints from the concatenated relationships are not transferred to the new deep relationship. Use hasManyDeepFromRelationsWithConstraints() with the relationships as callable arrays to apply these constraints:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeepFromRelationsWithConstraints([$this, 'posts'], [new Post(), 'comments']);
    }

    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class)->where('posts.published', true);
    }
}

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class)->withTrashed();
    }
}

Make sure to qualify the constraints' column names if they appear in multiple tables:
->where('posts.published', true) instead of ->where('published', true)

Third-Party Packages

Besides native Laravel relationships, you can also concatenate relationships from these third-party packages:

Defining Relationships Manually

If you don't have all the necessary existing relationships to concatenate them, you can also define a deep relationship manually by specifying the intermediate models, foreign and local keys.

HasMany

Consider this example from the Laravel documentation with an additional level:
Country → has many → User → has many → Post → has many → Comment

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}

Just like with hasManyThrough(), the first argument of hasManyDeep() is the related model. The second argument is an array of intermediate models, from the far parent (the model where the relationship is defined) to the related model.

By default, hasManyDeep() uses the Eloquent conventions for foreign and local keys. You can also specify custom foreign keys as the third argument and custom local keys as the fourth argument:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(
            Comment::class,
            [User::class, Post::class], // Intermediate models, beginning at the far parent (Country).
            [
               'country_id', // Foreign key on the "users" table.
               'user_id',    // Foreign key on the "posts" table.
               'post_id'     // Foreign key on the "comments" table.
            ],
            [
              'id', // Local key on the "countries" table.
              'id', // Local key on the "users" table.
              'id'  // Local key on the "posts" table.
            ]
        );
    }
}

You can use null placeholders for default keys:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class], [null, 'custom_user_id']);
    }
}

ManyToMany

You can include ManyToMany relationships in the intermediate path.

ManyToMany → HasMany

Consider this example from the Laravel documentation with an additional HasMany level:
User → many to many → Role → has many → Permission

Add the pivot tables to the intermediate models:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep(Permission::class, ['role_user', Role::class]);
    }
}

If you specify custom keys, remember to swap the foreign and local key on the "right" side of the pivot table:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep(
            Permission::class,
            ['role_user', Role::class], // Intermediate models and tables, beginning at the far parent (User).
            [           
               'user_id', // Foreign key on the "role_user" table.
               'id',      // Foreign key on the "roles" table (local key).
               'role_id'  // Foreign key on the "permissions" table.
            ],
            [          
              'id',      // Local key on the "users" table.
              'role_id', // Local key on the "role_user" table (foreign key).
              'id'       // Local key on the "roles" table.
            ]
        );
    }
}
ManyToMany → ManyToMany

Consider this example from the Laravel documentation with an additional ManyToMany level:
User → many to many → Role → many to many → Permission

Add the pivot table to the intermediate models:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep(Permission::class, ['role_user', Role::class, 'permission_role']);
    }
}

MorphMany

You can include MorphMany relationships in the intermediate path.

Consider this example from the Laravel documentation with an additional level:
User → has many → Post → morph many → Comment

Specify the polymorphic foreign keys as an array, starting with the *_type column:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postComments()
    {
        return $this->hasManyDeep(
            Comment::class,
            [Post::class],
            [null, ['commentable_type', 'commentable_id']]
        );
    }
}

MorphToMany

You can include MorphToMany relationships in the intermediate path.

Consider this example from the Laravel documentation with an additional level:
User → has many → Post → morph to many → Tag

Add the pivot table to the intermediate models and specify the polymorphic foreign keys as an array, starting with the *_type column:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postTags()
    {
        return $this->hasManyDeep(
            Tag::class,
            [Post::class, 'taggables'],
            [null, ['taggable_type', 'taggable_id'], 'id'],
            [null, null, 'tag_id']
        );
    }
}

Remember to swap the foreign and local key on the "right" side of the pivot table:

MorphedByMany

You can include MorphedByMany relationships in the intermediate path.

Consider this example from the Laravel documentation with an additional level:
Tag → morphed by many → Post → has many → Comment

Add the pivot table to the intermediate models and specify the polymorphic local keys as an array, starting with the *_type column:

class Tag extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postComments()
    {
        return $this->hasManyDeep(
            Comment::class,
            ['taggables', Post::class],
            [null, 'id'],
            [null, ['taggable_type', 'taggable_id']]
        );
    }
}

BelongsTo

You can include BelongsTo relationships in the intermediate path:
Tag → morphed by many → Post → belongs to → User

Swap the foreign and local key:

class Tag extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postAuthors()
    {
        return $this->hasManyDeep(
            User::class,
            ['taggables', Post::class],
            [null, 'id', 'id'],
            [null, ['taggable_type', 'taggable_id'], 'user_id']
        );
    }
}

HasOneDeep

Define a HasOneDeep relationship if you only want to retrieve a single related instance:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function latestComment()
    {
        return $this->hasOneDeep(Comment::class, [User::class, Post::class])
            ->latest('comments.created_at');
    }
}

Composite Keys

If multiple columns need to match between two tables, you can define a composite key with the CompositeKey class.

Consider this example from the compoships documentation with an additional level:
User → has many (matching team_id & category_id) → Task → belongs to → Project

use Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey;

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function projects()
    {
        return $this->hasManyDeep(
            Project::class,
            [Task::class],
            [new CompositeKey('team_id', 'category_id'), 'id'],
            [new CompositeKey('team_id', 'category_id'), 'project_id']
        );
    }
}

Intermediate and Pivot Data

Use withIntermediate() to retrieve attributes from intermediate tables:

public function comments()
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class);
}

foreach ($country->comments as $comment) {
    // $comment->post->title
}

By default, this will retrieve all the table's columns. Be aware that this executes a separate query to get the list of columns.

You can specify the selected columns as the second argument:

public function comments()
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class, ['id', 'title']);
}

As the third argument, you can specify a custom accessor:

public function comments()
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class, ['id', 'title'], 'accessor');
}

foreach ($country->comments as $comment) {
    // $comment->accessor->title
}

If you retrieve data from multiple tables, you can use nested accessors:

public function comments()
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class)
        ->withIntermediate(User::class, ['*'], 'post.user');
}

foreach ($country->comments as $comment) {
    // $comment->post->title
    // $comment->post->user->name
}

Use withPivot() for the pivot tables of BelongsToMany and MorphToMany/MorphedByMany relationships:

public function permissions()
{
    return $this->hasManyDeep(Permission::class, ['role_user', Role::class])
        ->withPivot('role_user', ['expires_at']);
}

foreach ($user->permissions as $permission) {
    // $permission->role_user->expires_at
}

You can specify a custom pivot model as the third argument and a custom accessor as the fourth:

public function permissions()
{
    return $this->hasManyDeep(Permission::class, ['role_user', Role::class])
        ->withPivot('role_user', ['expires_at'], RoleUser::class, 'pivot');
}

foreach ($user->permissions as $permission) {
    // $permission->pivot->expires_at
}

Intermediate and Pivot Constraints

You can apply constraints on intermediate and pivot tables:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}

$commentsFromActiveUsers = $country->comments()->where('users.active', true)->get();

Table Aliases

If your relationship path contains the same model multiple times, you can specify a table alias:

class Post extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function commentReplies()
    {
        return $this->hasManyDeep(Comment::class, [Comment::class . ' as alias'], [null, 'parent_id']);
    }
}

Use the HasTableAlias trait in the models you are aliasing:

class Comment extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;
}

For pivot tables, this requires custom models:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep(Permission::class, [RoleUser::class . ' as alias', Role::class]);
    }
}

class RoleUser extends Pivot
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;
}

Use setAlias() to specify a table alias when concatenating existing relationships:

class Post extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function commentReplies()
    {
        return $this->hasManyDeepFromRelations(
            $this->comments(),
            (new Comment())->setAlias('alias')->replies()
        );
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

class Comment extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;

    public function replies()
    {
        return $this->hasMany(self::class, 'parent_id');
    }
}

Soft Deleting

By default, soft-deleted intermediate models will be excluded from the result. Use withTrashed() to include them:

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class])
            ->withTrashed('users.deleted_at');
    }
}

class User extends Model
{
    use SoftDeletes;
}

Getting Unique Results

Deep relationships with many-to-many segments can contain duplicate models in their results. If you want to get unique results, you can remove duplicates from the result collection:

$uniqueComments = Country::find($id)->comments()->get()->unique();

If you need to remove duplicates in the query (e.g. for pagination), try adding distinct():

$uniqueComments = Country::find($id)->comments()->distinct()->get();

distinct() doesn't work for all cases. If it doesn't work for you, use groupBy() instead:

$uniqueComments = Country::find($id)->comments()
    ->getQuery()             // Get the underlying query builder
    ->select('comments.*')   // Select only columns from the related table
    ->groupBy('comments.id') // Group by the related table's primary key 
    ->get();

Reversing Relationships

You can define a HasManyDeep/HasOneDeep relationship by reversing an existing deep relationship using hasManyDeepFromReverse()/hasOneDeepFromReverse():

class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}

class Comment extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function country()
    {
        return $this->hasOneDeepFromReverse(
            (new Country())->comments()
        );
    }
}

IDE Helper

If you are using barryvdh/laravel-ide-helper, this package provides a model hook that will correctly add relations when generating the type hints. The model hook is enabled by default using Package Discovery.

To enable it manually, add model hook to the model_hooks array.

    // File: config/ide-helper.php

    /*
    |--------------------------------------------------------------------------
    | Models hooks
    |--------------------------------------------------------------------------
    |
    | Define which hook classes you want to run for models to add custom information
    |
    | Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
    |
    */

    'model_hooks' => [
        \Staudenmeir\EloquentHasManyDeep\IdeHelper\DeepRelationsHook::class,
    ],

To disable the model hook you have 3 options:

Disable using .env

Update your .env file to include:

ELOQUENT_HAS_MANY_DEEP_IDE_HELPER_ENABLED=false

Disable using config

Publish the config and disable the setting directly:

php artisan vendor:publish --tag=eloquent-has-many-deep
    // File: config/eloquent-has-many-deep.php
    
    /*
    |--------------------------------------------------------------------------
    | IDE Helper
    |--------------------------------------------------------------------------
    |
    | Automatically register the model hook to receive correct type hints
    |
    */
    'ide_helper_enabled' => false,

Disable by opting out of Package Discovery

Update your composer.json with the following:

"extra": {
    "laravel": {
        "dont-discover": [
            "staudenmeir/eloquent-has-many-deep"
        ]
    }
},

Contributing

Please see CONTRIBUTING and CODE OF CONDUCT for details.

eloquent-has-many-deep's People

Contributors

ahoiroman avatar daniel-de-wit avatar decadence avatar hafezdivandari avatar iwasherefirst2 avatar lidoma avatar staudenmeir avatar szepeviktor avatar thijsdejong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eloquent-has-many-deep's Issues

Query hasManyDeep

Hello, me again... (sorry!)

I currently have have the following relation setup on my Collective model (as per #2)

public function videos()
{
    return $this->hasManyDeep(Video::class, [Artist::class, 'artist_video'])->groupBy('videos.id');
}

How can I query this relation? I'm currently trying the following:

$collective->videos()->where('slug', 'my-slug')->first();

However I'm receiving the following error:

Integrity constraint violation: 1052 Column 'slug' in where clause is ambiguous (SQL: select videos.*, artists.collective_id from videos inner join artist_video on artist_video.video_id = videos.id inner join artists on artists.id = artist_video.artist_id where artists.collective_id = 1 and slug = my-slug group by videos.id limit 1)

Any ideas how I can get this to work?

Thanks in advance!

Incorrect join if alias is used

Hi!

If I have something like the following:

class Post extends Model
{
    public function similar()
    {
        return $this->hasManyDeep(
            self::class,
            ['taggable as alias', Tag::class, 'taggable']
        );
    }
}

The following sql is generated:

select "posts".*, "taggable" as "alias.post_post_pk"
from "posts"
       inner join "taggable" on "taggable"."post_post_pk" = "posts"."post_pk"
       inner join "tags" on "tags"."tag_pk" = "taggable"."tag_tag_pk"
       inner join "taggable" as "alias" on "taggable" as "alias.tag_tag_pk" = "tags"."tag_pk"
where "taggable" as "alias.post_post_pk" = 1

As you can see the "taggable" as "alias.tag_tag_pk" is the problematic part.

The error first occurs in HasManyDeep:110 as inside Model::qualifyColumn $this->getTable() returns project_category as alias. Then $this->getQualifiedFirstKeyName() returns the same so when the where is added this generates the wrong alias.

Edit: Example is replaced with Models from the test of this package.

problem for multiple level of table same category 3 level

hi, im using category table multiple level, for relation of grandpa(level 1) category with product use this package witch very well and work, but relation of father(level 2) category with product not work, this relation

public function throughProducts() { return $this->hasManyThrough(Category::class, 'App\Models\Category', 'parent_id', 'parent_id'); }
this error :

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'categories' (SQL: select count(*) as aggregate from categories inner join categories on categories.id = categories.parent_id where categories.parent_id = 2)

Unable to save() relation

When working on a simple hasManyDeep() relation, I'm unable to save() a new relation.
I can see there's no InteractsWithPivotTable trait used by these relations.
Would it be compatible to add mutating queries inside InteractsWithPivotTable to your relationships?

Global model scopes ignored in HasManyDeep

I have global scopes that are applied in the boot() method of some of my models in a HasManyDeep relationship.

It seems like these are being ignored - in effect, I'm getting data that I shouldn't be because my model 'active' property is being ignored.

Is this expected behaviour, or should global scopes apply in intermediate models?

MorphToMany and MorphMany

Is this possible using this package?

Event → morpthToMany → Product → morphMany → OrderItem

Thank you

Empty array returned (BelongsToMany -> BelonggsToMany -> BelongsToMany)

So, I have this type of relationship:

ApplicationType -> Many To Many -> Page -> Many To Many -> Section -> Many To Many -> Question

My relationship with hasManyDeep:

        /**
	 * @return \Staudenmeir\EloquentHasManyDeep\HasManyDeep|Question
	 */
	public function questions()
	{
		return $this->hasManyDeep(Question::class,
			[
				'application_types_pages',
				Page::class,
				'pages_sections',
				Section::class,
				'sections_questions'
			]
		);
	}

This one returns [] and it should return 3 objects.

This is my corresponding join statements:

ApplicationType
    ::whereId(1)
    ->join('application_types_pages', 'application_types.id', '=', 'application_types_pages.application_type_id')
    ->join('pages', 'application_types_pages.page_id', '=', 'pages.id')
    ->join('pages_sections', 'pages.id', '=', 'pages_sections.page_id')
    ->join('sections', 'pages_sections.section_id', '=', 'sections.id')
    ->join('sections_questions', 'sections.id', '=', 'sections_questions.section_id')
    ->join('questions', 'sections_questions.question_id', '=', 'questions.id')
    ->get();

This one returns everything as intended but I hate joins as it it returning messy single layer array.
Am I doing anything wrong?

HasManyThroughBelongsToMany

screen shot 2019-01-01 at 3 41 26 pm

class BroadActivity extends Model
{
    use HasRelationships;

    public function detailActivities()
    {
        return $this->hasMany(DetailActivity::class);
    }

    public function targets()
    {
        // How to relate the Targets with pivot value (target_value)?
    }
}
class DetailActivity extends Model
{
    public function broadActivity()
    {
        return $this->belongsTo(BroadActivity::class);
    }

    public function targets()
    {
        return $this->belongsToMany(Target::class)->withPivot('target_value');
    }
}
class Target extends Model
{
    public function detailActivities()
    {
        return $this->belongsToMany(DetailActivity::class);
    }
}

How to create a relation in BroadActivity model to Target with additional pivot values?

belongsTo through hasMany

Is this possible using this package?

User → hasMany → Campaign → belongsTo → Template.

I need $user->templates.

now I use:

public function getTemplatesAttribute()
{
    return $this->campaigns->map->template;
}

But this is just a Collection, not relationship.

Thanks!

Merge HasManyDeep on MorphMany at different levels

Scenario:

I have Institution -> Departments -> Qualifications -> Courses and both Qualification and Course morph Group. I want to load all groups for an institution.

I tried:

/**
 * Get all of the Institution's groups.
 */
public function groups()
{
    return $this->hasManyDeepFromRelations(
        $this->qualificationsGroups(), $this->coursesGroups()
    );
}

/**
 * Get all of the Institution's qualifications' groups.
 */
public function qualificationsGroups()
{
    return $this->hasManyDeep(
        Group::class,
        [Department::class . " as d1", Qualification::class . " as q1"],
        [null, null, ['groupable_type', 'groupable_id']]
    );
}

/**
 * Get all of the Institution's courses' groups.
 */
public function coursesGroups()
{
    return $this->hasManyDeep(
        Group::class,
        [Department::class . " as d2", Qualification::class . " as q2", Course::class],
        [null, null, null, ['groupable_type', 'groupable_id']]
    );
}

Issue:

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'groups' (SQL: select count(*) as aggregate from groups........

Question:
How do I resolve this or any other approach to loading groups for both courses and qualifications under an institution?

Support table aliases with BelongsToMany relationships.

Assume the following entities:

  • User
  • UserGroup
  • Organization

Assume the following relationships:

  • User belongs to many Organizations.
  • User belongs to many UserGroups.

Given above, we need a relationship User::organizationsOfUsersWithSharedUserGroups(), that would return all the Organizations that belongs to any of the Users that shares UserGroups with the calling User object.

PHP has to:

  1. Start with the current User object,
  2. get its UserGroups,
  3. get Users of those UserGroups (Thus coming back to the User class, through the same pivot table.),
  4. and get Organizations of those Users.

Following relationship definition accomplishes what I am after, with one caveat:

public function organizationsOfUsersWithSharedUserGroups() {
	return $this->hasManyDeep(
		Organization::class,
		[
			'user_user_group',
			UserGroup::class,
			'user_user_group2',
			User::class,
			'organization_user',
		]
	);
}

The caveat being user_user_group2 being a MySQL view defined as follows:

CREATE
OR REPLACE
VIEW `db`.`user_user_group2` AS select
    `db`.`user_user_group`.`id` AS `id`,
    `db`.`user_user_group`.`user_id` AS `user_id`,
    `db`.`user_user_group`.`user_group_id` AS `user_group_id`
from
    `db`.`user_user_group`

Table user_user_group and view user_user_group2 are identical.

If we replace user_user_group2 with user_user_group in User::organizationsOfUsersWithSharedUserGroups()'s definition, we get the following error:

SQLSTATE[42000]: Syntax error or access violation:
1066 Not unique table/alias: 'user_user_group'

(SQL:

select
	`organizations`.*,
	`user_user_group`.`user_id` as `laravel_through_key`
from
	`organizations`
	inner join `account_user`
		on `account_user`.`account_id` = `organizations`.`id`
	inner join `users`
		on `users`.`id` = `account_user`.`user_id`
	inner join `user_user_group`
		on `user_user_group`.`user_id` = `users`.`id`
	inner join `user_groups`
		on `user_groups`.`id` = `user_user_group`.`user_group_id`
	inner join `user_user_group`
		on `user_user_group`.`user_group_id` = `user_groups`.`id`
where
	`users`.`deleted_at` is null
	and `user_groups`.`deleted_at` is null
	and `user_user_group`.`user_id` = 1
	and `organizations`.`deleted_at` is null
)

I tried to specify an as in User::organizationsOfUsersWithSharedUserGroups()'s definition as follows, but it did not work.

public function organizationsOfUsersWithSharedUserGroups() {
	return $this->hasManyDeep(
		Organization::class,
		[
			'user_user_group',
			UserGroup::class,
			'user_user_group as alias',
			User::class,
			'organization_user',
		]
	);
}

Thus, I would like to propose supporting table aliases with BelongsToMany relationships.

Support for ManyToMany?

Given the relationship:
Country → has many to many → User → has many to many → Post

Can we get: all Posts of all Users in a Country

hasManyDeepJson ?

Hi, your work saved my life in terms of Eloquent Relationships everything that I needed was related to you on github 🥇
I wonder if it would be possible to have a hasManyDeepJson kind of hybrid like this :

class Mapregion extends Model { public function groups() { return $this->hasManyDeepJson('Models\Group', ['Models\Subregion', 'address->hq->country_id']); } }
thanks a lot

More levels of Many-to-many

Your extension looks very promising. However I'm not sure how it handles more levels of many-to-many relations.

Example: App\User belongsToMany App\Group belongsToMany App\Album belongsToMany App\Photo.

How would I get photos belonging to a user? I'm wondering how I would use the hasManyDeep() method.

How to use query scope with hasManyDeepFromRelations?

Thank you for this wonderful package. I just came to know about it recently and it has already made many parts of my code simpler.

I went through the documentation but there's one problem where I would appreciate some help.

I have the following relationship:

  • Lawyer office hasMany Lawyers
  • Lawyer belongsToMany Companies
  • Company belongsToMany Lawyers
  • Company hasMany Claims

Now I was able to get the companies of the lawyer office by using hasManyDeepFromRelations as

// Inside LawyerOffice Model

public function companies()
{
    return $this->hasManyDeepFromRelations($this->lawyers(), (new Lawyer)->companies())->active();
}

But when I do the same for claims as

public function claims()
{
    return $this->hasManyDeepFromRelations($this->companies(), (new Company)->claims());
}

It ignores the active() query scope of the companies and returns claims of all the companies.

I assume this is something related to #35 but I am not sure where should I add the query scope manually.

Can you please guide me on how can I add query scope or where() condition in order to get the claims of the active companies of a lawyer office.

Thank you.

Possible to merge two Relations?

Hi

I've successfully implemented this Laravel package, it's awesome

I have two possible Relations:

Order -> belongs to many -> DeliveryOrder -> belongs to many -> Invoices
Order -> belongs to many -> Invoices

Some Orders can relate directly to Invoices, some will have to go through DeliveryOrder

They have different possible paths but the start and end Models of the possible paths are the same

I'm able to use hasManyDeep to get both relations, separately

But how can we add support or workaround to combine the two Relations into one?

(not asking to convert into a Collection or array and merge them, that's cheating)

Thanks!

relation between 3 tabels

i have 3 table and want to make relation between them

order:
id,total

order_details:
order_id
dish_name

extra_items
id
title

order_details_extra_items
order_details_id
extra_items_id

how can make relation between them in Order Model؟
i try to use this function

public function order_details_extra()
{
    return $this->hasManyDeep(
        'App\Models\OrderDetails',
        ['order_details_extra_items', 'App\Models\ExtraItems'], 
        [           
           'order_details_id',
           'id',   
           'order_id'  
        ],
        [          
          'id',    
          'extra_items_id', 
          'id'     
        ]
    );
} 

Suggestion: Inform users about MySQL's View (virtual tables)?

Hi @staudenmeir

I really appreciate the repo

Out of desperation, I've moved a lot of advanced relationships to depend on MySQL's View instead

Creating a fake table, to trick laravel, eager loading, etc has been working

Have been depending on subquery joins lately
also, users should be discouraged to use appends() and use leftJoin() instead

I guess Laravel is built without having deep relationships in mind, which leaves out a lot of functions, causing a lot of limitations

Now I can even union relationships, adding where clauses for the relationships etc.

Would be nice if I knew earlier that Laravel's not capable and MySQL's View is there to help

If I'm right, please add a note to point out MySQL's View is the way to go if the relations are to advanced

In fact, I think Laravel should allow Migrations to create virtual tables

Part of my code that creates a fake relationship, based on the distance of an Address's GPS, to a Polygon of the ServiceArea table. The distance must be less than 0.05

      $query = DB::query()->selectRaw("
            #SELECT
                *
            FROM
                (
                SELECT
                    `crm_addresses`.`id` AS `address_id`,
                    `crm_servicearea`.`id` AS `service_area_id`,
                    `crm_addresses`.`updated_at` AS `updated_at`,
                    `crm_addresses`.`created_at` AS `created_at`,
                    FORMAT(ST_DISTANCE(
                        `crm_servicearea`.`polygon`,
                        `crm_addresses`.`gps`
                    ), 6) AS `distance`
                FROM
                    `crm_addresses`
                INNER JOIN `crm_servicearea` WHERE `crm_addresses`.`gps` IS NOT NULL
                ORDER BY
                    `address_id`,
                    `distance`
            ) AS address_service_area
            WHERE
                `distance` <= 0.05
        ");
        }

then:

        $query_string = getSqlString$query);
        $sql = "create view `{$pivot_table_name}` as {$query_string}";
        DB::statement($sql);

support eager-limit?

Hi, does hasOneDeep() supports HasEagerLimit ?
The docs said that it supports laravel's basic relationships HasOne/HasOneThrough/MorphOne but I'm using your hasOneDeep relationships.

Is it possible to use the window function from the hasOneDeep relationships?
Thank you

Privot id column at hasManyDeep relation

Hello, i have hasManyDeep relation using table aliases and in result i have my result model columns and one column of one pivot tables.
Like:

select vertices.*, head_vertices.user_id from

head_vertices.user_id is not a part of result model columns.

If i try to add select('vertices.') to relation, it doesn't change anything. The only way to hide this column is use getQuery()->select('vertices.'). But in this case i get a Builder instance instead a relationship instance.

withIntermediate eager loading relationships

The filtering is working as expected but, is there any way to eager load relationships for a intermediate/pivot table?

public function teachers()
{
       return $this->hasManyDeepFromRelations($this->enrolments(), (new Enrolment())->user())
                    ->withIntermediate(Enrolment::class)
                    ->where('request_status', 'Approved') //Filter by Enrolment column
                    ->with('school')               //Enrolment model relationship (Doesn't work)
                    ->with('enrolment.school')     //I have also tried this (Doesn't work)
                    ->with('courses')           //User model relationship (Works)
                    ->whereHas('roles', function ($query) { //Filter by user.roles column
                        $query->where('name', 'teacher');
                    });
}

I tried this as well but I see that hasManyDeepFromRelations doesn't preserve additional constraints. #36 (comment)

public function enrolments()
{
        return $this->hasManyThrough(
            Enrolment::class,
            CourseSchool::class,
            'course_id',
            'course_school_id'
        )
                    ->with('school'); //Also doesn't work
                    
}

Ids gets mixed up with the previous table's ID

Hi,

I have this example in the Address model

Address has BillingAccount through Account
Address -> Account -> BillingAccount

However, the ID return on the Address array is of the Account array instead.

 public function address_with_billing_account()
    {
        return $this->hasManyDeep(
            BillingAccount::class,
            [
                Account::class,
            ],
            [
                'id', //id of account in account table
                'id',  //id of billing account in billing account table
            ],
            [
                'account_id', //id of account in address table
                'billing_account_id', //id of billing account in account table
            ]
            );
            
        // equivalent:
        // return $this->account->billing_account();
    }

It seems to be related to the fact that joins is being used, but then a select query used is of the Account id, that's why Address id gets overridden (because same column name)

Has anyone faced this issue?

Thanks

Detach not working

I am using your package but the detach method for a deep relationship is not working for me.
There are any know problem with it?

Error in the README

I think there's a typo, otherwise I didn't catch the belongsToMany paragraph

Its written
public function permissions() { return $this->hasManyDeep('App\Permission', ['role_user', 'App\Role']); }

Shouldn't it be
public function permissions() { return $this->belongsToMany('App\Permission', ['role_user', 'App\Role']); }
?

query builder

how can i write query builder on this package for each spesfic model like where clause for columuns

belongsTo OR hasOneDeep

Do any of your relationships allow for a merge of a belongsTo and a hasOneDeep, like:
ifnull(belongsTo,hasOneDeep)

Currently:

public function locationPaymentMethod(){
	return $this->belongsTo('App\Models\PaymentMethod','payment_method_id');
}

public function paymentMethod(){
	// get this location.paymentMethod or the location.company.paymentMethod
	return $this->locationPaymentMethod ? $this->locationPaymentMethod() : $this->hasOneDeep('App\Models\PaymentMethod',['App\Models\Location', 'App\Models\Company'],['id','id','id'],['id','company_id','payment_method_id'])->latest();
}

I'm looking to eliminate that ternary check when getting Location::with('paymentMethod')->get()

Is there any way using BelongsToThrough with hasManyDeepFromRelations

I'm trying to using BelongsToThrough package with this package. But combining two of them it's not working. Maybe I'm missing something easy but anyway I want to get Orders -> Areas.

My Relations look like this;

Order → belongs to → Address → belongs to → District -> belongs to many -> Area

My Tables

orders

id other_columns address_id
1 Something 1

addresses

id other_columns district_id
1 Something 1

districts

id name
1 Kadıkoy

areas

id name
1 First Area

area_district

area_id district_id
1 1

My Code

In my Order model I have districts relation

public function districts ()
{
    return $this->belongsToThrough(District::class, Address::class);
}

When I add areas relation like this;

public function areas ()
{
    return $this->hasManyDeepFromRelations($this->districts(), (new District())->areas());
}

I got Exceptions because in your hasOneOrManyDeepRelationMethod hasn't BelongsToThrough

Is there any way to use both? Or maybe I miss something and Can anyone help?

Thanks,
Can

Tag v1.8 *requires* Laravel 5.8, not supports

Not sure if this is intentional, but since the README on 1.8 still says "supports laravel 5.5.29+", I'm guessing it's not.

I have laravel/framework locked to 5.5.* in my composer file (5.5 is LTS), and when attempting to install 1.8 I get a conflict due to the laravel requirements in your composer.json.

Output follows

# composer require staudenmeir/eloquent-has-many-deep:"^1.8"
./composer.json has been updated                                                    
Loading composer repositories with package information
Updating dependencies (including require-dev) 
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for staudenmeir/eloquent-has-many-deep ^1.8 -> satisfiable by staudenmeir/eloquent-has-many-deep[v1.8].
    - Conclusion: remove laravel/framework v5.5.45
    - Conclusion: don't install laravel/framework v5.5.45
    - staudenmeir/eloquent-has-many-deep v1.8 requires illuminate/database 5.8.* -> satisfiable by illuminate/database[v5.8.0, v5.8.11, v5.8.12, v5.8.14, v5.8.15, v5.8.2, v5.8.3, v5.8.4, v5.8.8, v5.8.9].
    - don't install illuminate/database v5.8.0|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.11|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.12|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.14|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.15|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.2|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.3|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.4|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.8|don't install laravel/framework v5.5.45
    - don't install illuminate/database v5.8.9|don't install laravel/framework v5.5.45
    - Installation request for laravel/framework (locked at v5.5.45, required as 5.5.*) -> satisfiable by laravel/framework[v5.5.45].


Installation failed, reverting ./composer.json to its original content.

hasOneDeep

Nice Packages @staudenmeir,

I have an issue.
having following tables
country table

id name code
int string string

city table

id country_id name
int int string

University table

id city_id name other_columns
int int string type

I'm Filtering According To The Country And Other Column On The University Table.
The Issue Here Is University table only hascity_id but I Want Use University table instead of the city table How I can acheive that with hasOneDeep

belongsToMany and BelongsTo ?

Hi, I have relationships like this:
User → belongsToMany Product → BelongsTo Customer

User Table: user.id

Product Table :
---- product.id
---- product.customer_id

Pivot table:
---- product_user.user_id
---- product_user.product_id

Customer Table:
customer.id

Does eloquent-has-many-deep support this? I only found this similar but for morphed by many:
Tag → morphed by many → Post → belongs to → User

How can I get user->customer() and reverse: customer->user() ?

Thank you!

breaks if you use same table twice..

i have a parent->student->assignments->tutor..

now parent/student Model while separate (extending USER Model) use same users table with type_id.. and has a parent_id which signifies whether a row has a parent...

i tried doing:

 {
     // Country → has many → User → has many → Post → has many → Comment
     return $this->hasManyDeep(Tutor::class, [Student::class, 'assignments'], [
         'parent_id', // Foreign key on the "users" table.
         'student_id',    // Foreign key on the "posts" table.
         'tutor_id'     // Foreign key on the "comments" table.
     ]);
 }

on my Client model but it returns:

Illuminate/Database/QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'users' (SQL: select `users`.*, `users`.`parent_id` from `users` inner join `assignments` on `assignments`.`id` = `users`.`tutor_id` inner join `users` on `users`.`id` = `assignments`.`student_id` where `users`.`parent_id` = 1 and `type_id` = 4)'

Is it just me or are the examples in the documentation extremely confusing?

This looks like an amazing library and exactly what I need. However, I've literally read the examples 50 times trying to figure out how to accomplish what I need, but I just can't understand it. First of all, does this library work for my situation? And if so, what is the proper relationship definition?

I'm have the following relationship:

Product -> belongsTo -> SSIN -> belongsToMany -> stockableItems

I am trying to set up a stockableItems relationship on the Product model.

I can not for the life of me figure out the right way to do this. Can anyone help? Here is something I tried, using the advanced hasManyDeepFromRelations method:

public function stockableItems() {
    return $this->hasManyDeepFromRelations(
        $this->ssin(),
        (new Ssin)->stockableItems()
    );
}

This seemed to work, but then I noticed that when I retrieved $product->stockableItems, the stockableItems were actually being returned with the wrong ID. For some reason they were being assigned an ID equal to the ssin_id from the ssin_stockable_item join table.

I'm not sure if this is a bug or if my setup is wrong. Also, I probably don't even need to use the hasManyDeepFromRelations method, but as stated above, I can't figure out from the documentation how this relationship is supposed to be set up.

How to get all Movies that are playing on a MovieTheater?

First of all, thanks for try to make our lifes easier! This is a very good solution. :)

Give me a little help?

I have the following eloquent entities:

  • Movie
  • MovieSession
  • MovieTheater
  • MovieTheaterRoom

where a MovieTheater hasMany MovieTheaterRooms, each MovieTheaterRoom hasMany MovieSessions and each MovieSession belongsTo a Movie.

What I'm trying, is to get all Movies that are playing today on a MovieTheater by its $movieTheaterId, but since it is a long relation, I'm unable of retrieve such collection.

This is what I'have tried:

class MovieTheater extends Model {
    use HasRelationships;

    public function movies()
    {
        return $this->hasManyDeep(Movie::class, [MovieSession::class, MovieTheaterRoom::class]);
    }
}

And when calling App\Models\MovieTheater::find(1)->movies()->get()

This is the output:

Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'movie_sessions.movie_theater_id' in 'field list' (SQL: select movies.*, movie_sessions.movie_theater_id from movies inner join movie_theater_rooms on movie_theater_rooms.id = movies.movie_theater_room_id inner join movie_sessions on movie_sessions.id = movie_theater_rooms.movie_session_id where movie_sessions.movie_theater_id = 1)'

Where I'm wrong?

HasMany and BelongsToMany

Is this possible using this package?

Region → has many → Destination → belongs to many → Activity

I would like to get activities for region

Thank you

Can this be used with belongsToMany?

Hello,

Excellent package! I currently have the following relations;

User → belongsToMany → Area → hasMany → Venue

Is there a way for me to get the users venues? $user->venues;


A venue can then have "entries".

Venue → hasMany → Entry

I would then like to get the users entries based on the above. Is this possible?

My end goal would be to be able to do this;

// fetch the users venues based on the areas they're assigned to
$venues = $user->venues;

// fetch the users entries based on the venues the entries are assigned to (the above needs to be done first perhaps?)
$entries = $user->entries;

Hope you can help!

Possibility to add a BelongsToThrough relationship

Hi!

This library works like a charm! The only issue I currently have is that I'd like to define the reverse of the HasManyDeep relation, so in your example the Comment model having a singular Country. Would it be possible to add this relationship as well?

Cheers

Retrieving duplicate models in collection

Hello,

I currently have the following relations;

Collective → hasMany → Artist → belongsToMany → Video

I currently have the following hasManyDeep relation setup for a collective to fetch their videos.

public function videos()
{
    return $this->hasManyDeep(Video::class, [Artist::class, 'artist_video']);
}

However, when I fetch the videos for a collective using $collective->videos I receive duplicate videos since an the same artists in a collective, can be assigned to the same video.

How can I ensure that only unique videos are fetched? Is there something wrong with my relation?

BelongToMany to belongsTo Relationship

Hello,

I'm having following models and table name:

Tags: table name (project_tags)

id
name

which is related to TechnicalDescription model with many to many relationship:

TechnicalDescription: table name(project_technical_detail)

id
project_id
description

Many to many relation holds on table (technical_detail_tag_relation):

id
technical_detail_id
tag_id

And finally I have Project Model table name(projects)

id
name

So I have Tags -> belongsToMany -> TechnicalDescription -> belongsTo -> Project

I tried doing:

public function projects()
{
    return $this->hasManyDeep(
        Project::class,
        ['technical_detail_tag_relation', TechnicalDescription::class],
        [null, null, 'id'],
        [null, null, 'project_id']
    );
}

But it throws error:

Column not found: 1054 Unknown column 'technical_detail_tag_relation.technical_description_id' in 'on clause'

Can you help me out with it, I tried replacing technical_description_id almost every null place where I defined this relationship, but no luck.

I'm trying to learn about your package, but little confused with this kind of relationships.

Thanks.

Problem with custom keys in ManyToMany -> ManyToMany -> ManyToMany

Hello!
At first, i'm really grateful to you because your package is really helpful, so thank you so much.

However, I'm a little confused when using custom keys in intermediate tables, that is because I have a relation App\User BelongsToMany App\User then the foreign keys couldn't be in the way as laravel require.
The structure of the tables are.

users :
id

responsible_user:
id - responsible_id - user_id

farms :
id

farm_user :
id - user_id - farm_id

the way that I need the relation is:
User -> BelongsToMany -> Users -> BelongsToMany -> Farms
I did something like:

public function farms(){
	return $this->hasManyDeep('App\Farm', ['responsible_user','App\User','farm_user']);
}

but I need to define the custom keys to responsible_user pivot table.

Thank you for your attention and sorry for disturbing you.

MorphedByMany and BelongsTo

Hi,

First of all, thank you for creating this extension. It's very useful and I think it should be added to Laravel.

My question: is it possible to combine MorphedByMany with BelongsTo?
Example: User -> morphedByMany -> Account -> belongsTo -> Partner

Currently I'm using this line to retrieve Partner models:
$user->accounts()->with('partner')->withTrashed()->get()->pluck('partner')->unique()

I'm hoping there is a better way to do this.

Thank you in advance!

Filter hasOneDeep

Is there a way to use the whereHas method properly with a hasOneDeep instance?

The pivot table:

order_id status_id step completed_at
1 1 10 2019-0706 16:00
1 2 20 null
1 3 30 null
1 7 40 null
1 5 50 null

I use the relationship like:

public function lastCompletedStatus()
    {
        return $this->hasOneDeep(Status::class, [OrderStatus::class])
            ->where('completed_at', '!=', null)
            ->latest('step');
    }

But if I filter through this relation:

$orders = $orders->whereHas('lastCompletedStatus', function($query){
            $query->where('description', 'order_checked');
        });

It gives me a collection with all orders completed the given status. But I want to filter for orders in this specific status. Is this even possible?

Composite keys join

I'm not sure, that is that package functionality, but it would be great, if you add ability to use composite keys on creating relations.

As example:

SELECT
    a.* 
FROM
    a_table AS a
INNER JOIN
    b_table AS b
ON 
    a.name = b.name
    AND
    a.surname = b.surname

installation issue

$ composer require staudenmeir/eloquent-has-many-deep
Using version ^1.6 for staudenmeir/eloquent-has-many-deep
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

Problem 1
- Installation request for staudenmeir/eloquent-has-many-deep ^1.6 -> satisfiable by staudenmeir/eloquent-has-many-deep[v1.6].
- Conclusion: remove laravel/framework v5.5.25
- Conclusion: don't install laravel/framework v5.5.25
- staudenmeir/eloquent-has-many-deep v1.6 requires illuminate/database ^5.5.29 -> satisfiable by illuminate/database[5.7.17, 5.7.18, 5.7.19, v5.5.33, v5.5.34, v5.5.35, v5.5.36, v5.5.37, v5.5.39, v5.5.40, v5.5.41, v5.5.43, v5.5.44, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.25, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9, v5.7.0, v5.7.1, v5.7.10, v5.7.11, v5.7.15, v5.7.2, v5.7.20, v5.7.21, v5.7.22, v5.7.3, v5.7.4, v5.7.5, v5.7.6, v5.7.7, v5.7.8, v5.7.9].
- don't install illuminate/database 5.7.17|don't install laravel/framework v5.5.25
- don't install illuminate/database 5.7.18|don't install laravel/framework v5.5.25
- don't install illuminate/database 5.7.19|don't install laravel/framework v5.5.25
- don't install illuminate/database v5.5.33|don't install laravel/framework v5.5.25
- don't install illuminate/database v5.5.34|don't install laravel/framework v5.5.25
- don't install illuminate/database v5.5.35|don't install laravel/framework v5.5.25
- don't install illuminate/database v5.5.36|don't install laravel/framework v5.5.25
- don't install illuminate/database v5.5.37|don't install laravel/framework v5.5.25

Table aliases in hasManyDeepFromRelation

I have 2 hasManyDeep relations, where i use table aliases and both work great. But if i try to create new relation from this two via hasManyDeepFromRelation, table aliases disappear from query and i get an error: SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias.

Is it possible to add table aliases to hasManyDeepFromRelation?

MorphToMany -> morphTo not working

Hi,

I have a relationship defined as:

User → morphToMany Team -> morphTo -> Campaign

I'm trying to get a list of all campaigns that a User belongs to. Looking at the documentation I think I should be able to do something like:

return $this->hasManyDeepFromRelations(
            $this->rolesTeams(),
            (new Team)->teamable()
        );

But that throws the following error:

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'teams' (SQL: select count(*) as aggregate from `teams` inner join `teams` on `teams`.`teamable_id` = `teams`.`team_id` inner join `role_user` on `role_user`.`team_id` = `teams`.`id` where `role_user`.`user_id` = 8 and `role_user`.`user_type` = App\User)

My User model looks something like this:

class User extends Authenticatable implements MustVerifyEmail
{
    ...

    /**
     * Many-to-Many relations with Team associated through the roles.
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     */
    public function rolesTeams()
    {
        return $this->morphToMany(
                App\Team::class,
                'user',
                'role_user',
                'user_id',
                'team_id'
            )
            ->withPivot('role_id');
    }

    /** Get the campaigns that the user is a member of
     *
     * @return Builder
     */
    public function campaigns()
    {
        return $this->hasManyDeepFromRelations(
            $this->rolesTeams(),
            (new Team)->teamable()
        );
    }

    ...

My Team model is like:

class Team extends LaratrustTeam
{
    ...

    /**
     * Get all of the owning teamable models.
     */
    public function teamable()
    {
        return $this->morphTo();
    }

    ...
}

Any idea what I'm doing wrong here?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.