staudenmeir / laravel-merged-relations Goto Github PK
View Code? Open in Web Editor NEWMerged Laravel Eloquent relationships
License: MIT License
Merged Laravel Eloquent relationships
License: MIT License
Hi !
I'm using both of your (amazing) packages : staudenmeir/eloquent-has-many-deep and staudenmeir/laravel-merged-relations.
And I have an issue when I want to use them together. Let me explain that.
I have a User with a deep relationship, with two morphedToMany :
I need to get both of this contents (Rss and Twitter) in the same call. So, here, I use the laravel-merged-relations, with a view. Here is the code of my model :
class User extends Authenticatable
{
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function rss_contents()
{
return $this->hasManyDeep(
RssContent::class,
[ 'flux_user', Flux::class, 'flux_contents'],
[ null, null, 'flux_id', 'id' ],
[ null, null, 'id', ['flux_content_type', 'flux_content_id']]
)->withIntermediate(Flux::class);
}
public function twitter_contents()
{
return $this->hasManyDeep(
TwitterContent::class,
[ 'flux_user', Flux::class, 'flux_contents'],
[ null, null, 'flux_id', 'id' ],
[ null, null, 'id', ['flux_content_type', 'flux_content_id']]
)->withIntermediate(Flux::class);
}
use \Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships;
public function all_contents()
{
return $this->mergedRelation('all_user_contents');
}
My migration looks like this:
class CreateUserContentsMergeView extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::createMergeView('all_user_contents', [(new User)->rss_contents(), (new User)->twitter_contents()
]);
}
}
All of this is working very well.
BUT... when I call the all_contents
method, I can't access the intermediate Flux::class
. I think this is normal because it's not in my view.. but I don't know how to have it.
Do you you have an idea how?
Thanks a lot for your help!
After dropping my dev database and restoring the live database containing a view created by this plugin, i get the following error:
SQLSTATE[28000]: Invalid authorization specification: 1045 Access denied for user 'db'@'%' (using password: YES)
The other tables working like normal.
If I delete the view and re-run the migration it works again.
Is this a known problem?
Hello, i can't make the mergedRelationWithModel work with my structure. Can you take a look of what i'm doing wrong?
Schema::createOrReplaceMergeView('participants', [(new Blog)->user(), (new Blog)->creator(), (new Blog)->commenters()]);
CREATE
ALGORITHM = UNDEFINED
DEFINER = `username`@`ip`
SQL SECURITY DEFINER
VIEW `database`.`participants` AS
SELECT
`database`.`users`.`username` AS `username`,
`database`.`users`.`id` AS `laravel_foreign_key`,
'App\Models\User' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
FROM
`database`.`users`
WHERE
(`database`.`users`.`deleted_at` IS NULL)
UNION ALL SELECT
`database`.`users`.`username` AS `username`,
`database`.`users`.`id` AS `laravel_foreign_key`,
'App\Models\User' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
FROM
`database`.`users`
WHERE
(`database`.`users`.`deleted_at` IS NULL)
UNION ALL SELECT DISTINCT
`database`.`users`.`username` AS `username`,
`database`.`blog_comments`.`blog_id` AS `laravel_foreign_key`,
'App\Models\User' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
FROM
(`database`.`users`
JOIN `database`.`blog_comments` ON ((`database`.`users`.`id` = `database`.`blog_comments`.`user_id`)))
WHERE
(`database`.`users`.`deleted_at` IS NULL)
class Blog extends Model
{
use \Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships;
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function commenters(): BelongsToMany
{
return $this->belongsToMany(User::class, BlogComment::class)->distinct();
}
/**
* Get participants in the blog.
*
* @todo: We should get the users who comments + creator + user
*
* @return MergedRelation
*/
public function participants(): MergedRelation
{
return $this->mergedRelationWithModel(User::class, 'participants');
}
}
$blog->participants returns the user + creator + commenters
$blog->participants is just returning the commenters
f3a002e2-5ecb-4205-aefd-cfb2ecc0112e is the primary key for the Blog Model
select * from `participants` where `participants`.`laravel_foreign_key` = 'f3a002e2-5ecb-4205-aefd-cfb2ecc0112e' and `participants`.`laravel_foreign_key` is not null
If you need more information, please feel free to tell
Thank you,
Mário
The User Model has a merged relationship called connections:
public function connections(): MergedRelation
{
return $this->mergedRelationWithModel(User::class, 'connections_view');
}
which is connected with the following connections_view:
public function up()
{
Schema::createMergeView(
'connections_view',
[(new User())->acceptedConnectionsFrom(), (new User())->acceptedConnectionsTo()]
);
}
It merges together the connections between two users, where a user can either be the sender or the receiver of a connection request. That is why we need two relationships for it. If you do not understand what I mean, check out https://blog.codecourse.com/setting-up-laravel-friendship-relations
In my seeder or in my tests I would now like to create records for the mergedRelation like so:
public function test_try_to_seed_user_with_friends()
{
$user = User::factory()
->hasConnections(10)
->create();
}
Unfortunately this throws the following error:
SQLSTATE[HY000]: General error: 1 table users has no column named laravel_foreign_key (SQL: insert into "users" ("name", "email", "email_verified_at", "password", "remember_token", "userable_id", "userable_type", "laravel_foreign_key", "updated_at", "created_at") values (Kareem Jast I, [email protected], 2022-11-04 14:22:07, $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi, CqbC0RCmTK, 2, App\Models\Site, 1, 2022-11-04 14:22:07, 2022-11-04 14:22:07))
Is it possible to fix it?
Hey,
I am using this package with enforcing a morph map like this
Relation::enforceMorphMap([
'dropbox' => Dropbox::class,
'ftp' => Ftp::class,
's3' => S3::class,
'user' => User::class,
]);
In the created view I see the column laravel_model
with the full path/namespace.
Shouldn't this be decoupled when using a morph map?
I have error Error: Call to undefined method Staudenmeir\LaravelMergedRelations\Facades\Schema::createMergeView() in file /public_html/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 353.
Hi @staudenmeir.
I stumbled onto your package and I have to say it's really great work.
Even if it's not documented I tried a $model->all_related->save($relatedModelInstance)
but it doesn't work.
I guess this is not supported yet but it may be my fault... any clue?
Thanks for taking the time.
Hello, I am already using staudenmeir/eloquent-has-many-deep relationships and wanted to use this package as well. However, I noticed these seem to be incompatible, am I correct?
staudenmeir/laravel-merged-relations: v1.5.2
staudenmeir/eloquent-has-many-deep: v1.17.1
Laravel: 9.46
When I'm trying to create a merged view with a relation which is defined using hasManyDeepFromRelations(), it uses the wrong 'base model'
In model "A":
public function c()
{
return $this->hasManyDeepFromRelations($this->b(), (new B)->c());
}
Creating schema:
Schema::createMergeViewWithoutDuplicates(
'all_cs',
[(new A)->c()]
);
Results in:
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `all_cs` AS
select
`cs`.`id` AS `id`,
`cs`.`name` AS `name`,
`cs`.`created_at` AS `created_at`,
`cs`.`updated_at` AS `updated_at`,
`bs`.`id` AS `laravel_foreign_key`,
'App\\Models\\C' AS `laravel_model`,
'' AS `laravel_placeholders`,
'' AS `laravel_with`
from
...
I was expecting it would do
`as`.`id` AS `laravel_foreign_key`
instead of
`bs`.`id` AS `laravel_foreign_key`
It does create the correct query to query using a B model. It seems to skip the first level (from what I would expect, at least).
Hello,
So am getting this error when I do php artisan migrate, which says:
**Illuminate\Database\QueryException
SQLSTATE[42883]: Undefined function: 7 ERROR: operator does not exist: boolean = integer at character 499**
Am just doing how the view example shows, here's my code:
use Staudenmeir\LaravelMergedRelations\Facades\Schema;
public function up()
{
Schema::createMergeView(
'friends_view',
[( new User())->acceptedFriendsOf(), ( new User())->acceptedFriendsOfMine()]
);
}
Is it possible to add pivot columns to the generated view?
I have a users
table and a pivot table for friends which contains the user_id
, friend_id
and accepted_at
.
Is it possible to get the accepted_at
in the generated view?
I was so happy to find this package today! Thank you for creating it!!
It is mostly working fine for me, but I noticed that when I add a ->select('column')
query modifier to the view query, I get some warnings and errors:
<warning>PHP Warning: Undefined property: stdClass::$laravel_model in vendor/staudenmeir/laravel-merged-relations/src/Eloquent/Builder.php on line 23</warning>
<warning>PHP Warning: Undefined property: stdClass::$laravel_placeholders in vendor/staudenmeir/laravel-merged-relations/src/Eloquent/Builder.php on line 27</warning>
PHP Error: Class name must be a valid object or a string in vendor/staudenmeir/laravel-merged-relations/src/Eloquent/Builder.php on line 35
Here's the query I'm running:
$source->newsItems()->select('external_id')->get();
and the SQL it is generating:
select `external_id` from `source_all_newsitems` where `source_all_newsitems`.`laravel_foreign_key` = ? and `source_all_newsitems`.`laravel_foreign_key` is not null"
Here's the Source model setup:
public function feedNewsItems()
{
return $this->hasManyThrough(NewsItem::class, Feed::class);
}
public function directNewsItems()
{
return $this->hasMany(NewsItem::class);
}
public function newsItems()
{
return $this->mergedRelationWithModel(NewsItem::class, 'source_all_newsitems');
}
and the migration:
Schema::createMergeView('source_all_newsitems', [
(new \App\Models\Source())->feedNewsItems(),
(new \App\Models\Source())->directNewsItems()
]);
Note that if I run the query without the select()
modifier, it works fine. I see the limitation disclaimer about not being able to specify columns in the view creation, but it looks like it should be possible to specify columns in the query of the view, unless I'm missing something.
After upgrading this package to the new release and running my test suite which uses sqlite with an in memory database I'm getting an error with it not finding Call to undefined method Staudenmeir\LaravelMigrationViews\Schema\Builders\SQLiteBuilder::createOrReplaceMergeView()
however if I look inside the vendor folder and find the SQLiteBuilder file I do find the method inside of the CreatesMergeViews trait.
I did not get this error when I ran my tests pior to the upgrading this package and upgrading Laravel to 9.
<?php
use App\Models\Group;
use Illuminate\Database\Migrations\Migration;
use Staudenmeir\LaravelMergedRelations\Facades\Schema;
class CreateAllGroupMembersView extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::createOrReplaceMergeView(
'all_group_members',
[(new Group)->teachers(), (new Group)->students()]
);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropView('all_group_members');
}
}
I'm getting a phpunit test suite set up for a project where I'm using this package, and immediately started encountering "Base table or view already exists" errors for the created view on n>=2 runs of the tests. My best guess is that something about the existence of a view is not expected in the way Laravel handles creating and cleaning up the test database structure. But it's also possible/likely I've configured something incorrectly.
Do you have any guidance on how to address this? For now I'm adding a Schema::dropViewIfExists()
call to the migration's up()
method as a workaround. Thank you.
DB: PostgreSQL 13.6
Laravel: 9.38.0
When trying to create a merged view without duplicates on a table with json columns an error is thrown. If duplicates are allowed it works fine.
Schema::createMergeViewWithoutDuplicates(
'business_all_gatherings',
[(new \App\Models\Business())->productGatherings(), (new \App\Models\Business())->activityGatherings()]
);
Output:
SQLSTATE[42883]: Undefined function: 7 ERROR: could not identify an equality operator for type json...
I get an error when migrating
error:
SQLSTATE[42S21]: Column already exists: 1060 Duplicate column name
migration:
Schema::createMergeViewWithoutDuplicates(
'movie_recommended_view',
[(new Movie())->recommended(), (new Movie)->recommendedFor()]
);
relationships:
public function recommended(): BelongsToMany
{
return $this->belongsToMany(static::class, 'movie_recommended', 'movie_id', 'recommended_id' ,'tmdb_id' , 'tmdb_id');
}
public function recommendedFor(): BelongsToMany
{
return $this->belongsToMany(static::class, 'movie_recommended', 'recommended_id', 'movie_id' ,'tmdb_id' , 'tmdb_id');
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.