Laravel attach issue - laravel

I'm going to attach a specific present item with various pivot values to a single order. I'm looking around for something like :
$order->presents()->attach(1,[
['price' => '2400, 'qty' => 2],
['price => '1000, 'qty' => 4]
]);
of course its not a valid code.i can attach items one by one:
$order->presents()->attach(1,['price' => '2400, 'qty' => 2]);
$order->presents()->attach(1,['price => '1000, 'qty' => 4]);
but i think there should be a better way, can anyone let me know how may i do a bunch attach?

Lookin at the documentation I can see you almost got the solution.
Referring to the documentation you should use an array like array(id => [values]). In your case:
$order->presents()->attach([
1 => [
'price' => 2400,
'qty' => 2
],
....
]);
This code has not been tested.
Edit
When you check the attach() function in the deep dungeons of the Laravel framework can see it also accepts a Model, Collection or integer. When you look further you can see it (maybe) also accepts an array of ID's.
/**
* Attach a model to the parent.
*
* #param mixed $id
* #param array $attributes
* #param bool $touch
* #return void
*/
public function attach($id, array $attributes = [], $touch = true)
{
if ($id instanceof Model) {
$id = $id->getKey();
}
if ($id instanceof Collection) {
$id = $id->modelKeys();
}
$query = $this->newPivotStatement();
$query->insert($this->createAttachRecords((array) $id, $attributes));
if ($touch) {
$this->touchIfTouching();
}
}
Don't know if it works, but try:
$order->presents()->attach([1, 1], [[
'price' => 2400,
'qty' => 2
], [
'price' => 1337,
'qty' => 420
]
]
]);

You can do it like this:
$order->presents()->attach([
1 => ['count' => 3, 'price' => '2400, 'qty' => 2],
2 => ['count' => 4, 'price' => '2400, 'qty' => 2]
]);

Related

Laravel Resource return value from another Resource?

I tried to find a solution here but nothing worked. I want to return values from TagResource using MealResource because I have TagTranslations table and I'm getting the data from the table with translations in TagResource.
Relationships are correctly formed, meal and tag models are connected via meal_tags table and tagtranslations belongsTo Tag::class.
I used TagResource like this:
class TagResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$translation = $this->translations->where('tag_id', $this->id)->first();
return
[
'id' => $this->id,
'title' => $translation->title,
'slug' => $translation->slug,
];
}
}
and MealResource like this:
public function toArray($request)
{
$translation = $this->translations->where('meal_id', $this->id)->first();
$category_translation = $this->category->translations->where('category_id', $this->category->id)->first();
return [
'id' => $this->id,
'title' => $translation->title,
'decription' => $translation->description,
'category' => [
'id' => $this->category->id,
'title' => $category_translation->title,
'slug' => $category_translation->slug,
],
'tags' => FILL IN THE BLANK (have used TagResource:collection() and new TagResource()) and didnt work
];
}
public function toArray($request)
{
$translation = $this->translations->where('meal_id', $this->id)->first();
$category_translation = $this->category->translations->where('category_id', $this->category->id)->first();
return [
'id' => $this->id,
'title' => $translation->title,
'decription' => $translation->description,
'category' => [
'id' => $this->category->id,
'title' => $category_translation->title,
'slug' => $category_translation->slug,
],
'tags' => TagResource::collection($this->tags),
];
}
If all the Relationships namings/mappings are correct then this will work.And please make sure that model are perfectly mapped respectively.

Laravel subquery other table

How can I get data from another table?
// ServiceComplexController
public function index(Store $store): JsonResponse
{
/* #var User $user */
$user = auth()->user();
$this->listQuery = $user->store->serviceComplexes()->getQuery();
return response()->json([
'data' => StoreServiceComplexResource::collection($this->listQuery->get()),
]);
}
// StoreServiceComplexResource
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'base_service_ids' => $this->base_service_ids,
'more_service_ids' => $this->more_service_ids,
];
}
// Dump $this->listQuery->get()
array (
0 =>
array (
'id' => 3,
'name' => 'Complex 1',
'description' => 'Desc complex 1',
'base_service_ids' =>
array (
0 => 1,
1 => 2,
),
'more_service_ids' =>
array (
0 => 10,
),
),
)
How to get base services from another table(services) based on field "base_service_ids" and "more_service_ids" and add them to response ?
Is it possible to give this data also through Collection Resource ? For example
// StoreServiceComplexResource
public function toArray($request): array
{
return [
...
'service' => [] //StoreServiceResource::collection() ....
...
];
}

Sorting array of collections

I have an array storing 3 merged collections:
public function answer() {
$interview = Interview::find(1);
$videoQuestions = $interview->VideoQuestions()->get();
foreach ($videoQuestions as $vq) {
$vq->type = 'video';
}
$textQuestions = $interview->TextQuestions()->get();
foreach ($textQuestions as $tq) {
$tq->type = 'text';
}
$uploadQuestions = $interview->UploadQuestions()->get();
foreach ($uploadQuestions as $uq) {
$uq->type = 'upload';
}
$questions = collect($videoQuestions);
$questions = $questions->merge($textQuestions);
$questions = $questions->merge($uploadQuestions);
$questions->sortBy('order_position');
dd($questions);
}
The ->sortBy is not working as I assume it doesn't work on an array of collections.
This is what I have:
But I really just want it to be a merged collection not an array inside the collection.
Each VideoQuestion or TextQuestion has an order_position field that I would like to sort by.
Any help is appreciated!
First thing collection is a class containing an array of elements with special methods to filter sort, docs:
The Illuminate\Support\Collection class provides a fluent, convenient
wrapper for working with arrays of data.
The sortBy method returns a sorted collection (it does not apply to the item it has):
$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
/*
[
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150],
['name' => 'Desk', 'price' => 200],
]
*/
So you should have something like:
$questions = $questions->sortBy('order_position');
dd($questions);
This could be an alternative:
$interview = Interview::find(1)->with(['VideoQuestions',
'TextQuestions',
'UploadQuestions',
'Questions' => function($query){
$query->orderBy('order_position', 'asc');
}])->get();
Define the relationships and make a table Questions that holds an order_position that you can sort on instead of each table.

How to remove code repetition in Yii2 validators method `when`?

You have to read my previous problem to understand what i'm talking here about(Link to my problem). So it was solved.
But i have a lot of fields in my view that are always filled by current user's value. And it's code repetition when i doing next
[['new_email'], 'unique', 'targetAttribute' => 'email', 'targetClass' => '\common\models\User',
'when' => function ($model, $attribute) {
$this->isNewEmail = false;
if($model->$attribute != User::find()->where(['id' => Yii::$app->user->id])->one()->email) {
$this->isNewEmail = true;
}
return $this->isNewEmail;
},
'message' => 'This email can not be taken.'],
And this
[['first_name'], 'string', 'min' => 4, 'max' => 50,
'when' => function ($model, $attribute) {
$this->isNewFirstName = false;
if($model->$attribute != User::find()->where(['id' => Yii::$app->user->id])->one()->first_name) {
$this->isNewFirstName = true;
}
return $this->isNewFirstName;
},
],
And so on.
What can i do to remove this code repetition. Or is there are somewhere exists module or component for Yii2 just like for this situation like mine? Or is there are somewhere exists core validator for my issue? Or i doomed forever to do all of this code repetition?)
You can see that 2 when callable function have same structure. So you can write a simple function like that:
/**
* #param $model ActiveRecord
* #param $attribute string
* #return bool
*/
public function checkUniqueAttribute($model, $attribute)
{
return $model->$attribute != $model::find()->where(['id' => Yii::$app->user->id])->one()->$attribute;
}
And use it in your rules:
[
['new_email'], 'unique',
'targetAttribute' => 'email',
'targetClass' => '\common\models\User',
'message' => 'This email can not be taken.',
'when' => 'checkUniqueAttribute',
],
[
['first_name'], 'unique',
'targetAttribute' => 'first_name',
'targetClass' => '\common\models\User',
'message' => 'This first name can not be taken.',
'when' => 'checkUniqueAttribute',
],
[['first_name'], 'string', 'min' => 4, 'max' => 50,],
Hope it useful.
Goodluck and have fun!

Session::instance() and push array data to session array

for example i have Session::instance()->get('orders') which is an array of some arrays:
$first = array('id' = 1, 'name' => 'first', 'price' => 100);
$second = array('id' => 2, 'name' => 'second', 'price' => 200);
$_SESSION['orders'] = array($first, $second);
but if i use this
Session::instance()->set('orders', array(array('id' => 3, 'name' => 'third', 'price' => 300)));
this will erase first orders (id 1, id 2).
so how can i ADD but not ERASE data arrays to session array named 'orders'? array_push or something else?
Edit, didn't see your comment, it's perfect.
Self explanatory.
$session = Session::instance();
// Find existing data
$data = $session->get('orders');
// Add new array
$data[] = array('id' => 3, 'name' => 'new data', 'price' => 300);
// Resave it
$session->set('orders', $data);
As for me, I think that best way:
public function before() {
...
$this->variable = Session::instance()->get('key', array());
...
}
some code...
public function after() {
...
Session::instance()->set('key', $this->variable, Date::MINUTE);
...
}

Resources