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;
}
Related
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 need to create a query that get all tags from an array of posts.in a many-to-many polymorphic relationship between tags and posts
TAG MODEL
class Tag extends Model
{
use HasFactory;
protected $guarded = ['id'];
//
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
}
POST MODEL
class Post extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
TAG MIGRATION
public function up()
{
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
TAGGABLE MIGRATION
public function up()
{
Schema::create('taggables', function (Blueprint $table) {
$table->id();
$table->bigInteger('tag_id')->unsigned();
$table->morphs('taggable');
$table->foreign('tag_id')->references('id')->on('tags')
->onDelete('cascade')
->onUpdate('cascade');
});
}
POST MIGRATION
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
// 1 borrador, 2 revision, 3 publicado, 4 caducado
$table->enum('status', [Post::BORRADOR, Post::REVISION, Post::PUBLICADO, Post::CADUCADO]);
// Para diferenciar entre publicaciones del Sistema (Admin = 1) o de usuarios normales (USERS = 2)
$table->enum('type', [Post::ADMIN, Post::USERS]);
$table->boolean('atemporal');
$table->string('slug')->unique();
$table->unsignedBigInteger('user_id')->nullable();
$table->unsignedBigInteger('survey_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
$table->foreign('survey_id')->references('id')->on('surveys');
$table->timestamps();
});
CATEGORIES MIGRATION
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedBigInteger('parent_id')->nullable();
$table->string('slug');
$table->foreign('parent_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
PIVOT TABLE CATEGORY_POST
Schema::create('category_post', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id');
$table->unsignedBigInteger('post_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->timestamps();
});
RELATIONSHIP POST
public function categories()
{
return $this->belongsToMany(Category::class);
}
RELATIONSHIP CATEGORY
public function posts()
{
return $this->belongsToMany(Post::class);
}
I have tried this but I can't get it to work
$posts = Post::whereHas('categories', function($query) {
$query->whereIn('category_id', [$this->categoriaTags]);
})->get();
// Here I get the list of posts from which I want to get their tags, this is OK.
//But then I can't get the right query to get the tags.
$tags = Tag::whereHasMorph('posts', function($query) use($posts){
$query->where('tag_id', $posts);
})->get();
Any suggestions? Thank you
You are close, but you are querying the wrong column, and using the wrong builder method. You want:
$tags = Tag::whereHasMorph('posts', function ($query) use ($posts) {
$query->whereIn('id', $posts->pluck('id'));
})->get();
I have an admin which can create several recordings in the form Members.
In the table Members, there are 2 fields user_id and team_id.
Here is an example below:
Now, my problem is that I want to log for example with the user jeremy#gmail.com.
I have to see only my informations.
Here is an example:
DataBase:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('team_id')->unsigned()->nullable();
$table->foreign('team_id')->references('id')->on('teams');
$table->timestamps();
});
}
public function up()
{
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
I'm trying to understand the syntax to do?
public function index(Request $request)
{
$user = $request->user();
$members = Member::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
$query->where('id???', $user->email); ????
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->where('name??', 'like', '%' . $request->input('search') . '%');
})->with('team:id,name')
->paginate(5);
return view('admin.members.index', compact('members'))
->with('display_search', $user->hasRole('admin'));
}
Thank you in advance for your help.
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 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();