How to get an array of 2-tuples from Laravel query builder? - laravel

Basically, I want to do this:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->map(function($c) { return [$c->id, $c->name]; })->toArray();
But without such a verbose map function. Isn't there a get-like method that will return flat numeric arrays instead of objects?
To be clear, the output should look like this:
array:4 [
0 => array:2 [
0 => 4
1 => "My Company"
]
1 => array:2 [
0 => 14
1 => "Example Company"
]
2 => array:2 [
0 => 13
1 => "Best Company"
]
3 => array:2 [
0 => 12
1 => "Super Co"
]
]
This is what I mean by 2-tuples: two-element numeric arrays. I know they don't exist in PHP, but the concept is the same; each entry has a fixed length.

There is no function out of the box to do this, but Laravel's Collection is Macroable, so you can add your own function to it to do this.
For example, somewhere in your code (like the boot() method of your AppServiceProvider), you can add a new method to the Collection:
// add toIndexedArray method to collections
\Illuminate\Support\Collection::macro('toIndexedArray', function() {
return array_map('array_values', $this->toArray());
});
Now you can use this new method like any other normal Collection method, so your final code would be:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->toIndexedArray();

If this is something you need a lot, you can change the PDO fetch mode in config/database.php to PDO::FETCH_NUM. I'm assuming it's possible to change it on-the-fly as well, but the code probably won't look that great. I don't think there's a Laravel command to change it for a single query, I'm afraid.
Otherwise, since the array is multidimensional, I'm afraid you do need to map over them somehow, and Laravel collections don't work nicely with e.g. ->map('array_values') which would have been a lot cleaner.
You could wrap it in array_map('array_values', $array) but that seems silly.
At least you could make it a little shorter if you change ->map() to ->transform() - then you don't need to tack on the ->toArray() at the end.

Use pluck():
$locals['companies'] = Company::orderBy('name')->pluck('id', 'name')->toArray();
If you need a list for Form::select this will work:
$locals['companies'] = Company::orderBy('name')->pluck('name', 'id');

You can omit the map function and just do:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->toArray();

Related

Laravel - what does the manual paginations 'option' query parameter do?

The manual pagination I found while googling works fine but I was just wondering what does the 'query' => $request->query() in the option parameter does?
$total = count($form_list);
$per_page = 10;
$current_page = $request->input('page') ?? 1;
$starting_point = ($current_page * $per_page) - $per_page;
$form_list = array_slice($form_list, $starting_point, $per_page, true);
$form_list = new Paginator($form_list, $total, $per_page, $current_page, [
'path' => $request->url(),
'query' => $request->query(),
]);
Calling ->query() without any parameters returns all the values from the query string as an associative array.
Suppose you have a query string like this:
https://example.com/path/to/page?name=ferret&color=purple
You can retrieve the value of name by doing something like so:
$request->query('name')
which returns ferret. You can also pass a second parameter for a default value so if you call:
$request->query('size', 'Medium')
which doesn't exist on the query string, you'll get 'Medium' instead of null.
If you omit all parameters, you'll receive an associative array that looks something like this:
query = [
'name' => 'ferret',
'color' => 'purple',
]
The options parameter is not needed by the pagination itself but for your dataset query. If you do not pass the query parameter, when you click one of the pagination urls, you'll get something like this:
https://example.com/path/to/page?page=2&per_page=5
Sometimes, this works fine and will give us something that we want but sometimes, we need those additional query string to get the correct dataset. We pass in all values from our query to get something like this:
https://example.com/path/to/page?page=2&per_page=5&name=ferret&color=purple
Which will filter your dataset for all those purple ferrets. As for the question if you need it, it's up for you to decide if that is essential for your code or if you can get away with just pagination.
Good luck! I hope this helps.

PHP array_map() always change my first index value to zero value

I have a controller in Laravel
This is my collection
$milestones = $this->getmilestones();
dump($milestones);
and the value is
array:3 [▼
0 => "["109"
1 => "110"
2 => "111"]"
]
And I tried this code based on the answer here.
So, I have code like this
array_unshift($milestones, $milestones[0]);
unset($milestones[0]);
dump($milestones);
and the value is (index was changed)
array:3 [▼
1 => "["109"
2 => "110"
3 => "111"]"
]
So, after unshifting the collections, I tried to use array_map to convert array of strings to array of integers.
$milestones = array_map('intval', $milestones);
dump($milestones);
But, I still got the same value. The first index returns 0 like this
array:3 [▼
1 => 0
2 => 110
3 => 111
]
What should I do?
Try this one
array_splice($milestone, 0, 1);
dump($milestone);
Ah, finally I got the results that I wanted. I try to remove square brackets and double quote. Because milestones is collection. So my code is
$milestones = str_replace(array('[', ']', '"'),'',$milestones);
Thank you all for your help
Use array_values this should re-index your array the way you need it:
$milestones = array_values($milestones);
If $milestones is a collection:
$milestones = $milestones->values();
The method values() will call array_values on your items defined in your collection instance.
Source: http://php.net/manual/en/function.array-values.php

get the first, the second, the third element of collection

I have a collection like that:
Collection {#750 ▼
#items: array:18 [▼
18 => User {#691 ▶}
19 => User {#696 ▶}
20 => User {#701 ▶}
]
}
Where 18, 19, 20 should vary
I tried to call with
$collection->get(0);
$collection->get(1);
$collection->get(2);
But obviously, it doesn't work
I found a workaround with shift, that return first element and remove it from the collection,
$el1 = $collection->shift();
$el2 = $collection->shift();
$el3 = $collection->shift();
But in this case, my original collection is destroyed.
Any idea how I should do it?
You can use slice() method:
$collection->slice(0, 3)
The slice method returns a slice of the collection starting at the given index. If you would like to limit the size of the returned slice, pass the desired size as the second argument.
You can use values() as:
$collection = $collection->values();
then you can use it as:
$collection->get(0);
$collection->get(1);
$collection->get(2);
You can either loop over them:
foreach ($collection as $element) {
// use $element
}
Or you can reset the keys to be sequentially indexed:
$collection = $collection->values();
$element1 = $collection->get(0);
$element2 = $collection->get(1);
$element3 = $collection->get(2);
There are many ways you can access thoes values. For example, you can get keys by calling:
$keys = $collection->keys()
Then call by the ordered keys you wanted:
if (isset($keys[0])) $collection->get($keys[0]);

Laravel - Access Config value using a wildcard?

Let's say that I have a config file called templates.php
It stores a list of types and items.
Now, I know that in order to obtain a specific row I could just do Config::get("list.type1.item1");
<?php
return [
'list' => [
'type1' => [
'item1' => [
//
],
'item2' => [
//
],
'item3' => [
//
],
],
]
];
But the thing is that 'type1' is dynamic, so I need a way to get all elements that matches item name.
Something like this (wildcards are not supported, so it doesn't work)
Config::get("list.*.item1");
What's the fastest (okay, that doesn't actually matter, I just want to know if it can be done at all) possible way to achieve this?
You only need to put your dynamic type on a variable let's says:
$type = 'type1';
config('services.' . $type . '.item1');

getting the value of array key in codeigniter

I have the following line in my controller:
$data['faq'] = $this->faqModel->get();
This data print the following using the print_r
Array
(
[faq] => Array
(
[0] => Array
(
[faqid] => 12
[catid] => 122
[question] => How this CMS works
[question_en] => How this CMS works
[answer] => How this CMS works?
[answer_en] => How this CMS works?
[sorder] => 2
[visible] => 1
)
[1] => Array
(
[faqid] => 8
[catid] => 121
[question] => How does the design cost?
[question_en] => How does the design cost?
[answer] => How does the design cost?
[answer_en] => How does the design cost?
[sorder] => 1
[visible] => 1
)
)
)
I want to use the value stored in the [catid] key, and I am trying to do something like:
$data['faq']['catid'] to get that value in the controller (I want to make another select with that value) But I am getting with this error message: Undefined index: catid
Anyone can help me to get the value of ['catid']???
Regards, Zoran
Its 3 dimensional array u look closely there is two elements in faq array. You must wrote something like this: $data['faq'][0]['catid'] or $data['faq'][1]['catid']
The way you are accessing the array is incorrect, you are missing the item index on the second level. The correct way to use it as you are doing would be to do
echo $data['faq'][0]['faqid']; //faqid of the first item
However, this will only show one faqid at a time, and it not so useful when you are iterating. So, a good way would be this way.
foreach($data['faq'] as $value) {
echo $value['faqid'];
}

Resources