Laravel - Many to Many Polymorphic Relation with Extra Fields - laravel

How can I define a many to many polymorphic relation with extra fields?
I have three (or more, as it is a polymorphic relation) tables.
tags table: id, name
tagged table: id, tag_id, taggable_id, taggable_type, user_id
posts table: id, record, timestamps
users table: id, name, email
The user_id on the tagged table referes to the users table on column id.
In my Post model I have:
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable','tagged');
}
and in my Tag model I have:
public function posts()
{
return $this->morphedByMany('App\Post', 'taggable','tagged');
}
Then when I am try this in my controller:
$tag = new \App\Tag(
array(
'tag'=>"someTag"
));
$tag->save()
$post = \App\Post::find($id);
$post->tags()->save($tag);
I get Integrity Constraint Violation for not having a user_id:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (hb.tagged, CONSTRAINT tagged_user_id_foreign FOREIGN KEY (user_id) REFERENCES users (id)) (SQL: insert into tagged (tag_id, taggable_id, taggable_type) values (26, 2, App\Resource)).
Which is somewhat expected, as I have never had the chance to define or declare the user_id field.
Also, I have tried withPivot() on tags relation as follows, to no avail:
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable','tagged')->withPivot('user_id');
}

Like in the comment: withPivot has nothing to do with saving/creating. If you want to pass additional pivot data when saving, do this:
$post->tags()->save($tag, ['user_id' => $userId]);

Related

How to delete record with composite primary keys using Eloquent?

I'm trying to delete a record with two primary keys, using Eloquent - Laravel.
This is my model
class Like extends Model
{
//protected $primaryKey = ['crdid', 'usrid'];
public $timestamps = false;
use HasFactory;
}
Controller
try{
$dellike = Like::where('crdid', '=', $like->crdid, 'and')
->where('usrid', '=', $like->usrid)->first();
$dellike->delete();
}
catch(Exception $e){
return $e->getMessage();
}
Table definition
Schema::create('likes', function (Blueprint $table) {
$table->biginteger('crdid');
$table->biginteger('usrid');
$keys = array('crdid', 'usrid');
$table->primary($keys);
});
However, it gives me the below error;
Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: delete from `likes` where `id` is null)
I believe the 'id' is the default primary key used by Eloquent, but I'm not using it.
How should I define that, I'm not using the default primary key? or what is the correct way to delete the record with composite primary keys? Any help would be highly appreciated.
As Laravel Eloquent Docs says:
Eloquent requires each model to have at least one uniquely identifying "ID" that can serve as its primary key. "Composite" primary keys are not supported by Eloquent models. However, you are free to add additional multi-column, unique indexes to your database tables in addition to the table's uniquely identifying primary key.
So you can't use some methods of eloquent.
But seeing your code, looks like you are trying to create a model for a relationship pivot table (many to many between user and crd (what is crd?! no reason to abreviatte here.)
Try defining a many to many relationship on your user and crd model.
Also laravel naming convention for key columns is: model_name_id for a model named ModelName
But, just to delete, you can skip the first in your query:
Like::where('crdid', '=', $like->crdid, 'and')
->where('usrid', '=', $like->usrid)->delete();
This happens because when you delete a model (your attempt) laravel uses the primary key field (defaults to id) as where condition. But manually querying, you are defining the where clauses of the delete.
Just create additionnal column named id in the table as unique with auto-increment option. Eloquent will use it to delete each row with delete function.
Example with Laravel 5.5 :
$logement = Logement::findOrFail($id);
$commodites = Commodites_logement::all()->where('logement_id','=',$logement->id);
foreach ($commodites as $commodite) {
$commodite->delete();
}

Laravel get column name using child table with eager loading

I want to fetch the data from profile table using a child table of other parent table.
Here is the tables
Profile table
id
profile_name
Transaction table
id
transaction_name
Sub transaction table
id
transaction_id
profile_id
Now i want to get the profile name from transaction model using eager loading . i tried has one Though relationship in transaction model but returning null
Here is my relationship in Transaction model
public function profileName()
{
return $this->hasOneThrough(
Profiler::class,
SubTransaction::class,
'profile_id',
'id',
'id',
'transaction_id',
);
}
Here is where i am trying to fetch from transaction controller
$options = Transaction::with([
'profileName:id,profile_name as profileName',
])
->get();
It returns null because I think you have a little problem about matching between foreign keys and local keys. You could try the following code:
return $this->hasOneThrough(
Profiler::class, //Final model we wish to access
SubTransaction::class, //The name of the intermediate model
'transaction_id', //Foreign key on sub_transaction table
'id', //Foreign key on profile table
'id', //Local key on transaction table
'profile_id', //Local key on sub_transaction table
);
If you have any problem, tell me.

Why am I getting the error in post? Laravel

So I'm trying to create a simple REST API using Laravel.
While testing out the API with creating new items to the database I'm receiving an error:
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (world.cities, CONSTRAINT cities_ibfk_1 FOREIGN KEY (CountryCode) REFERENCES country (Code)) (SQL: insert into cities (Name, CountryCode, District, Population, updated_at, created_at) values (Valhalla, vlh, Ragnar Alley, 200000000, 2020-02-19 01:07:26, 2020-02-19 01:07:26)) in file C:\xampp\htdocs\myapp\vendor\laravel\framework\src\Illuminate\Database\Connection.php on line 669
here's the Controller:
public function createCity(Request $request) {
$city = new City;
$city->Name = $request->Name;
$city->CountryCode = $request->CountryCode;
$city->District = $request->District;
$city->Population = $request->Population;
$city->save();
Model:
class City extends Model
{
protected $table = 'cities';
protected $fillable = ['Name', 'CountryCode', 'District', 'Population'];
}
Help would be appreciated as I can't figure out why I'm getting the error after POST.
Thanks in advance.
You try to add vlh as contry_code value into your model .but this field refrence to another model that have country name and in that table there is not any record with this condition and vlh value is unknown or it.
You can romve relation between these models (if it is possible) or first find the id of country that has that code and then insert it into your model.

yii 1.1.x ar relation for composite forign key

I have three tables
Boooking
id, -> primary key
name
Ticket
booking_id, (primary key)
seq , (primary key)
name
TicketAllocation
id, (primary key)
booking_id, (foreign key)
seq, (foreign key)
name,
date
Ticket table has primary key as composite of(booking_id,seq), and foreign key booking_id from Booking table.
and it works as foreign key in TicketAllocation table.
How can i define relation in both Ticket and TicketAllocation table so i can use AR relation to get related data.
Hii it you can simply use this
Ticket Model
public function relations()
{
return array(
'ticketToBoooking' => array(self::BELONGS_TO, 'Boooking', 'booking_id'),
);
}
TicketAllocation Model
public function relations()
{
return array(
'ticketAllcationToBooking' => array(self::BELONGS_TO, 'Boooking', 'booking_id'),
);
}

One-to-one relations that only go one way in Laravel

Is it possible/right to have a a relation between tables that only goes one way? I have an invoices table that I need to reference in other tables likes commission_payments and membership_payments but the invoices table does not need a commission_payment_id or a membership_payment_id. In other words, there different types of transactions that can happen and they all may have a invoice attached, but the invoice does not need to reference these transaction tables.
invoices commission_payments membership_payments
--------------- --------------------- ---------------------
-id -id -id
... -invoice_id -invoice_id
... ...
I have created Eloquent models for each table. I added a hasOne relation to invoices on the other two models.
class CommissionPayment extends Model{
public function invoice(){
return $this->hasOne('App\Models\Invoice');
}
}
I then tried accessing the Comission Payment's attached invoice like this:
$com = CommissionPayment::first();
$com->invoice->id;
I then get this error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'invoices.commission_payment_id' in 'where clause' (SQL: select * from `invoices`
where `invoices`.`commission_payment_id` = 15 and `invoices`.`commission_payment_id` is not
null limit 1)
Why is it looking for commission_payment_id field in the invoices table? I would expect a query sort of like this:
SELECT * FROM `invoices` WHERE `id` = 23
/* id is fetched from the `invoice_id` field in the `commission_payments` table */
Do I HAVE to add a column for each table that will reference invoice_id? At the moment it's two but this could grow. Also, when an invoice was generated for a commission payment, it won't need the membership payment field so I don't think it should go there.
A one-to-one relationship is setup using either the hasOne or belongsTo relationship. The hasOne side of the relationship assumes the foreign key is stored on the other table. The belongsTo side of the relationship has the foreign key.
Therefore, since your foreign key to the invoices are stored on the commission_payments and membership_payments tables, those models are said to belong to the invoices table.
Change your relationship from hasOne to belongsTo and you should be good to go:
class CommissionPayment extends Model{
public function invoice() {
return $this->belongsTo('App\Models\Invoice');
}
}

Resources