Attach extra attributes to Laravel pivot table - laravel

I have 4 extra attributes ('product_id', 'quantity', 'discount_percent', 'discount_amount') in my pivot table, but my values for these are always 0 when I store, while the rest is populated properly. Any ideas?
Invoice model
public function productversion()
{
return $this->belongsToMany('App\Productversion')->withPivot('product_id', 'quantity', 'discount_percent', 'discount_amount')->withTimestamps();
}
Productversion model
public function invoice()
{
return $this->belongsToMany('App\Invoice')->withPivot('product_id', 'quantity', 'discount_percent', 'discount_amount')->withTimestamps();
}
Controller (store)
$invoice->productversion()->attach($productversionid, ['product_id' => $productid], ['quantity' => $qty], ['discount_percent' => $discountprc], ['discount_amount' => $discountamt]);

Just one array will do:
$invoice->productversion()->attach($productversionid, [
'product_id' => $productid,
'quantity' => $qty,
'discount_percent' => $discountprc,
'discount_amount' => $discountamt
]);

In addition to #jeff's method, you can attach or sync multiple elements with pivot attributes providing a multidimensional array that has ids as keys.
$attach_data[$productversionid] = [
'product_id' => $productid,
'quantity' => $qty,
'discount_percent' => $discountprc,
'discount_amount' => $discountamt
];
Then you can $invoice->productversion()->attach($attach_data).
Substantially you can pass an array like
[
'relation_id' => [
// pivot data
],
'relation_id' => [
// pivot data
],
// ...
]

Related

Add order Laravel

I am adding order to database. It works like this: When ordering is clicked, the order is created in the Order table, at the same time the product items are also added to the OrderItem table, via the order_id foreign key. But I don't know how to get the order_id, because it is added at the same time, and the Order id is increments.
public function save(array $data, int $id = null){
$idCurrent = Auth::id();
$orderItems = $data['orderItems'];
//add to Order
Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
//add to OrderItem
foreach($orderItems as $item){
OrderItem::Create([
'order_id' => 222, //=> ?????????????
'product_id' => $item -> product_id,
'quantity' => $item->quantity,
]);
}
return true;
}
$order = Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
//add to OrderItem
foreach($orderItems as $item){
OrderItem::Create([
'order_id' =>$order->id
'product_id' => $item -> product_id,
'quantity' => $item->quantity,
]);
}
return true;
Avoid multiple call to databases.
When you create order with
$order = Order::updateOrCreate(
[
'id' => $id
],
[
'user_id' => $idCurrent,
'shipping_fee' => $data['shipping_fee'],
'total' => $data['total'],
'payment' => $data['payment'],
'status_id' => 1,
]
);
next you should is to send just one request to database with
// create batch array
$insertOrderItems = [];
foreach($orderItems as $item){
$insertOrderItems[] = [
'product_id' => $item->product_id,
'quantity' => $item->quantity,
];
}
// insert all at once in batch mode making just one call to database
$order->orderItems()->create($insertOrderItems);
Presuming you have sorted relations in Order and OrderItem models.

Filter values in select fields

I'm using Laravel 7 + Backpack CRUD 4.1.
I have two models Payment and PaymentMethods and field in PaymentCrudController
$this->crud->addField([
'label' => 'Payment Method',
'type' => 'select2',
'name' => 'payment_method_id',
'entity' => 'paymentMethod',
'attribute' => 'name',
'model' => 'App\Models\PaymentMethod',
'wrapperAttributes' => [
'class' => 'form-group col-md-3',
],
]);
Relation in Payment model:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class, 'id', 'payment_method_id');
}
Actually, this works as expected - I see all records from the PaymentMethod model in the options field. But I need to filter some values. I trying to modify model relation:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class, 'id', 'payment_method_id')->where('name', '!=', 'Online');
}
But I still see all records in select options. How can I filter select values?
putting 'where' in relation make no sense, in my opinion, relation should be as it is, reflect tables 's relations ....
for your suituation you could use 'options' for 'select2' field:
$this->crud->addField([
'label' => 'Payment Method',
'type' => 'select2',
'name' => 'payment_method_id',
'entity' => 'paymentMethod',
'attribute' => 'name',
'model' => 'App\Models\PaymentMethod',
'options' => (function ($query) {
return $query->where('name', '!=', 'Online')->get();}),
'wrapperAttributes' => [
'class' => 'form-group col-md-3',
],
]);
something else ... for your one to many relation: it should be:
public function paymentMethod()
{
return $this->hasOne(PaymentMethod::class,'payment_method_id');
}
second parameter should be the foreign key ...

Laravel multi dimensional array validation

I am trying to validate a multi dimensional array in Laravel. This whole input itself is not required, however, if it is present, all of its keys should have some value.
My Input has dynamic input arrays.
Example :
$users = [
['name' => 'John' , 'Age' => 25],
['name' => 'Nick' , 'Age' => 28]
]
My requirement is that, if a record is sent along with the request, it has to contain both name and age. At the same time, this whole array is not mandatory.
I can accept
$users = []
Cannot accept
$users = [
['name' => '' , 'Age' => 25],
['name' => 'Nick' , 'Age' => null]
]
Something like that in your Request should work:
public function rules()
{
return [
'users' => 'array', //add 'sometimes' if the array can be null other than empty
'users.*.name' => 'required',
'users.*.Age' => 'required',
]
}
This return false if any of the user is missing name or Age attributes.
I like #Shafeel's solution - Here is another way to go around:
if(count($users >= 1){
foreach($users as $user) {
if(empty($user->name) || empty($user->age) {
return false; //break the loop and return with error message
}
}
}
You can validate an array as an optional or sometimes a validation rule inside a validator.
public function rules()
{
return [
'users' => 'sometimes|array',
'users.*.name' => 'sometimes',
'users.*.Age' => 'sometimes',
]
}
** OR you can**
public function rules()
{
return [
'users' => 'optional|array',
'users.*.name' => 'optional',
'users.*.Age' => 'optional',
]
}

How to insert all json file data in database?

I have JSON file and have data in it. I want to import all data in the database through DB seeders. I am getting an error Trying to get property name of non-object. I have multiple data how I can insert in the database?
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
// dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj[0]->Name,
'description' => $obj[0]->description,
'altitudeMode' => $obj[0]->altitudeMode,
'Town' => $obj[0]->Town,
'AC' => $obj[0]->AC,
'No_of_TW' => $obj[0]->No_of_TW,
'No' => $obj[0]->No,
'DC'=> $obj[0]->DC,
'HH_2017' => $obj[0]->HH_2017,
'FID' => $obj[0]->FID,
'Area_ha' => $obj[0]->Area_ha,
'Field_1' => $obj[0]->Field_1,
'Pop_Dens' => $obj[0]->Pop_Dens,
'Id' => $obj[0]->Id,
'Pop_2017' => $obj[0]->Pop_2017,
'Area_Sq'=> $obj[0]->Area_Sq,
));
}
}
Sample Json Format
31 => {#837
+"type": "Feature"
+"properties": {#838
+"Name": "Gujjar Pura"
+"description": null
+"altitudeMode": "clampToGround"
+"Town": "Shalimar Town"
+"AC": "31"
+"No_of_TW": "11"
+"No": "13"
+"DC": "38"
+"HH_2017": "30478"
+"FID": "31"
+"Area_ha": "648.327"
+"Field_1": "Gujjar Pura"
+"Pop_Dens": "54063.141167"
+"Id": "0"
+"Pop_2017": "196619"
+"Area_Sq": "3.63684"
}
+"geometry": {#839
+"type": "MultiPolygon"
+"coordinates": array:1 [
0 => array:1 [
0 => array:169 [ …169]
]
]
}
}
Let's support I have a model Post and I want to save additional data in JSON format in the posts table. In that case, we can use property $casts in Laravel. Which will cast our field value to whatever we gave.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table='posts';
protected $fillable = ['user_id', 'title', 'short_description', 'description', 'status', 'json_data'];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'json_data' => 'array',
];
}
Now we want to save data something like this
$data = [
'user_id' => 1,
'title' => 'abc',
'short_description' => 'test',
'description' => 'test',
'status' => true,
'json_data' => [
'additional_info' => '',
'post_image' => '',
...
],
];
$item = new Post;
$item->fill($data)->save();
This will save your json_data array values to JSON in the database. But when you will get data from the database it will convert that to array automatically.
For reference read this
since i am not a big fan of processing the json as a object
So the json_decode will accept the second arg so
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json,true);
dd($data);
foreach ($data as $obj)
{
Regions::create(array(
'name' => $obj['Name'],
'description' => $obj['description'],
'altitudeMode' => $obj['altitudeMode'],
'Town' => $obj['Town'],
'AC' => $obj['AC'],
'No_of_TW' => $obj['No_of_TW'],
'No' => $obj['No'],
'DC'=> $obj['DC'],
'HH_2017' => $obj['HH_2017'],
'FID' => $obj['FID'],
'Area_ha' => $obj['Area_ha'],
'Field_1' => $obj['Field_1'],
'Pop_Dens' => $obj['Pop_Dens'],
'Id' => $obj['Id'],
'Pop_2017' => $obj['Pop_2017'],
'Area_Sq'=> $obj['Area_Sq'],
));
}
Can You Post the dd() result and fileds sets of the table
public function run()
{
$json = File::get("public/kmz/WASASubdivisions.geojson");
$data = json_decode($json);
dd($data);
foreach ($data as $obj){
Regions::create(array(
'name' => $obj->Name,
'description' => $obj->description,
'altitudeMode' => $obj->altitudeMode,
'Town' => $obj->Town,
'AC' => $obj->AC,
'No_of_TW' => $obj->No_of_TW,
'No' => $obj->No,
'DC'=> $obj->DC,
'HH_2017' => $obj->HH_2017,
'FID' => $obj->FID,
'Area_ha' => $obj->Area_ha,
'Field_1' => $obj->Field_1,
'Pop_Dens' => $obj->Pop_Dens,
'Id' => $obj->Id,
'Pop_2017' => $obj->Pop_2017,
'Area_Sq'=> $obj->Area_Sq,
));
}
}
The attributes are under the properties key, but you're referencing them from the root of the object. e.g. $obj[0]->Name should be $obj[0]->properties->Name, etc.

How to add fields which are not available in database?

I am not able to add field which is not available in my database
I have tried adding
$this->crud->addFields([
[
'name' => 'coupon_type',
'label' => 'Coupon For',
'type' => 'select_from_array',
'options' => [
// Options
],
'allows_null' => true,
'default' => 1,
'attributes' => [
'id' => 'coupon_type'
]
]
]);
I want to add fields in my create page.
You can do this by defining accessors for your "virtual" attributes
public function getIsAdminAttribute()
{
return $this->attributes['admin'] == 'yes';
}
and defining the appends on your model
protected $appends = ['is_admin'];
Find everything in the docs here:
https://laravel.com/docs/5.8/eloquent-serialization#appending-values-to-json

Resources