I have an array, I want to order that array by "is_available" key, (true first)
I'm using laravel 8 and a livewire component
0 => array:12 [▼
"id" => 1
"name" => "치킨 ~The Chicken~"
"is_available" => true
"nearest_customer_distance" => 4905.4423678942
"customers" => array:26 [▶]
]
1 => array:12 [▼
"id" => 2
"name" => "混ぜるな危険"
"is_available" => false
"customers" => array:10 [▶]
]
2 => array:12 [▼
"id" => 3
"name" => "Oh! Bánh mì"
"is_available" => true
"customers" => array:8 [▶]
]
3 => array:12 [▼
"id" => 5
"name" => "CHIJIMI DEVIL"
"is_available" => false
"customers" => array:44 [▶]
]
]
I'm trying this
$newFranchiseList = $this->getFranchiseListActualPage();
$finalFranchiseList = array_merge($this->franchiseList, $newFranchiseList);
$finalFranchiseList = collect($finalFranchiseList)->sortBy('is_available')->reverse();
$this->franchiseList = $finalFranchiseList->toArray();
but I get the order by ID in my view, this is my view
#forelse($franchiseList as $franchise)
#if($franchise['is_available'])
{{$franchise['name']}}
IS AVAILABLE
#else
{{$franchise['name']}}
NOT AVAILABLE
#endif
#empty
#endforelse
if I do a dump($this->franchiseList) the list is shown with the order of is_available!
note: $this->franchiseList is never used in the component, the only line to be used is the last one, if I don't use this line, the list is empty
component data collection process
first, in javascript call a livewire listener
window.livewire.emit('franchises:selectedCoords', JSON.stringify(selectedCoords));
then that is received by the component
public $selectedLatitude,
$selectedLongitude,
$perPage = 20,
$franchiseList = [],
$page = 1,
$totalFranchises = 0,
$isLoaded = false;
protected $listeners = [
'franchises:selectedCoords' => 'getCoords'
];
public function render()
{
return view('livewire.franchise-list');
}
public function getCoords($selectedCoords)
{
if ($selectedCoords) {
if (!empty($this->franchiseList)) {
$this->clearList();
}
$this->selectedLatitude = json_decode($selectedCoords, true)['lat'];
$this->selectedLongitude = json_decode($selectedCoords, true)['lng'];
}
$this->getFranchiseList();
}
public function getFranchiseList()
{
if ($this->selectedLatitude && $this->selectedLongitude) {
if (!$this->allFranchisesAreLoaded())
{
$newFranchiseList = $this->getFranchiseListActualPage();
$finalFranchiseList = array_merge($this->franchiseList, $newFranchiseList);
$this->franchiseList = collect($finalFranchiseList)->sortBy('is_available')->reverse()->toArray();
}
$this->isLoaded = true;
}
}
remember that $this->franchiseList is never overwritten, that is, it is only used once, in the line $this->franchiseList = collect($finalFranchiseList)->sortBy('is_available')->reverse()->toArray (); and if it is not done, it ends up being an empty array, so there is no other $this->franchiseList with the order shown by the blade view
Livewire will on each request serialize the public properties, so that it can be sent to the frontend and stored in JavaScript.
Now here's the kicker: JavaScript will do its own internal sorting on objects, which you can't prevent. So to work around that, you have to re-key your array after you sort it, so that the keys are now in ascending order of what you sorted it to.
Basically, all you need to do before you call ->toArray(), is to call ->values() on it, thereby grabbing the values in the order they were, and PHP will assign it new keys starting from 0.
$this->franchiseList = collect($finalFranchiseList)->sortBy('is_available')->reverse()->values()->toArray();
For example, a object like this in JavaScript,
{
1: 'foo',
0: 'bar',
}
Will be internally sorted by JavaScript like this
{
0: 'bar',
1: 'foo',
}
And you can't change that. That's why you need to re-key it.
Related
Good day I need help on how to get the specific value on an array.I want to get the qty value and id value. The array output is like this
{"items":{"2":{"qty":1,"price":300,"item":{"id":2,"title":"LOTR","author":"James Cameron","price":300,"quantity":150,"created_at":"2020-08-24T13:35:36.000000Z","updated_at":"2020-08-24T13:38:52.000000Z"}}},"totalQty":1,"totalPrice":300}
As for the code
public function postCheckout(Request $request){
if (!Session::has('cart')){
return view('shop.shoppingcart');
}
$oldCart = Session::get('cart');
$cart = new Cart($oldCart);
$order = new Order();
$order->cart = json_encode($cart);
$order->address = $request->input('address');
$order->name = $request->input('name');
Auth::user()->orders()->save($order);
Session::forget('cart');
}
public function findvalarray(){
$order = Order::orderBy('created_at', 'desc')->limit(1)->get();
return view("test", ['order' => $order]);
}
The one with $order->cart = json_encode($cart) is the part where all the products that have been added to cart.
While the findvalarray is the one to find the cart value in the database dont mind the limit cause I need it for selection of a specific date.
And this is the blade view
#foreach($order as $item)
{{$item['cart']}}
#endforeach
Appreaciate the reply thank you
Your $order->cart is in JSON format you need to json_decode() your cart to convert it to array|object so you can access it's value, in your blade you can do
#foreach($order as $item)
{{ dd(json_decode($item['cart'])) }}
#endforeach
The result will be an object that you can access like json_decode($item['cart'])->totalQty
{#260 ▼
+"items": {#258 ▼
+"2": {#257 ▼
+"qty": 1
+"price": 300
+"item": {#251 ▼
+"id": 2
+"title": "LOTR"
+"author": "James Cameron"
+"price": 300
+"quantity": 150
+"created_at": "2020-08-24T13:35:36.000000Z"
+"updated_at": "2020-08-24T13:38:52.000000Z"
}
}
}
+"totalQty": 1
+"totalPrice": 300
}
If you want it as array you can do dd(json_decode($item['cart'], true)) this will give you
array:3 [▼
"items" => array:1 [▼
2 => array:3 [▼
"qty" => 1
"price" => 300
"item" => array:7 [▼
"id" => 2
"title" => "LOTR"
"author" => "James Cameron"
"price" => 300
"quantity" => 150
"created_at" => "2020-08-24T13:35:36.000000Z"
"updated_at" => "2020-08-24T13:38:52.000000Z"
]
]
]
"totalQty" => 1
"totalPrice" => 300
]
And you can access it like json_decode($item['cart'])['totalQty']
I am working with an array in this form:
"car_documents_attributes"=>{
"1562523330183"=>{
"id"=>"", "filename"=>"tyYYqHeqSFOnqLHEz5lO_rc_tispor12756_6wldwu.pdf", "document_type"=>"contract"
},
"1562523353208"=>{
"id"=>"", "filename"=>"a9P8TyECRiKbI2YdRVZy_rc_tispor12756_bbtzdz.pdf", "document_type"=>"request"
},
"1562523353496"=>{
"id"=>"", "filename"=>"WCM5FHOfSw6yNSUrfPPm_rc_tispor12756_dqu9r2.pdf", "document_type"=>"notes"
},
...
}
I need to find out if in this array is an item where document_type=contract (there can be none, one or multiple ones).
The way I do it is looping through the array item by item, which can be slow if there are tens of items.
Is there a better and faster way to simply check if in the array is an item with document_type = contract?
That's a hash containing more hashes. What you can do is to access to car_documents_attributes, iterate over those hash values and check if any document_type is "contract":
data = {
"car_documents_attributes" => {
"1562523330183" => { "id" => "", "filename" => "tyYYqHeqSFOnqLHEz5lO_rc_tispor12756_6wldwu.pdf", "document_type" => "contract"},
"1562523353208" => { "id" => "", "filename" => "a9P8TyECRiKbI2YdRVZy_rc_tispor12756_bbtzdz.pdf", "document_type" => "request" },
"1562523353496" => { "id" => "", "filename" => "WCM5FHOfSw6yNSUrfPPm_rc_tispor12756_dqu9r2.pdf", "document_type" => "notes" }
}
}
p data['car_documents_attributes'].any? { |_, doc| doc['document_type'] == 'contract' }
# true
Didn't know it was data coming from the params. If so, you do need to permit what's being received or convert the params to an unsafe hash.
Also, you can try using fetch instead [] when trying to get car_documents_attributes, because if that key isn't in data, it'll throw nil, which would throw a NoMethodError:
data.fetch('car_documents_attributes', []).any? { |_, doc| doc['document_type'] == 'contract' }
I have to following array from inputs
array:9 [
"columns" => "4"
"device_id" => array:4 [
0 => "1"
1 => "2"
2 => "3"
3 => "4"
]
"hub_id" => "11"
"usage" => array:4 [
0 => "1"
1 => "2"
2 => "3"
3 => "4"
]
....
In my foreach loop i get back only one value not all
$devices = $request->all();
foreach ($devices["device_id"] as $device) {
dd($device);
}
This will return only 1 one value not all.
I have problem displaying all the value and saving them to database.
Witch would be the fast and the right way ?
The array and the behaviour you are getting is normal.
$devices = $request->all();
foreach ($devices["device_id"] as $device) {
dd($device);
}
This will indeed return 1, because your cursor is at the first value of $devices["device_id"]. If you wait for the next iteration, it'll be 2, then 3 and 4.
Remember you can also write your foreach this way:
foreach ($devices["device_id"] as $index => $device)
, where $index will be equal to the index related to the current value.
If you want all values, you can just simply dd($devices["device_id"]), it'll return you this array:
array:4 [
0 => "1"
1 => "2"
2 => "3"
3 => "4"
]
You do not save array in a database. Databases are not supposed to save multidimensional structures, since they do not support them.
You must convert your array into a format that the database is able to save, for example JSON or PHP serialize. It is actually very common to save data in this way if you do not need to search it easily at a later time.
Nevertheless, I would use a setter in your model to achieve this:
public function setAttributeNameAttribute($values)
{
$this->attributes['attribute_name'] = json_encode($values);
}
public function getAttributeNameAttribute($values)
{
return json_decode($values);
}
I have a conditional query that works in my index controller that should return eloquent relationships but does not always return an accessible array index:
$customers = Customer::with('orders', 'regions')->orderBy('created_at', 'desc')->whereHas('regions', function($query)
{
$user_id = Auth::user()->id;
$current_user = User::with('roles')->where('id', '=', $user_id)->latest()->first();
$role_name = $current_user->roles[0]->name;
if($role_name == 'admin_master'){$query->whereIn('region', array(11, 7));}
}
)->get();
The problem is the related array is not always accessible eg order[1] and displays oddly when I dd($customers);
#relations: array:5 [▼
"orders" => Collection {#442 ▼
#items: array:2 [▼
0 => Order {#446 ▶}
1 => Order {#447 …25}
]
}
For future users, the get method gets the results as a collection. You can chain the toArray() method on it to convert it into an array.
So it will be something like $query->get()->toArray()
Is there a way I can pick a value in hash of array, and reformat it to be only hash?
Is there any method I can do with it?
Example
[
{
"qset_id" => 1,
"name" => "New1"
},
{
"qset_id" => 2,
"name" => "New2"
}
]
Result
{
1 => {
"name" => "New1"
},
2 => {
"name" => "New2"
}
}
You can basically do arbitary manipulation using reduce function on array or hashes, for example this will get your result
array.reduce({}) do |result, item|
result[item["qset_id"]] = { "name" => item["name"] }
result
end
You can do the same thing with each.with_object do:
array.each.with_object({}) do |item, result|
result[item["qset_id"]] = { "name" => item["name"] }
end
it's basically the same thing but you don't have to make each iteration return the result (called a 'memo object').
You could iterate over the first hash and map it into a second hash:
h1.map{|h| {h['qset_id'] => {'name' => h['name']}} }
# => [{1=>{"name"=>"New1"}}, {2=>{"name"=>"New2"}}]
... but that would return an array. You could pull the elements into a second hash like this:
h2 = {}
h1.each do |h|
h2[h['qset_id']] = {'name' => h['name']}
end
>> h2
=> {1=>{"name"=>"New1"}, 2=>{"name"=>"New2"}}