Laravel save to database with multiple tables having many relations to a table - laravel

I have a transaction table in database. The relation for the transaction table is, customer can send many transactions. A branch can have many transactions and a transaction handler can serve many transactions. I have defined models and relations. But don't know how to save the relations as save one first will make other fk null. Is there any method to save all at once or my database relation is wrong?
My schema is
And my controller code to save the relation is
//Save models related to transactions
$transaction = new Transaction($request->input('partCTransaction'));
//Customer can have many transactions
$customer->transactions()->save($transaction);
//branch has many reporting entities and a branch handles many transactions
$branch->transactions()->save($transaction);
//A transaction handler handles different transactions
$transactionHandler->transactions()->save($transaction);
Any idea on how to resolve this issue.
My error is
General error: 1364 Field 'branch_id' doesn't have a default value (SQL: insert into `transactions` (`date`, `ref_number`, `customer_id`, `updated_at`, `created_at`) values (, , 9, 2018-06-25 23:36:11, 2018-06-25 23:36:11))

Your Transaction model should have customer, branch, and transactionHandler belongsTo relationships:
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function branch()
{
return $this->belongsTo(Branch::class);
}
public function transactionHandler()
{
return $this->belongsTo(TransactionHandler::class);
}
The belongsTo relationship has an associate() method that sets the relationship field, but does not save the record. You can use these relationships to setup all the appropriate relations, and then call save() when you're done.
$transaction = new Transaction($request->input('partCTransaction'));
$transaction->customer()->associate($customer);
$transaction->branch()->associate($branch);
$transaction->transactionHandler()->associate($transactionHandler);
$transaction->save();
Just a side note, associate() returns the child model, so you can chain all these together if you prefer that look:
$transaction = new Transaction($request->input('partCTransaction'));
$transaction
->customer()->associate($customer)
->branch()->associate($branch)
->transactionHandler()->associate($transactionHandler)
->save();

Related

Can we use an observer on the attach method in Laravel?

I would like to observe a pivot table in which, rows are created with an attach method in a specific model, is there a way to Observe that pivot table through the attach method that is responsible for creating rows?
after struggling some time, I came to answer my question,
so in order to observe a table whose rows are created by the attach method, we will need to do 3 things
1- we will need to create a model that extends
$Illuminate\Database\Eloquent\Relations\Pivot
2- Connect the model to the database table with this line:
protected $table = 'data_base_table_name';
3- use the method 'using' at the end of the BelongsToMany relationship in each model that is related to the pivot table
Example:
let's say we have a model called Student and another one called Group, we have also a pivot table called group_students that is filled with the attach method since we have a student BelongsToMany groups and Group BelongsToMany Students,
we will need to create a model named GroupStudent that extends
Illuminate\Database\Eloquent\Relations\Pivot
and link it to the group_students by adding the following line in the GroupStudent Class:
protected $table = 'group_student'
After that, we will need to add the using method The BelongsToMany relations in the Student Model and the Group Model like the following:
public function students()
{
return $this->BelongsToMany(Student::class)->using(GroupStudent::class);
}
and
public function groups()
{
return $this->belongsToMany(Group::class)->using(GroupStudent::class);
}
And here we go, now whenever I create a row in the group_students table through the attach method, this will be observed and the method created will be executed.

Eager Loading with filters (where clauses)?

Is it possible to add where clause to an eager loading method on a model? For example:
class User extends Model {
public function sources()
{
return $this->hasManyThrough(
Source::class, // The related model
UserNetwork::class, // The intermediate table that connects this model with the related model.
'user_id', // The intermediate table's column that connects to this model.
'network_id', // The related table's column that connects to the secondLocalKey.
'id', // This model's column that connects to the firstKey.
'network_id' // The intermediate table's column that connects the related model.
)
->where('xyz_id', $this->xyz_id);
}
}
Doing this User::with('sources')->get() returns a collection of users with the sources relation but the sources collection is empty. When I run User::first()->sources()->get() it returns just the collection of sources with the actual data.
Isn't eager loading supposed to 'eager load' all the records instead of having to specify the the first() record?

Nested eloquent relationship

I just started my first laravel project today and stumbled upon this confusing situation,
I intended to use eloquent relationship instead of manually joining tables on query. So here it goes...
I have 3 tables which are users , tbl_instruments_taught , tbl_instruments
users table does not hold any of the table's ID,
tbl_instruments_taught - holds the id of user and intruments
Note: user can teach multiple instruments
Now, I implemented a hasOne on my other result set but I dont think hasOne works on this one. I read about belongsToMany but as I try implement it, it seems like every minute, it gets confusing.
Any idea?
I think you are looking for pivot table and relation many to many.
You have users table, instruments table (user has many instruments and one instrument could belong to many users) and user_instruments pivot table. Here db model:
And then add belongsToMany relationship in User and Instrument model (with specified pivot table). Like so:
//IN USER MODEL
public function instruments()
{
return $this->belongsToMany('App\Models\Instruments', 'users_instruments', 'user_id', 'instrument_id');
}
//IN INSTRUMENT MODEL
public function users()
{
return $this->belongsToMany('App\Models\Users', 'users_instruments', 'insrument_id', 'user_id');
}
Now you can reach instruments/users data through laravel relations/eager loading.

Broken Eloquent relationship with extended model

I have a model Asset with documents() { $this->hasMany(Document::class); } through a table data_asset_document. I extend Asset into multiple models, one of which is Equipment. In my seeder for Equipment, I attempt to create a Document bound to the Equipment record:
$asset = Equipment::create([...]);
$document = Document::create([
'name' => "$type Purchase Order",
'tracking_number' => app('incrementer')->current()
]);
$asset->documents()->save($document);
Eloquent produces this query:
update `data_document` set `equipment_id` = 1, `data_document`.`updated_at` = 2019-09-20 14:39:48 where `id` = 1
This is obviously incorrect, since data_document does not have an equipment_id column (Documents "belong to" several models besides Asset). How do I rewrite Asset::documents so that produces the correct mapping, even in its extensions? Or do I need to save my Document through a means other than Asset::documents?
Since your extended asset model is called Equipment, Laravel expects your foreign key to be called equipment_id. You will need to specify the actual foreign key of asset_id in your relationship.
https://laravel.com/docs/6.x/eloquent-relationships#one-to-many
hasMany
documents() {
$this->hasMany(Document::class, 'asset_id');
}
The problem is, I'm not convinced your relationship is really hasMany since you mention what looks like a pivot table data_asset_document as being involved. Many-to-many relationships, like mentioned in your title, would use the belongsToMany method.
https://laravel.com/docs/6.x/eloquent-relationships#many-to-many
https://laravel.com/docs/6.x/eloquent-relationships#has-many-through

Laravel / Eloquent hasMany relationship with no foreign key

I have a model (Client) with a hasMany relationship to another (Client_option).
The two tables are in different databases (so there is a list of clients, and then each client has their own database with an options table within).
In my Client class I want my options() method to return the entire contents of the options table (it knows which client db to look for). As it is I get an error because the column client_id does not exist in the options table. I can of course create that column and populate every row with the client's id, but I'd only be doing it to keep Eloquent happy so would rather avoid that little messiness.
Thanks in advance for any input!
Geoff
This will allow you to work with it as a relation, call it as dynamic property $user->options, bulk save with push method and so on:
public function options()
{
// it will use the same connection as user model
$options = ClientOption::on($this->getConnectionName())->get();
// if options model has its own, then simply
// $options = ClientOption::get();
$this->setRelation('options', $options);
return $options;
}
public function getOptionsAttribute()
{
return (array_key_exists('options', $this->relations))
// get options from the relation, if already loaded
? $this->getRelation('options')
// otherwise call the method and load the options
: $this->options();
}

Resources