Why my structure of collection is not expected (not as I need) - php

I have the following method of my cart class:
public function add($productId) {
$product = Product::where('id', $productId)->first();
if (!$product) {
return false;
}
if ($this->items->has($productId)) {
$this->items->$productId->qty++;
} else {
$this->items->push([$productId => [
'name' => $product->title,
'price' => $product->price,
'is_sale' => $product->is_sale,
'sale_price' => $product->sale_price,
'sale_percent' => $product->sale_percent,
'can_use_promocode' => $product->can_use_promocode,
'qty' => 1,
]
]);
}
$this->save();
return true;
}
But on dump($cart) in controller, I got this:
+items: Collection {#176 ▼
#items: array:1 [▼
0 => {#171 ▼
+"2": {#164 ▼
+"name": "101 роза"
+"price": 4999
+"is_sale": 0
+"sale_price": null
+"sale_percent": null
+"can_use_promocode": 1
+"qty": 1
}
}
]
}
But I need to:
+items: Collection {#176 ▼
#items: array:1 [▼
2 => {
+"name": "101 роза"
+"price": 4999
+"is_sale": 0
+"sale_price": null
+"sale_percent": null
+"can_use_promocode": 1
+"qty": 1
}
]
}
In this case, I thought that $this->items->push([$productId => ...] will push the key => value pair to collection, but collection creates its own pair, and my pair goes into collection pair. (idk how to describe it correctly, but I think you understand me :) )

Use the put() method instead:
->put($key, $data)
The put method sets the given key and value in the collection

Related

Convert collection to key value collection

I have the following collection:
$configuration = DB::table('configuration')->get();
Illuminate\Support\Collection {#562 ▼
#items: array:7 [▼
0 => {#1447 ▼
+"configuration_name": "assign_device_email_addresses"
+"configuration_value": "mobiles#example.com|accountspayable#example.com"
}
1 => {#1357 ▼
+"configuration_name": "helpdesk_platform_url"
+"configuration_value": "https://clouddesk.com/app/itdesk/ui/requests/{helpdeskurl}/details"
}
2 => {#1446 ▼
+"configuration_name": "mail_encryption"
+"configuration_value": "tls"
}
3 => {#563 ▼
+"configuration_name": "mail_host"
+"configuration_value": "exampleserver.example.com"
}
4 => {#1292 ▼
+"configuration_name": "mail_password"
+"configuration_value": "encrypted_password"
}
5 => {#1291 ▼
+"configuration_name": "mail_port"
+"configuration_value": "465"
}
6 => {#885 ▼
+"configuration_name": "mail_username"
+"configuration_value": "mobiles"
}
]
}
With this structure I can only access each item via the following statements:
$configuration[0]->configuration_name
$configuration[0]->configuration_value
$configuration[1]->configuration_name
$configuration[1]->configuration_value
etc.
I want to be able to access it via:
$configuration->assign_device_email returning "mobiles#example.com|accountspayable#example.com".
$configuration->mail_host returning "exampleserver.example.com".
etc.
How can I can convert this collection so that I can access each property value via it's configuration_name?
I have tried the below which got me closer, but I still can't access it via statements like: $configuration->mail_port etc.
$configuration2 = DB::table('configuration')->get()
->mapWithKeys(function($configuration2){
return [$configuration2->configuration_name => $configuration2->configuration_value];
});
I think this fails as the above statement still returns an array:
Illuminate\Support\Collection {#1500 ▼
#items: array:7 [▼
"assign_device_email_addresses" => "mobiles#example.com|accountspayable#example.com"
"helpdesk_platform_url" => "https://clouddesk.com/app/itdesk/ui/requests/{helpdeskurl}/details"
"mail_encryption" => "tls"
"mail_host" => "exampleserver.example.com"
"mail_password" => "encrypted_password"
"mail_port" => "465"
"mail_username" => "mobiles"
]
}
Anyone have any ideas? I feel like I am getting closer with it, but collections confuse me a bit.
I think I am essentially after something like this:
Illuminate\Support\Collection {#1507 ▼
+"assign_device_email_addresses" : "mobiles#example.com"
+"helpdesk_platform_url" : "https://cloudesk.com/app/itdesk/ui/requests/{helpdeskurl}/details"
+"mail_encryption" : "tls"
+"mail_host" : "emailhost#example.com"
+"mail_password" : "encrypted_password"
+"mail_port" : "465"
+"mail_username" : "mobiles"
}
You can Arr helper to map in key value:
$configuration = DB::table('configuration')->get();
$configuration = Arr::pluck($configuration, 'configuration_value','configuration_name');
also, add below line to import class:
use Illuminate\Support\Arr;

Get value by column name value

Ny array looks something like this:
Illuminate\Database\Eloquent\Collection {#2052 ▼
#items: array:3 [▼
0 => App\Models\NewsMeta {#2089 ▶}
1 => App\Models\NewsMeta {#2090 ▶}
2 => App\Models\NewsMeta {#2091 ▶}
]
}
If I open up the array 2:
#original: array:7 [▼
"id" => 17
"post_id" => 240231
"news_tag_id" => 5
"meta_name" => "_thumbnail_id"
"meta_value" => "240232"
"created_at" => "2020-08-06 22:34:06"
"updated_at" => "2020-08-06 22:34:06"
]
Now, I looking to get value "240232" given that I've 240231.
How do I search inside array of the object?
Something like: where post_id is 240231 get ts meta_value.
FYI: It's not eloquent or DB query.
Something like this should work:
$postId = 240231;
$metaValue = null;
foreach ($collection as $model) {
if ($model->post_id == $postId) {
$metaValue = $model->meta_value;
break;
}
}
echo $metaValue;
You could also use the collection's seach method:
$postId = 240231;
$metaValue = $collection->search(static function($model, $key) use($postId) {
if ($model->post_id == $postId) {
return $model->meta_value;
}
});
echo $metaValue;
You can use the collection firstWhere() method
$collection->firstWhere('post_id', '240231')['meta_value'] ?? null;
With the data you provided this should return 240232. In a dataset where there is no post_id = 240231 it would return null.

Laravel working with nested collection delete nested branch

unable to delete all nested branches where "product" => null
Have a query
$cartWhere['user_id'] = $user_id;
$cartWhere['site_id'] =$currentSite->id;
$item = Cart::select('product_id','quantity')->with(['product' => function($product) use ($search){
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
},'product.manufacturer:id,name'])
->where($cartWhere)->get();
then I receive collection that has all filtered carts but some of these carts have a relation with product => null
1 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 1
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => App\Models\Product {#785 ▶}
]
}
2 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 2
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => null
]
}
sorry for my English
You can filter them from the results using the collections filter() method
$item = Cart::select('product_id','quantity')
->with(['product' => function($product) use ($search) {
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
}, 'product.manufacturer:id,name'])
->where($cartWhere)
->get()
->filter(function ($cart) {
return $cart->product !== null;
});
Along with with you should use whereHas. So the result will not include any relation with null value. So this way you can also avoid the extra filter method used.

Laravel Object of class stdClass could not be converted to string. Still object when using toArray();

I have a table that I want to export via excel. I use the method toArray(); and still I get the result as object. Here is my sample code
$items = \DB::table('users')
->join('finances', 'users.id','=','finances.user_id')
->join('schoolyears', 'users.school_id','=','schoolyears.school_id')
->select('users.name','users.phone','users.section_id', 'users.student_school_id','finances.amount','finances.description','schoolyears.name as syear','finances.date')
->where('finances.date', '=' ,(\DB::raw("(select max(`date`) from finances f where finances.user_id=f.user_id)")))
->where('users.role','=','4' )
->where('users.school_id','=', $sid)
->get()->toArray();
// dd($items);
} else {
return redirect('home')->with('error', 'Invalid access');
}
\Excel::create($this->page_title . 's', function ($excel) use ($items) {
$excel->sheet($this->page_title . 's', function ($sheet) use ($items) {
$sheet->fromArray($items);
});
The result I get when i dd($items)
array:2 [▼
0 => {#558 ▼
+"name": "Annamarie Morar"
+"phone": "(0997) 212-7919"
+"section_id": null
+"student_school_id": "50"
+"amount": "500"
+"description": "New Pays"
+"syear": "SY-2019-2020"
+"date": "2019-11-14"
}
1 => {#561 ▶}
]
What i want is like this so that i can export it as an excel file
array:9 [▼
0 => array:10 [▼
"FirstName" => "Madelynn"
"LastName" => "Stokes"
"Gender" => "female"
"Birthday" => "2013-10-09"
"Address" => "78A/40 Goodwin Meadow, Poblacion, Iloilo City 1333 Nueva Ecija"
"PhoneNo" => "+63 (971) 659-8143"
"Parent" => "Deondre Stokes"
"SchoolID" => "521"
"RFID" => "173"
"Section" => null
]
1 => array:10 [▶]
2 => array:10 [▶]
3 => array:10 [▶]
4 => array:10 [▶]
5 => array:10 [▶]
6 => array:10 [▶]
7 => array:10 [▶]
8 => array:10 [▶]
]
You could convert each object to an array by transforming the Collection then turning the Collection into an array if you had to:
$items = DB::table(...)->.....->get()->transform(function ($item) {
return (array) $item;
})->toArray();
Laravel 6.x Docs - Collections - Methods - transform

Save data in db from excel in laravel

I need to import excel data in db. but is giving me tough time.
here is my controller function
$path = Input::file('import_file')->getRealPath();
$data = \Excel::load($path)->get();
if($data->count()){
foreach ($data as $key => $value) {
$arr[] = ['product_id' => $value->price, 'details' =>
$value->stock];
}
if(!empty($arr)){
\DB::table('stock')->insert($arr);
dd('Insert Record successfully.');
}
}
where price and stock is fields in excel.
below is the error
Property [price] does not exist on this collection instance.
here is dd() of my controller function when i am trying to save excel data in db.
SheetCollection {#375 ▼
#title: ""
#items: array:3 [▼
0 => RowCollection {#498 ▼
#heading: array:2 [▼
0 => "stock"
1 => "price"
]
#title: "Sheet1"
#items: array:3 [▼
0 => CellCollection {#462 ▼
#title: null
#items: array:2 [▼
"stock" => 2.0
"price" => 3.0
]
}
1 => CellCollection {#481 ▼
#title: null
#items: array:2 [▼
"stock" => 3.0
"price" => 2.0
]
}
2 => CellCollection {#480 ▼
#title: null
#items: array:2 [▶]
}
]
}
1 => RowCollection {#533 ▶}
I'll paste my import function here, modify them for your needs.
My excel template has only 1 sheet and the first row contains the field names.
// Retrieve file
$file = $request->file('file');
$ext = $file->getClientOriginalExtension();
// Just my helper method to create filenames
$filename = Helper::create_filename($ext);
// Move file
$path ="uploads/import";
$file->move($path, $filename);
Excel::selectSheetsByIndex(0)->load("{path}/{$filename}", function($reader) {
$sheet = $reader->all();
foreach ($sheet as $i => $row) {
$data = $row->toArray(); // Utilize this data to fill your model
}
});
CHANGE EXCEL SHEET COLUMN NAME LIKE THAT
price stock
100 400
200 15
12 167

Categories