Finding related model in laravel based on parent - php

I want to search for like which is made by a given user on a given post.
I have one Post model as: Post
class Post extends \Eloquent
{
protected $fillable = [];
public function likes()
{
return $this->morphMany('Like', 'likeable');
}
}
and one Like model as:
class Like extends \Eloquent
{
protected $fillable = [];
/**
* #return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function likeable()
{
return $this->morphTo();
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
return $this->belongsTo('User', 'owner_id');
}
}
and default User model provided in laravel.
now I have queried Post model to find one post using post_id like
$post=Post::find(10);
and User model like
$user=User::find(1);
now I want to find Like made by this User(1) on Post(10) Is there any function available in laravel for this.
I know that I can directly query Like using raw where function as
\Like::whereLikeableId('10')->whereLikeableType('Post')->whereUserId('1')->get();
but this looks ugly and I want to know laravel way of doing it.

All you need is:
$like = $post->likes()->where('user_id', 1)->first();

Related

To carry out CRUD operations for multiple tables in a single view

I'm on Laravel 8 with Livewire, currently have 3 models, Category, SubCategory and MenuItem for 3 tables. All the above models have separate livewire controllers and have the code for the CRUD operations respectively. I have separate views and routes to edit the above tables and they all have a eloquent relationship between each other. Now what I need to do here to is, I need to display all the three tables in a single view to carry out the CRUD operations.
I tried to achieve this by using the sub-view function, to pass the view and make the variables available to the specific view, but it didn't work out and I think it isn't the way to do it, was just trying to figure a workaround. I'm mentioning my models down below for referencing. Please help me with this. Thanks a lot for your time!
App\Models\Category
class Category extends Model
{
use HasFactory;
protected $table = "categories";
protected $fillable = ['sub_category_name'];
public function SubCategories() {
return $this->hasMany(SubCategory::class, 'category_id');
}
public function MenuItems() {
return $this->hasManyThrough(
'MenuItem::class',
'SubCategory::class',
'sub_category_id',
'category_id'
);
}
}
App\Models\SubCategory
class SubCategory extends Model
{
use HasFactory;
protected $table = "sub_categories";
protected $fillable = ['category_id', 'sub_category_name'];
public function Categories() {
return $this->belongsTo(Category::class, 'category_id');
}
public function MenuItems() {
return $this->hasMany(MenuItem::class, 'sub_category_id');
}
}
App\Models\MenuItem
class MenuItem extends Model
{
use HasFactory;
protected $table = "menu_items";
protected $fillable = ['sub_category_id', 'item_name', 'item_description'];
public function SubCategories() {
return $this->belongsTo(SubCategory::class, 'sub_category_id');
}
}
This is what I tried to achieve the said result. As I needed to include the view with the sub category table to the menu items table view. I made the variables available to that specific view.
Resources\Views\Livewire\Menu-Item
<div>
#include('livewire.sub-category')
</div>
App\Providers\AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
use App\Models\SubCategory;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
View::composer('livewire.menu-item', function ($view) {
$view::with('sub_category_name', SubCategory::orderBy('sub_category_name')->get());
});
}
}
I managed to solve the above problem, using livewire's component feature. Created 3 separate component for 3 separate tables, and finally used all the three components in the master-menu.blade.php file. Working with livewire and laravel is a treat.

Exclude records which does not meet condition in model in laravel

I have multiple tables and their models which they have relation with each other named : "users","posts","tags","comments".
I want to exclude data of deactive users from all of this models, and whenever any of this models has been called do not return users which are deactive
I don't want to exclude those "users" using eloquent or query builder in their controllers, I need to do this in model so it apply to all places which are using said models.
posts , comments and tags relation to users is :
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
I need something like this in related model:
$instance = $this->belongsTo('App\Models\User', 'user_id');
$instance->whereIsDeactive(0);//return active users only
return $instance;
And something like this in user model:
return $this->whereIsDeactive(0);
Is it possible and is there any way to accomplish this?
Thanks to #Adam I solved the issue using global scopes.
This is IsDeactive global scope :
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class IsDeactiveScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('is_deactive', 0);
}
}
And this is how to call it in user model:
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new IsDeactiveScope());
}
I hope this solution help others.

How to use one model for multiple tables in laravel 5.6

I am looking for solutions, but can't really understand. I'm new in Laravel and I want a simple instruction on how to use one model for multiple tables like CodeIgniter as follows:
Controller myController:
public function shipBuilding()
{
$data = $this->input->post();
$response = $this->MyModel->shipbuildingSave($data);
}
public function contact()
{
$data = $this->input->post();
$response = $this->MyModel->contactSave($data);
}
Model MyModel:
public function shipbuildingSave($data){
$this->db->insert('tbl_shipbuilding', $data);
return $this->db->insert_id();
}
public function contactSave($data){
$this->db->insert('tbl_contact', $data);
return $this->db->insert_id();
}
This is not how models work in Laravel. each model should be a representation of one single table.
You could, however, change the table name on booting the model up:
class Flight extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'example';
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
// Set the $this->table depending on some logic.
}
}
But again, this is probably not recommended for your case.

Laravel relationship 2 layers

I have my database (=model) structure like that:
game:
lot (typeof Lot)
places (array type of Place)
place_id // just a number of a lot in some game
user_id
What should I do to call in everywhere like this:
User::find(1)->games() // returns Game collection where user has places
?
Models are:
class Place extends Model
{
protected $fillable = ['place_id', 'user_id', 'game_id'];
public function user() {
return $this->belongsTo(User::class);
}
public function game() {
return $this->belongsTo(Game::class);
}
}
User:
class User extends Model implements AuthenticatableContract,
AuthorizableContract,
CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'email', 'steam_id', 'avatar'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['remember_token'];
/**
* Get all of the tasks for the user.
*/
public function items()
{
return $this->hasMany(SteamItem::class);
}
public function places() {
return $this->hasMany(Place::class);
}
}
The Game:
class Game extends Model
{
protected $fillable = ['lot_id'];
public function lot() {
return $this->belongsTo(Lot::class);
}
public function places() {
return $this->hasMany(Place::class);
}
}
Now I use this code in my User class:
public function games() {
return Game::with(['places' => function ($query) {
$query->where('user_id', $this->id);
}]);;
}
It doesn't work, because I need to make it as a relationship method, but with method returns a query builder.
In the finals I must call $user->games and it should return me all the games user linked to through place.
Okay. I think I understand now.
User has many Place. Place belongs to User.
Place belongs to Game. Game has many Place.
You can try this:
$user = User::with('places.game.lot')->find(1);
This will fetch the User and eager load all the relationships. Because Place belongsTo a Game, which in turn belongs to Lot, you can then do this:
#foreach ($user->places as $place)
<img src="{{$place->game->lot->imageUrl}}" />
#endforeach
Also, place is actually a pivot table, and you can take advantage of Eloquent's many-to-many relationship, which I would recommend reading about.

Laravel after composer update model method call undefined

I am working on a project with Laravel 4.2 and I created some models and controllers and called model function from controller, the problem is after composer update command it displays this error: Call to undefined method Department::getAllParent() but before composer update it works fine. You think what is the problem with this issue? thanks in advance
Model code:
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
$table = DB::table('department');
$object = $table->get();
return $object;
}
public static function getAllParent()
{
$table = DB::table('department');
$table->where('parent',0);
$object = $table->get();
return $object;
}
}
And Controller code:
class DepartmentController extends BaseController
{
/*
Getting all records from department
#param: none
#Accessiblity: public
#return: Object
*/
public function getAllDepartment()
{
//get data from model
$deps = Department::getAllParent();
$depAll = Department::getAll();
//load view for users list
return View::make("department.dep_list")->with('deps',$deps)->with('all',$depAll);
}
}
Don't think this is related to your issues but this might be a better way to handle these queries. you are using Eloquent and setting the table parameter. why not use Eloquent's build in power?
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
return Department::get();
}
public static function getAllParent()
{
return Department::where('parent', 0)->get();
}
}
I think you might also be able to use $this->get(); but I can't test right now.

Categories