Laravel many-to-many relation with custom table names and IDs - laravel

Hello so I have many to many relation between Question [table name: tblquestion, id: que_id] and Agecategory [table name: tblagecategory, id: aca_id]. They have shared table named QuestionAgecategory [table name: tblquestionagecategory, id: qac_id].
I want to note that all the IDS and table names are custom named and not according to typical Laravel syntax.
And I am trying to relate them in Laravel. So far it returns null when I try to look $question->agecategories;
$question->agecategories;
=> null
But it has records in it and returns this after $question = App\Question::find(1);
$question = App\Question::find(1);
=> App\Question {#2901
que_id: 1,
que_name: "hello",
Question model
class Question extends Model
{
protected $table = 'tblquestion';
protected $primaryKey = 'que_id';
protected $keyType = 'integer';
public $incrementing = true;
public $timestamps = false;
public function agecategories()
{
return $this->belongsToMany('App\Agecategory');
}
}
Agecategory model
class Agecategory extends Model
{
protected $table = 'tblagecategory';
protected $primaryKey = 'aca_id';
protected $keyType = 'integer';
public $incrementing = true;
public function questions()
{
return $this->belongsToMany('App\Question');
}
}
QuestionAgecategory model
class QuestionAgecategory extends Model
{
protected $table = 'tblquestionagecategory';
protected $primaryKey = 'qac_id';
protected $keyType = 'integer';
public $incrementing = true;
}
Migrations
Schema::create('tblquestion', function (Blueprint $table) {
$table->increments('que_id');
$table->string('que_name', 128);
});
Schema::create('tblagecategory', function (Blueprint $table) {
$table->increments('aca_id');
$table->timestamps();
});
Schema::create('tblquestionagecategory', function (Blueprint $table) {
$table->increments('qac_id');
$table->integer('qac_que_id')->unsigned();
$table->integer('qac_aca_id')->unsigned();
$table->foreign('qac_que_id')->references('que_id')->on('tblquestion');
$table->foreign('qac_aca_id')->references('aca_id')->on('tblagecategory');
});

You are using custom columns and custom database naming.
Your Belongs to many is expecting a pivot table tblquestion_tblagecategory which does not exist. As the previos answer stated, you should change your belongsToMany to search for the custom tables and columns.
https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
Change to this in your question Model
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'qac_que_id', 'qac_aca_id');
}
And also, in your other Agecategory Model
public function questions()
{
return $this->belongsToMany('App\Question', 'tblquestionagecategory', 'qac_aca_id', 'qac_que_id');
}

add below relationship function in Question model
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'qac_que_id', 'qac_aca_id');
}

I encountered the same problem but I had to declare only the foreign keys without a prefix like this:
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'que_id', 'aca_id');
}

Related

How can i store more than one product_ticket?

Im trying to store more than one product with my controller. In my function store first i generate a ticket and then i generate a product_ticket with the ticket_id recently generated and the product_id from the selected product from the form. But how can i do to store more than one if i select more than one product in the form.
This are my relationships:
Product.php:
class Product extends Model
{
public function tickets()
{
return $this->belongsToMany(Ticket::class);
}
public function productXticket()
{
return $this->hasMany(ProductXTicket::class);
}
}
Ticket.php
class Ticket extends Model
{
public function productXticket()
{
return $this->hasMany(ProductXTicket::class);
}
public function products()
{
return $this->belongsToMany(Product::class);
}
}
ProductXTicket:
class ProductXTicket extends Model
{
protected $table = 'product_ticket';
public function ticket_id(){
return $this->belongsTo(Ticket::class);
}
public function product_id(){
return $this->belongsTo(Product::class);
}
}
product_ticket migration:
Schema::create('product_ticket', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id')->constrained();
$table->foreignId('ticket_id')->constrained();
$table->string('serial_number');
$table->integer('quantity');
$table->timestamps();
});
}
TicketController:
public function store(Request $request){
/*dd($request->all());*/
$ticket = new Ticket();
/*$ticket->cuenta_id = $request->cuenta_id;*/
$ticket->contact_id = $request->contact_id;
$ticket->statusTicket_id = $request->statusTicket_id;
$ticket->typeTicket_id = $request->typeTicket_id;
$ticket->idOwner = Auth::user()->id;
$ticket->save();
$productXticket = new ProductXTicket();
$productXticket->ticket_id = $ticket->id;
$productXticket->serial_number = $request->serial_number;
$productXticket->quantity = $request->quantity;
$ticket->productXticket()->save($productXticket);
Session::flash('success');
return redirect()->route('tickets.view');
}
So here im storing one ticket and one product_ticket. I want form each ticket to store the same amount of product_ticket as the amount products selected
Instead of:
$ticket->productXticket()->save($productXticket);
Use:
$ticket->productXticket()->saveMany([$productXticket,...]);

Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsTo::save()

I want to insert data into multiple tables (one to one), but i get error and in my database the column "metode_id" is null. i want the "metode_id" is not null
this is class "Transaksi" :
class Transaksi extends Model
{
protected $table = "transaksi";
protected $primarykey = "id";
protected $fillable = ['stok_kedelai', 'stok_ragi', 'harga_kedelai', 'harga_ragi'];
public function metode()
{
return $this->belongsTo('App\Metode');
}
public function pengguna()
{
return $this->belongsTo('App\Pengguna');
}
}
This is class "Metode" :
class Metode extends Model
{
protected $table = "metode";
protected $primarykey = "id";
protected $fillable = ['bni', 'bri', 'mandiri', 'bca', 'btpn', 'ovo', 'gopay', 'dana'];
public function transaksi()
{
return $this->hasOne('App\Transaksi', 'metode_id');
}
}
This is database of "Transaksi" :
public function up()
{
Schema::create('transaksi', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('pengguna_id')->unsigned();
$table->integer('stok_kedelai');
$table->integer('stok_ragi');
$table->integer('harga_kedelai');
$table->integer('harga_ragi');
$table->bigInteger('metode_id')->unsigned();
$table->timestamps();
});
Schema::table('transaksi', function (Blueprint $table) {
$table->foreign('pengguna_id')->references('id')->on('pengguna')->onDelete('cascade')->onUpdate('cascade');
});
Schema::table('transaksi', function (Blueprint $table) {
$table->foreign('metode_id')->references('id')->on('metode')->onDelete('cascade')->onUpdate('cascade');
});
}
This is database of "Metode" :
public function up()
{
Schema::create('metode', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('bni')->nullable();
$table->integer('bri')->nullable();
$table->integer('mandiri')->nullable();
$table->integer('bca')->nullable();
$table->integer('btpn')->nullable();
$table->integer('ovo')->nullable();
$table->integer('gopay')->nullable();
$table->integer('dana')->nullable();
$table->timestamps();
});
}
i want insert data into mutiple table that which depends on the "id" of pengguna table but i get error Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsTo::save()
public function data_penjualan(Request $request)
{
$pengguna = Pengguna::where('id', Auth::user()->id)->first();
$transaksi = new Transaksi();
$transaksi->stok_kedelai = $request->stok_kedelai;
$transaksi->stok_ragi = $request->stok_ragi;
$transaksi->harga_kedelai = $request->harga_kedelai;
$transaksi->harga_ragi = $request->harga_ragi;
$pengguna->transaksi()->save($transaksi);
$metode = new Metode();
$metode->bni = $request->bni;
$transaksi->metode()->save($metode);
return view('transaksi.supplier', compact('transaksi'));
}
this is my database, the "metode_id" get null, how i want that "metode_id" is not null :
enter image description here
If you try to update a belongsTo relationship, you have to use the associate method instead of save method.
...
$metode = new Metode();
$metode->bni = $request->bni;
$metode->save();
$transaksi->metode()->associate($metode);
$transaksi->save();
...
If you try to SaveMethod in the belongsTo relationship.
Add Comment(controller file)
public function addComment($id)
{
$comment = new Comment(['comment' =>'Comment 1']);
$user = User::find(1);
$user->comment()->save($comment);
return "Comment Submitted";
}
Comment.php (Model File)
class Comment extends Model
{
use HasFactory;
protected $table ="comments";
protected $fillable = ['comment'];
public function User()
{
return $this->belongsTo(User::class);
}
}
web.php (Route File)
Route::get('comment/{id}',[UserController::class,'addComment']);

Completion system with Laravel + VueJS

I've been tring for hours to define my relations for a completion system but I failed.
I have a table Users and a table Episodes, and I would like to get in my views if the User has completed an episode.
I created a "completions" table with user_id and episode_id and a boolean field called "completed"
Is it a manytomany relation ? I'd like to have something like $episode->completed which gave me True if the logged in user finished the course, but I can't find my way... I just wanna know how to define my relations, not a whole work done.
Thank you very much !!!!
I believe you can tell Laravel what table to use and also query the pivot column.
//user model
public function episodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' );
}
public function completedEpisodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' )
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany( 'App\User', 'completions', 'episode_id', 'user_id' );
}
The alternative would be to create your pivot as episode_user and laravel will auto detect it as the pivot, add a completed boolean to that table and it would function with just:
//user model
public function episodes(){
return $this->belongsToMany('App\Episode');
}
public function completedEpisodes(){
return $this->belongsToMany('App\Episode')
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany('App\User');
}
Query if episode is complete:
//maybe, haven't tried this
//user
public function hasCompletedEpisode($id){
return $this->belongsToMany('App\Episode')->wherePivot('episode_id','=', $id)
->wherePivot('completed','=', true)->get();
}
//episode
public function hasCompletedEpisode($id){
$user_id = Auth::id();
return $this->belongsToMany('App\User')->wherePivot('user_id','=', $user_id)
->wherePivot('completed', true)->get();
}
If I was you, I would use a custom intermediate table. You can implement this as follows:
Migrations
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('episodes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('watches', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('epsiode_id');
$table->boolean('completed');
$table->timestamps();
});
Models
class User extends Model
{
protected $guarded = [];
public function watchedEpisodes()
{
return $this->hasMany(Episode::class)->using(Watch::class);
}
public function watches()
{
return $this->hasMany(Watch::class);
}
}
class Episode extends Model
{
protected $guarded = [];
public function users()
{
return $this->hasMany(User::class)->using(Watch::class);
}
}
class Watch extends \Illuminate\Database\Eloquent\Relations\Pivot
{
protected $table = 'watches';
protected $guarded = [];
public static function create(User $user, Episode $episode, bool $completed = false)
{
$watch = new self();
$watch->user_id = $user->id;
$watch->epsiode_id = $episode->id;
$watch->completed = $completed;
$watch->save();
return $watch;
}
public function user()
{
return $this->hasOne(User::class);
}
public function episode()
{
return $this->hasOne(User::class);
}
}
Example Use
$user = User::create(['name' => 'Big Watcher']);
$episode1 = Episode::create(['name' => 'Episode 1']);
$episode2 = Episode::create(['name' => 'Episode 2']);
$episode3 = Episode::create(['name' => 'Episode 3']);
$episode4 = Episode::create(['name' => 'Episode 4']);
Watch::create($user, $episode1);
Watch::create($user, $episode2);
Watch::create($user, $episode3);
return $user->watchedEpisodes;

My hasMany in laravel response null, my model its correct

I have problem my has many relation response null.
this is my model
class Diskusi extends Model
{
protected $table = 'tbl_diskusi';
protected $hidden = [
'topic'
];
public function user(){
return $this->belongsTo(User::class,'id_user');
}
public function category(){
return $this->belongsTo(Category::class);
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class);
}
}
this is my another model
class PetsCategory extends Model
{
//
protected $table = 'tbl_pets_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_pets_category');
}
}
and another
class Category extends Model
{
//
protected $table = 'tbl_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_category');
}
}
and this is my migration for Diskusi
class CreateTblDiskusi extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tbl_diskusi', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('content');
$table->string('topic');
$table->unsignedBigInteger('id_user');
$table->unsignedBigInteger('id_category');
$table->unsignedBigInteger('id_pets_category');
$table->timestamps();
$table->foreign('id_user')->references('id')
->on('users')->onDelete('cascade');
$table->foreign('id_category')->references('id')
->on('tbl_category')->onDelete('cascade');
$table->foreign('id_pets_category')->references('id')
->on('tbl_pets_category')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('tbl_diskusi');
}
}
the condition is
i want my Diskusi have one category, and one pets_category
but when i create Diskusi like this
public function create(Request $request)
{
$diskusi = new Diskusi;
$diskusi->title = $request->title;
$diskusi->content = $request->content;
$diskusi->topic = $request->topic;
$diskusi->id_user = Auth::user()->id;
$diskusi->id_category = $request->id_category;
$diskusi->id_pets_category = $request->id_pets_category;
if ($request->photo != ''){
foreach ($request->photo as $itemPhoto) {
# code...
$photo = new Photo;
$rand = $this->generateRandomString() . 'jpg';
//taroh foto di server
// file_put_contents('storage/photo/diskusi/' . $rand , base64_decode($request->photo));
$photo->path_photo = $rand;
$photo->save();
}
}
$diskusi->save();
$diskusi->user;
$diskusi->category;
$diskusi->pets_category;
return response()->json([
'success' => true,
'message' => 'posted',
'post' => $diskusi
]);
}
the response like this
please help me, i tried with many tutorial relational laravel but it's not working for me. i dont know where my false, please tell me my false.
*note: sorry for bad english
You've to define your foreign key in relationship.
public function category(){
return $this->belongsTo(Category::class,'id_category','id');
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class,'id_pets_category','id');
}
If you don't pass the foreign key then by default it judges 'category_id' or 'pets_category_id' but you've given id_category and id_pets_category

Populate laravel object with relationships

I want to populate Every CustomerEvent with the Customer related to the CustomerEvent.
When I Loop through the object and call to $customerevent->customer foreach object I can get the customer related to that event but Can I populate the all objects in the main object without looping through every single event ?
I want to do something like this:
$typeOne = CustomerEvent::typeOne()->get();
$customersWithTypeOne = $typeOne->Customers;
Here my code:
Table 1: "events"
id, customer_id
Model for Table 1 "CustomerEvent":
<?php
class CustomerEvent extends Eloquent{
protected $guarded = ['id'];
public $table = "event";
protected $softDelete = true;
public function scopeTypeOne($query)
{
$followUps = $query->where('type_id', '=', '1');
}
public function Customers()
{
return $this->belongsTo('Customer', 'customer_id');
}
}
Table 2: "customers"
id
Model for Table 2 "Customers":
<?php class Customer extends BaseModel{
protected $guarded = ['id'];
}
EventController:
public function index()
{
$typeOne = CustomerEvent::typeOne()->get();
$customersWithTypeOne = $typeOne->Customers;
dd($customersWithTypeOne);
}
From you database scheme I see customer has many events, so I would recommend to define this relationship in you Customer model.
class Customer extends BaseModel{
protected $guarded = ['id'];
public function events()
{
return $this->hasMany('CustomerEvent', 'customer_id');
}
}
Then you will be able to query customers with events:
$customersWithTypeOne = Customer::whereHas('events', function($query){
$query->where('type_id', 1);
})->get()
Maybe Ardent can help you: https://github.com/laravelbook/ardent
It's an extension for Eloquent models and very popular.

Resources