I have 2 tables: 'users' and 'nests' and 1 pivot table: 'nest_user'. In my pivot table I have email addresses I want to filter against so I can grab all the nests which have the associated email addreses. Here is my scehma:
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('username');
$table->text('bio');
$table->string('picture');
$table->string('email');
$table->string('password');
$table->integer('visits');
$table->integer('nest_id');
$table->timestamps();
});
}
public function up()
{
Schema::create('nests', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->string('info');
$table->integer('note_id');
$table->integer('website_id');
$table->integer('image_id');
$table->integer('video_id');
$table->integer('location_id');
$table->integer('user_id');
$table->integer('share_id');
$table->string('inviteAuth');
$table->string('tid');
$table->timestamps();
});
}
public function up()
{
Schema::create('nest_user', function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id');
$table->integer('nest_id');
$table->string('inviteEmail');
$table->timestamps();
});
}
I can do this no problem based on the User ID like this:
Route::get('/t1', function () {
$nest = User::find(2)->nest()->where('inviteEmail', '=', 'martinelli#gmail.com')->get();
foreach( $nest as $nest)
echo $nest->name, ': ', $nest->pivot->inviteEmail, "</br>";
});
I can get the nest and name and the email in the pivot - awesome...However, I want to find ALL the 'nests' which have the associated email which is NOT tied to a user ID. This is getting me closer but it is still not working:
Route::get('/t4', function () {
$users = User::all();
foreach($users as $users)
{
$nests = $users->with(array('nest' => function($query) {
$query->where('inviteEmail', '=', 'martinelli#gmail.com');
}))->get();
foreach($nests->nest as $nest)
{
echo $nest->name,"<br />";
}
}
});
I am getting this error:
Undefined property: Illuminate\Database\Eloquent\Collection::$nest
I'm not sure I fully understand your question, but your last code block doesn't make sense. You'll want to do the with while fetching the users. Also, the error you're getting makes sense, because the $nests (Collection) doesn't have a $nest property.
Again, I'm not sure this is what you're after, but give this a try:
Route::get('/t4', function () {
// Get all users and their nests where nests are filtered by inviteEmail
$users = User::with(array('nest' => function($query) {
$query->where('inviteEmail', '=', 'martinelli#gmail.com');
}))->get();
// Loop through all users
foreach($users as $user)
{
// I'm asuming you defined the relation as nests() in your User model.
foreach($user->nests as $nest)
{
echo $nest->name . "<br />";
}
}
});
Related
I have a set that has a list of group and each group has a list of attributes like this
//sets
Schema::create('sets', function (Blueprint $table) {
$table->id();
$table->string('name');
});
//groups
Schema::create('groups', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('set_id')->constrained('sets')->onDelete('cascade');
});
//attributes
Schema::create('attributes', function (Blueprint $table) {
$table->id();
$table->string('name');
});
//set_group_attributes
Schema::create('set_group_attributes', function (Blueprint $table) {
$table->foreignId('set_id')->constrained('sets')->onDelete('cascade');
$table->foreignId('group_id')->constrained('groups')->onDelete('cascade');
$table->foreignId('attribute_id')->constrained('attributes')->onDelete('cascade');
$table->integer('position');
$table->unique(['set_id', 'attribute_id']);
});
I need to save the set with groups and attributes, this is my code :
$set = Set::create(['name' => $request->name]); ---> save the set
$set->groups()->createMany($request->groups); ---> save the group
//set model
public function groups(): HasMany
{
return $this->hasMany(Group::class, 'set_id','id');
}
My question is how to save the attributes with laravel eloquent?
Here we can use attach like in Docs with belongsToMany
//group model
/**
* #return BelongsToMany
*/
public function attributes(): BelongsToMany
{
return $this->belongsToMany(Attribute::class, 'set_group_attributes', 'group_id', 'attribute_id')->withPivot('position');
}
// save attributes of groups
foreach ($attributes as $attribute) {
$group->attributes()->attach($attribute['id'], ['set_id' => $model->id, 'position' => $attribute['position']]);
}
I use Laravel 8. I want to get the user proccess course, but I get all users proccess.
In User.php
public function courses()
{
return $this->belongsToMany(Course::class);
}
Course.php
public function progresses()
{
return $this->hasMany(Progress::class);
}
Progress.php is empty.
Course table
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->string('title');
...
$table->timestamps();
});
Progress table
Schema::create('progress', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->integer('percent');
$table->timestamps();
});
CourseController
public function index()
{
$userCourses = User::where('id', 1)->with('courses.progresses')->first();
return $userCourses;
}
And this return:
But I only wanted proccess where user_id = 1.
With() method can constrain eager loads with a specific array annotation. This is also described in the documentation.
$userId = 1;
$userCourses = User::where('id', $userId)
->with(
[
'courses.progresses' => function ($query) use ($userId) {
$query->where('user_id', $userId)
},
]
)->first();
I have two models Post and Category
// migration post
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('body');
$table->string('image');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
$table->timestamps();
});
}
// migration category
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
How can I display only the last post from each category in home page?
Hiren was close, but you need to go from the category since your post is owned by the category
$category->posts()->latest()->first();
Alternatively you could work backwards:
$post = Post::latest()->whereHas('category', function($q) use($category_id) {
return $q->where('id', $category_id);
})->first();
For this to work you'll need to define your model relationships:
Category Model needs this function:
public function posts()
{
return $this->hasMany(App\Post::class);
}
Post Model needs this function:
public function category()
{
return $this->belongsTo(App\Category::class);
}
To respond to Alexey Mezenin, we can just pass a callback to with() to define which posts we want to pull in for each category, performing the correct eager load.
Category::with(['posts' => function($q) {
return $q->latest()->first();
})->get();
An Eloquent solution for loading categories with latest post is to create an additional hasOne() relationship in the Category model:
public function latestPost()
{
return $this->hasOne(Post::class)->latest();
}
And then use eager loading:
Category::with('latestPost')->get();
This will generate just 2 queries to DB.
public function up()
{
Schema::create('news', function (Blueprint $table) {
$table->increments('id');
$table->string('slug')->unique();
$table->unsignedInteger('author_id');
$table->unsignedInteger('category_id');
$table->string('subject');
$table->text('short');
$table->text('content');
$table->integer('view')->default(0);
$table->integer('status')->default(0);
$table->string('image');
$table->timestamps();
$table->foreign('author_id')
->references('id')->on('users')
->onDelete('cascade');
// $table->foreign('category_id')
// ->references('id')->on('categories')
// ->onDelete('cascade');
});
// Schema::enableForeignKeyConstraints();
}
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
});
}
in contoller:
$latestpostlist = News::whereIn('created_at',function($query){
$query->select(DB::raw('max(created_at)'))
->from('news')
->groupBy('category_id');
})->get();
in your case news will be post. this query worked for me
I have the following tables:
Uses table:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('firstname');
$table->string('surename');
$table->string('address')->nullable();
$table->string('city')->nullable();
$table->string('country')->nullable();
$table->string('postcode')->nullable();
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->string('facebook_id')->nullable();
$table->string('linkedin_id')->nullable();
$table->string('twitter_id')->nullable();
$table->timestamps();
});
Setting table:
Schema::create('settings', function (Blueprint $table) {
$table->increments('id');
$table->string('value');
$table->timestamps();
});
Setting_user (Pivot table):
Schema::create('setting_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('setting_id')->unsigned();
$table->foreign('setting_id')->references('id')->on('settings');
$table->timestamps();
});
Categories table:
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Setting_category (pivot table):
Schema::create('setting_category', function (Blueprint $table) {
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories');
$table->integer('setting_id')->unsigned();
$table->foreign('setting_id')->references('id')->on('settings');
$table->timestamps();
});
In my User model this I have a belongsToMany relationship:
public function settings()
{
return $this->belongsToMany(Setting::class, 'setting_user', 'user_id','setting_id')->with('category');
}
And in my setting model:
protected $table = 'settings';
public function category()
{
return $this->hasMany(Categories::class,'id');
}
When I access it like so:
public function settings()
{
$user = User::find(1);
return $user->settings()->with('category')->first();
}
This is the result I get:
{"id":1,"value":"87658675.jpg","created_at":"2017-07-04 00:00:00","updated_at":null,"pivot":{"user_id":1,"setting_id":1},"category":[{"id":1,"name":"avatar","created_at":"2017-07-06 00:00:00","updated_at":null}]}
How can I get only the settings with category->id == 1 ?
Many thanks
If you want to get only settings for specified user and specified category, use whereHas():
public function settings()
{
$categoryId = 1;
$userId = 1;
return Settings::whereHas('categories', function ($q) use ($categoryId) {
$q->where('id', $categoryId);
})
->whereHas('users', function ($q) use ($userId) {
$q->where('id', $userId);
})
->get();
}
To make this work, fix your relationships. Looks like all relations should be belongsToMany() and not hasMany()
I have changed the relationships in my Setting model to:
public function users()
{
return $this->belongsToMany(User::class, 'setting_user','setting_id', 'user_id');
}
public function categories()
{
return $this->belongsToMany(Categories::class,'setting_category','category_id','setting_id');
}
I still have the belongsToMany relationship in my User model :
public function settings()
{
return $this->belongsToMany(Setting::class, 'setting_user', 'user_id','setting_id');
}
And I have created another method to extract the Avatar which has id of "1" like so :
/**
* Get user's avatar.
*/
public function getAvatarAttribute() {
$categoryId = 1;
$userId = Auth::user()->id;
$avatar = $this->settings()->whereHas('categories', function ($q) use ($categoryId) {
$q->where('id', $categoryId);
})->whereHas('users', function ($q) use ($userId) {
$q->where('id', $userId);
})->first();
if(!$avatar)
{
return "default-avatar.jpg";
}
return $avatar->value;
}
I have a polymorphic table called 'Item':
Schema::create('items', function(Blueprint $table) {
$table->increments('id');
$table->text('itemable_type')->nullable();
$table->string('itemable_id')->nullable();
$table->integer('subject_id')->nullable();
$table->integer('user_id')->nullable();
$table->integer('new')->nullable();
$table->integer('school')->nullable();
$table->string('private')->nullable();
$table->text('snippet')->nullable();
$table->string('elementSubject')->nullable();
$table->integer('follow_id')->nullable();
$table->timestamps();
});
Also have a table called 'Follow':
Schema::create('follows', function(Blueprint $table) {
$table->increments('id');
$table->integer('subject_id')->nullable();
$table->integer('teacher_id')->nullable();
$table->integer('user_id')->nullable();
$table->integer('effort')->nullable();
$table->timestamps();
});
Also have a table called 'Subject':
Schema::create('subjects', function(Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->integer('studentID')->nullable();
$table->integer('teacherID')->nullable();
$table->integer('schoolID')->nullable();
$table->integer('memberID')->nullable();
$table->string('private')->nullable();
$table->integer('creator')->nullable();
$table->softDeletes();
$table->timestamps();
});
They are linked together like this in my model:
class Follow extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function subjects()
{
return $this->hasMany('Subject');
}
I like to filter the 'Item' list based on the 'Subjects' the 'User' is following. What would my Eloquent look like?
I have this filtering on the 'School' but I want to filter it on what the user is 'Following'
$follows = Follow::where('user_id', Auth::user()->id)->get();
$items = Item::where('school', Auth::user()->school)
->where('private', 'false')
->orderBy('created_at', 'DESC')
->get();