I have pivot table vacancy_tag. I tried different options (value,select, lists and etc), but didn't go further than that. My request:
Vacancy::where('id',1)->with(['tags' => function ($q){
$q->select('tags.id')->pluck('id');
}])->get()->toArray();
return this:
"id" => 1,
"title" => "pm",
"tags" => array:2 [▼
0 => array:1 [▼
"id" => 1
]
1 => array:1 [▼
"id" => 2
]
but need this:
"id" => 1,
"title" => "pm",
"tags" => [
1,
2
]
I would like to receive the data result in a query, without using a methods transformation of the collection, if possible.
PS: I slightly corrected the example, need to display all fields of the vacancy + an array of tags.
I'm trying to increment during the map method, however my variable doesn't seem to save the new value. My code:
$position = 0;
$statement = $medias->map(fn(string $media) => [
'position' => ++$position
])->values();
My expected result would be:
#items: array:4 [
0 => array:4 [
"position" => 1
]
1 => array:4 [
"position" => 2
]
2 => array:4 [
"position" => 3
]
3 => array:4 [
"position" => 4
]
]
However it's actually
#items: array:4 [
0 => array:4 [
"position" => 1
]
1 => array:4 [
"position" => 1
]
2 => array:4 [
"position" => 1
]
3 => array:4 [
"position" => 1
]
]
Is incrementing inside map not possible or am I doing something wrong here?
The problem here is that you expect $position variable to be passed by reference, which is not the case.
Arrow functions use by-value variable binding. This is roughly equivalent to performing a use($x) for every variable $x used inside the arrow function. A by-value binding means that it is not possible to modify any values from the outer scope. Anonymous functions can be used instead for by-ref bindings. PHP Manual - Arrow Functions
A workaround for you could be like this:
// Either
$posObj = new \stdClass();
$posObj->position = 0;
// or
$posObj = (object)array('position' => 0);
$statement = $medias->map(fn(string $media) => [
'position' => ++$posObj->position
])->values();
I have this collection
Collection {#611
#items: array:1 [
0 => Payeur {#605
#guarded: array:1 [
0 => "id"
]
#attributes: array:11 [
"id" => 1
"prenom_payeur" => "aymen"
"nom_payeur" => "larabi"
"mobile_payeur" => "non"
"telephone" => 230493212
"observation" => "jeflolena"
"adresse" => "jdjfnrll"
"event_id" => 1
"adherent_id" => 3
"created_at" => "2019-12-22 14:57:43"
"updated_at" => "2019-12-22 14:57:43"
]
}
]
}
and I want to get the nom_payeur attributes from this collection. I did this many times before and I don't know why I get this error:
(Property [nom_payeur] does not exist on this collection instance.)
I'm trying to get the attributes by doing this: $payeur->nom_payeur , $payeur is the collection.
Please help.
try this hope its help
you have the collection and you try to access this property that is not possible beacuse in collection you can n't access element or attribute directly you have to use the array of index for this to access the poperty.
$payeur -> is collection this is incorrect way to access the property.
try this to access the attribute property.
$payeur[0]->nom_payeur
I am doing a request to an API and for each request I get an array with the BrowseNodes back. Inside this array I get this result:
array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "2502033031"
"Name" => "OBD-II Diagnosewerkzeuge"
"Ancestors" => array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "5142250031"
"Name" => "Motorwerkzeuge & Zubehör"
"Ancestors" => array:1 [
"BrowseNode" => array:3 [
"BrowseNodeId" => "2502064031"
"Name" => "Werkzeuge"
"Ancestors" => array:1 [
"BrowseNode" => array:4 [
"BrowseNodeId" => "79899031"
"Name" => "Kategorien"
"IsCategoryRoot" => "1"
"Ancestors" => array:1 [
"BrowseNode" => array:2 [
"BrowseNodeId" => "78191031"
"Name" => "Auto & Motorrad"
]
]
]
]
]
]
]
]
]
]
If this would be a fixed array which always had this length it would be easy for me to get the last BrowseNode Array and the value with the key "Name". In this case it would be the this one "Name" => "Auto & Motorrad".
However, because a category can have one or more nested arrays, it is not static...
That means I have to find a solution to always get the most nested array and from this one the name to get the category. Because it is dynamic data, I don't know how to solve that. I just know I always have to get the BrowseNode and then inside the BrowseNode array. I have to get the Ancestors and inside this Ancestors again. I have to get the BrowseNode array until I arrived at the last BrowseNode array and the get the name.
So, I have to iterate through my array until the BrowseNode array doesn't have an Ancestors array anymore and the get the name of this BrowseNode array.
Do you guys have any idea on how to do this?
I guess you can use recursion to achieve that.
On each object, search for Ancestors, if not found return the name, else do so again on the Ancestors.
Consider the following code:
$arr = array("BrowseNode" => array("BrowseNodeId" => "1", "Ancestors" => array("BrowseNode" => array("BrowseNodeId" => "2", "Ancestors" => array("BrowseNode" => array("BrowseNodeId" => "3"))))));
function getLastName($elem) {
$elem = $elem["BrowseNode"];
if (!array_key_exists("Ancestors", $elem))
return $elem['BrowseNodeId'];
else return getLastName($elem["Ancestors"]);
}
echo getLastName($arr);
Notice that this code return id instead of your Name - small modification I leave to you...
There might be a more "correct" way of doing this but since I'm writing this on my phone on a plane, you'll have to forgive my not being able to proof check my answer. But you could do a recursive function, like...
function recurseArray($browseNode)
{
if(isset($browseNode["Ancestors"])) {
recurseArray($browseNode["Ancestors"]["browseNode"])
} else {
// Do whatever you want with the last iteration
}
}
Hope that makes sense!
I'm having some issues with the Laravel Collection class.
What I'm trying to do:
I have a multisite solution in which a site has "facilitators". Sometimes one facilitator appears on multiple sites, and not just one.
I want to list all the facilitators and the website they're on the main page, but I don't want multiple users.
So what I currently do is:
Get the Facilitators.
Use Collection to collect the facilitators and use unique('name').
This gives me unique facilitators, but only picks the first one it detects and then deletes the other ones.
So lets say I have this collection:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => "Example"
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
2 => array:2 [
"name" => "John"
"site" => "Another"
]
]
}
With unique() I would get:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => "Example"
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
]
}
And this is what I want to get:
Collection {
#items: array:3 [
0 => array:2 [
"name" => "John"
"site" => ["Example", "Another"]
]
1 => array:2 [
"name" => "Martin"
"site" => "Another"
]
]
}
Does anyone have an idea how I could accomplish this with Laravel's collection class?
When stuck with collections always remember reduce is a powerful tool in your arsenal.
Building on Sam's answer which I couldn't get to work, I think using reduce alongside groupBy should work...
$sites = collect([
["name" => "John", "site" => "Example"],
["name" => "Martin", "site" => "Another"],
["name" => "John", "site" => "Another"],
]);
$sites->groupBy('name')->reduce(function ($result, $item) {
$result[] = [
'name' => $item->first()['name'],
'sites' => $item->pluck('site')->toArray()
];
return $result;
}, collect([]))->toArray();
And from the console...
λ php artisan tinker
Psy Shell v0.8.2 (PHP 7.0.10 ÔÇö cli) by Justin Hileman
>>> $sites = collect([
... ["name" => "John", "site" => "Example"],
... ["name" => "Martin", "site" => "Another"],
... ["name" => "John", "site" => "Another"],
... ]);
=> Illuminate\Support\Collection {#698
all: [
[
"name" => "John",
"site" => "Example",
],
[
"name" => "Martin",
"site" => "Another",
],
[
"name" => "John",
"site" => "Another",
],
],
}
>>> $sites->groupBy('name')->reduce(function ($result, $item) {
... $result[] = ['name' => $item->first()['name'], 'sites' => $item->pluck('site')->toArray()];
...
... return $result;
... }, collect([]))->toArray();
=> [
[
"name" => "John",
"sites" => [
"Example",
"Another",
],
],
[
"name" => "Martin",
"sites" => [
"Another",
],
],
]
One thing to note is that you specified in your question that the sites should return a single string if there's only one site and an array if there's many.The above solution does not provide this! I think this is inconsistent and you should always return an array for the sites key, even if it only has one value as it will make it more difficult to read and manipulate later on.
However, if this is something important, you could instead check if there are many sites when using pluck to set an array and if not you could set it as a single string, like this:
$sites->groupBy('name')->reduce(function ($result, $item) {
$result[] = [
'name' => $item->first()['name'],
'sites' => $item->pluck('site')->count() > 1 ? $item->pluck('site') : $item->first()['site']
];
return $result;
}, collect([]))->toArray();
which would produce...
[
[
"name" => "John",
"sites" => [
"Example",
"Another",
],
],
[
"name" => "Martin",
"sites" => "Another",
],
]
you can do it by chaining to get exactly what you want, assuming $collection is the main collection
$collection->groupBy('name')->map(function($facilitators) {
return ['name' => $facilitators->first()['name'], 'site' => $facilitators->pluck('site')->toArray()];
})->values()->toArray();
first we group by name so it will give 2 dimensional array inside collection, then iterate to that and name will be common so get it from first element, then from all the element pluck site and convert it to array, using flatMap will make it single level nested.