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.
Related
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();
Hello I am learning relationship many to many I read the official documentation and use the conventions,
but I can't make the relation many to many I get the error that the property does not exist.
how can I solve that?
Migrations
Schema::create('role_user', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
$table->foreignId('role_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
User
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Roles
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Models:
User
public function roles(){
return $this->belongsToMany(role::class, 'role_user', 'user_id', 'role_id');
}
Role
public function users(){
return $this->belongsToMany(User::class, 'role_user','role_id','user_id');
}
query:
$v = User::get();
dd($v->roles);
$v = User::get(); returns a collection of users. If you get one user, for example, User::find(1) you will have access to the roles for this specific user.
Another option is
$users = User::with('roles')->get();
foreach ($users as $user) {
$userRoles = $user->roles;
}
I have multi level relation in my app
Category
|products
|product_items
|product_group
|product_attributes
Category Model
public function products(){
return $this->belongsToMany(Product::class);
}
Product Model
public function items()
{
return $this->hasMany(ProductItem2::class);
}
Item Model
public function attribute()
{
return $this->belongsToMany(AttributeValue::class,'product_groups','item_id','attribute_id')->withTimestamps();
}
Attribute value
public function attributeName(){
return $this->belongsTo(Attribute::class,'attribute_id');
}
all relations works fine but now I need filter my product by example 'colors'
so I tried
return $this->where('parent_id',0)->whereHas('childrenRecursive')->with('products.items.attribute.attributeName')->get();
put of course it return all categories with all product and product items etc
here is the migration files
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('image');
$table->string('cover')->nullable();
$table->string('url')->nullable();
$table->string('cover');
$table->text('url_cover');
$table->text('description')->nullabel();
$table->unsignedInteger('parent_id');
$table->boolean('elite')->default(0);
$table->timestamps();
});
Schema::create('category_product',function (Blueprint $table){
$table->integer('category_id');
$table->integer('product_id');
$table->primary(['product_id','category_id']);
});
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description');
$table->string('serial_number');
$table->float('price');
$table->integer('discount');
$table->enum('type',['pound','percentage']);
$table->timestamp('start')->nullable();
$table->timestamp('end')->nullable();
$table->string('image');
$table->unsignedInteger('shop_id');
$table->boolean('recommendation');
$table->boolean('published');
$table->integer('preparing_days')->unsigned();
$table->integer('visits')->defualt(0);
$table->unsignedInteger('priorty')->defualt(0);
$table->timestamps();
});
Schema::create('product_items', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('product_id');
$table->double('price');
$table->string('image');
$table->unsignedInteger('amount');
$table->timestamps();
});
Schema::create('product_groups', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('attribute_id');
$table->unsignedInteger('item_id');
$table->timestamps();
});
Schema::create('attribute_values', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('attribute_id');
$table->string('value');
$table->timestamps();
});
Schema::create('attributes', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
all i need to return the attribute 'color' values like ['red,blue,black'] with each category
seems complicated and need 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 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;
}