Pivot table not working as expected - many-to-many

I am trying to use many-to-many relationships between my posts and categories models. So far I created posts , categories and post_categories tables.
In my models, I have my relationships
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category', 'post_categories','category_id');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post','post_categories');
}
}
and in my controllers when I try to create a Post instance by :
$post = new Post;
$post->title = e(Input::get('title'));
$post->slug = e(Str::slug(Input::get('title')));
$post->content = e(Input::get('content'));
// Was the blog post created?
if($post->save())
{
$id = (int) Input::get('category_id');
$category = Category::find($id);
$post->categories()->attach($category);
// Redirect to the new blog post page
return Redirect::to("admin/blogs/$post->id/edit")->with('success', Lang::get('admin/blogs/message.create.success'));
}
After submitting form , I can see blog post is created normally. When I check the db , Category_id is inserted inside post_categories table but post_id is always 0.
Can anyone help me to fix this?

$post->categories()->attach($category->id);

I was using relationships in a wrong way. The table had to know the second table column name.
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category', 'post_categories','category_id','post_id');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post','post_categories',,'post_id','category_id');
}
}
The best usage will be changing the table name and make it category_post table. This way all I have to do is
class Post extends Eloquent {
public function categories()
{
return $this->belongsToMany('Category');
}
}
class Category extends Eloquent {
public function posts()
{
return $this->belongsToMany('Post');
}
}

Related

Laravel eloquent query with multiple child relations

I am working on a query but can't find the solution to this one.
The structure i have at the moment is:
A project has 1 machine, but a machine can belong to multiple projects.
A machine can have multiple issues.
Now i want to get all projects with the issues created after the project got created.
The query that i have at the moment, but doesn't work:
$allProjects = Project::with(['machine',
'machine.issues' => function ($query) {
$query->where('created_at', '>=', 'project.created_at');
}
])
->orderBy('id')
->get();
I am not getting the issues at all by using this query, when i switch the operator to: < then i get all the issues even the ones after project.created_at
You can have a pivot do most of the work for you. I tried reproducing your problem statement as below.
<?php
class Project extends Model
{
use HasFactory;
public function machine()
{
return $this->hasOneThrough(Machine::class, MachineProject::class, 'machine_id', 'id', 'id', 'project_id');
}
public function issues()
{
return $this->hasManyThrough(Issue::class, Machine::class, 'id', 'machine_id')->whereDate('issues.created_at', '<=', $this->created_at);
}
}
class Machine extends Model
{
use HasFactory;
public $with = ['issues'];
public function projects()
{
return $this->belongsToMany(Project::class);
}
public function issues()
{
return $this->hasMany(Issue::class);
}
}
class Issue extends Model
{
use HasFactory;
public function machine()
{
return $this->belongsTo(Machine::class);
}
}
class MachineProject extends Pivot
{
//
}
To retrieve the Project with issues, you just do
$allProjects = Project::with(['machine' => function ($machine) {
$machine->with('issues');
}])->get();

How to get data from table reference in Laravel

I have table relation like this:
Is it possible to get the data of the project from the cash mutation table?
In example in cash mutation table with id '4' I wanna call agency name from projects table.
I've done it with with (eager loading in Laravel) but it returns null like:
$cash_mutations = CashMutation::where('id', 4)->with('project')->get();
This is my CashMutation Model:
class CashMutation extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function category(){
return $this->belongsTo(Category::class);
}
public function balanceType(){
return $this->belongsTo(BalanceType::class);
}
public function project(){
return $this->belongsTo(Project::class, 'cash_mutation_id', 'id');
}
public function deposit(){
return $this->hasMany(Deposit::class);
}
}
and this is my Project Model:
class Project extends Model
{
use HasFactory;
protected $guarded = ['id'];
public function cashMutation(){
return $this->belongsTo(CashMutation::class);
}
public function projectFunding(){
return $this->hasMany(ProjectFunding::class);
}
public function SharingProfit(){
return $this->hasMany(SharingProfit::class);
}
}
Is it possible to do that in Laravel? If it possible anyone want to tell me about it? Thanks
Yes. It is definitely possible.
You don’t get an error message so the basic configuration should be fine.
I suspect that the data in the database is not correct. What’s the project_id for the CashMutation with the id 4? Is it maybe null?

Eloquent Multiple Join With Where Clause

I am trying to join the user table with the attendance_user and attendance_supervisor table where the location id is equal to a specific value however currently the results that i am being returned doesnt seem to take into consideration the where clause.
Can anyone please tell me what i am doing wrongly?
$new_attendance_user = AttendanceUser::join('users','users.id','=','attendance_users,user_id')
->join('attendance_supervisors','users.id','=','attendance_supervisors.user_id')
->groupby('user_id')
->where('function($query)uses($location){
$query->where('attendance_supervisors.atttendance_location','=','$location')
->orWhere('attendance_users.atttendance_location','=','$location');
}
->get()
User Table
class User extends Eloquent{
public function attendance_users()
{
return $this->hasMany('attendance_user');
}
public function attendance_supervisors()
{
return $this->hasMany('attendance_supervisor');
}
}
Attendance_user
class AttendanceUser extends Eloquent{
public function userBelongsToUser()
{
return $this->belongsTo('User');
}
}
Attendance_supervisor
class AttendanceSupervisor extends Eloquent{
public function supBelongsToUser()
{
return $this->belongsTo('User');
}
}

Laravel Eloquent Getting children of children via model relqtionships

I'm trying to directly edit my Kodi MySQL DB and build a tool to fix some scraping errors that have always been not quite right.
the relationship of tables is
tvshow -> episode -> file
So I'm able to so far (after creating models for these tables)
List all shows
view specific show and list all episodes
show file entry for that episode.
What I'm trying to do is list all files that belong to the show, via a dropdown. ( as I need to change them )
So I need to use the TVShow model to get all epiodoes that have an idShow entry.. AND then get all the files based on the episode table. I know that Eloquent can handle this typically, but I've only ever used my own table structure, never one like this.. so I think my issue is over riding key names etc...
the key column names are:
idShow
idEpisode
idFile
(Where that SAME name is used as the primary key on the parent table AND the mapping ID in the child table)
Anyhoo, here's my models..
Any ideas?
TVShow
<?php
namespace App\Models;
use Eloquent as Model;
class TvShow extends Model
{
public $table = 'tvshow';
protected $primaryKey = 'idShow';
public function episodes()
{
return $this->hasMany(Episode::class, 'idShow');
}
}
Episode
<?php
namespace App\Models;
use Eloquent as Model;
class Episode extends Model
{
public $table = 'episode';
protected $primaryKey = 'idEpisode';
public function tvshow()
{
return $this->belongsTo(TvShow::class, 'idShow', 'idShow');
}
public function season()
{
return $this->hasOne(Season::class, 'idShow', 'idShow')->where('season', '>=', 0)->where('idSeason', $this->idSeason);
}
public function file()
{
return $this->hasOne(File::class, 'idFile', 'idFile');
}
public function files()
{
return $this->hasMany(File::class, 'idFile', 'idShow');
}
}
File
<?php
namespace App\Models;
use Eloquent as Model;
class File extends Model
{
public $table = 'files';
protected $primaryKey = 'idFile';
public function episode()
{
return $this->belongsTo(Episode::class, 'idFile', 'idFile');
}
}
I'm calling this in my Controller...
TvShow::with('episodes.files')->get();
I'm getting ALL shows as a list..?
A hasManyThrough relationship will work. Add this to your TvShow model.
public function files()
{
return $this->hasManyThrough(Episode::class, File::class);
}
See https://laravel.com/docs/7.x/eloquent-relationships#has-many-through

Laravel Many models as Publisher Polymorphic Relationship with pivot?

Hi I am having problems with relation and database design.
There are three tables called 'articles' , 'users' , and 'companies' with one attribute each called id:
"articles" -id
"users" -id
"companies" -id
The article table contain many publishers that are user model or company model.
My pivot table must be something similar to 'authors' -id, -model_id, -model_name, -article_id
Is there any way to get article's publisher ids and data from models in one collection with a single query? Maybe I misunderstood the problem and there is a simpler solution for that case.
thx in advance
Assuming Article only have one company or one user , The right way to do that is to do a one to many (polymorphic) relationship creating the table with these columns:-
{ article_id , articleable_id , articleable_type }
and then define it in your model
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
/**
* Get all of the owning articleable models.
*/
public function articleable()
{
return $this->morphTo();
}
}
and the Users table:-
class Userextends Model
{
/**
* Get all of the user's articles.
*/
public function articles()
{
return $this->morphMany('App\Article', 'articleable');
}
}
and same in the Company model:-
class Company extends Model
{
/**
* Get all of the companies articles.
*/
public function articles()
{
return $this->morphMany('App\Article', 'articleable');
}
}
and then you can retrieve the relationship using:-
$user = App\User::find(1);
foreach ($user->articles as $article) {
// do this
}
as mentioned here
but if the article can have more than user or company then you have to do many to many polymorphic as mentioned here
#Mohamed Gabr
the problem is that i need this in many to many way.
and i don't have problem to receive article from User model or Company.
I need receive authors from Article.
i assume there will be something like that.
class Article extends Model
{
public function authors()
{
return $this->hasMany('App\Article_Authors','article_id');
}
}
class Article_Authors extends Model
{
public function authorable()
{
return $this->morphTo();
}
public function article(){
return $this->belongsTo('App\Article');
}
}
class User extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
class Company extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
i can make it work but i don't think its good practice
I implement this models
class Article extends Model
{
public function authors()
{
return $this->hasMany('App\Article_Authors','article_id');
}
}
class Article_Authors extends Model
{
public function authorable()
{
return $this->morphTo();
}
public function article(){
return $this->belongsTo('App\Article');
}
}
class User extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
class Company extends Model
{
public function authors()
{
return $this->morphMany('App\Article', 'authorable');
}
}
and after call $article->authors i get
0
id 1
record_id 2
authorable_id 1
authorable_type "App\\User"
created_at "2019-03-22 15:56:38"
updated_at "2019-03-22 15:56:38"
1
id 2
record_id 2
authorable_id 1
authorable_type "App\\Company"
created_at "2019-03-22 15:56:59"
updated_at "2019-03-22 15:56:59"
how to call this models now :(
#MohamedGabr
Edit :
after making research i didn't find any option to get result in one query there is only option to make a loop and checking instants of model.
its generate a loot loops for collection i need cache result and please settle for this temporarily.
thx For help