Related
I need to return an array only with the permissions name column but cant make it work with a ->pluck()
class User
{
public function roleTeams()
{
return $this->hasMany(RoleTeam::class);
}
}
class RoleTeams
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}
class Role
{
public function permissions()
{
return $this->belongsToMany(Permission::class);
}
}
This is the last code i try based on similar answers i found.
$permissions = $user->roleTeams()->with('roles.permissions')->pluck('roles.*.permissions.*.name')->all();
The expected result is
[
'edit_user',
'delete_user',
...
]
So, I tried to simulate your situation. My code is:
$arr = [
'id' => 1,
'name' => 'User 1',
'roles' => [
[
'id' => 2,
'name' => 'Admin',
'permissions' => [
[
'id' => 8,
'name' => 'edit_user',
'type' => 'editor',
],
[
'id' => 9,
'name' => 'delete_user',
'type' => 'deleter',
],
],
],
[
'id' => 3,
'name' => 'Manager',
'permissions' => [
[
'id' => 6,
'name' => 'do_smth1_with_user',
'type' => 'smth1',
],
[
'id' => 7,
'name' => 'do_smth2_with_user',
'type' => 'smth2',
],
],
],
],
];
$collection = collect([$arr]);
And have interested results. If use pluck() method like in your answer:
dd($collection->pluck('roles.*.permissions.*.name'));
The result would be like this:
Collection {#322 ▼
#items: array:1 [▼
0 => array:4 [▼
0 => "edit_user"
1 => "delete_user"
2 => "do_smth1_with_user"
3 => "do_smth2_with_user"
]
]
}
But if I use pluck() with collapse() method it looks like you want:
dd($collection->pluck('roles')->collapse()->pluck('permissions')->collapse()->pluck('name'));
And result is:
Collection {#322 ▼
#items: array:4 [▼
0 => "edit_user"
1 => "delete_user"
2 => "do_smth1_with_user"
3 => "do_smth2_with_user"
]
}
To be honest, I don't know why it works like it works, but try to use it with collapse() method and let me know if it helps your or not.
Hope my answer helps you to slove your problem.
I've an array
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
A dataprovider :
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
And the Gridview :
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'value' => 'email',
]
]
]);
As is, the code make me View the array in a grid, and the possibility to sort it when clicking on columns. That's ok.
But how to do to use filtering ?
I tried with the following :
$searchModel = ['id' => null, 'name' => '', 'email' => ''];
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="da" type="text">',
'value' => 'email',
]
]
]);
But it's not working.
Does I have to filter myself the object depending on the $get value ?
My solution with full code :
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
function filter($item) {
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
if (strlen($mailfilter) > 0) {
if (strpos($item['email'], $mailfilter) != false) {
return true;
} else {
return false;
}
} else {
return true;
}
}
$filteredresultData = array_filter($resultData, 'filter');
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
$namefilter = Yii::$app->request->getQueryParam('filtername', '');
$searchModel = ['id' => null, 'name' => $namefilter, 'email' => $mailfilter];
$dataProvider = new \yii\data\ArrayDataProvider([
'key'=>'id',
'allModels' => $filteredresultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="'. $searchModel['email'] .'" type="text">',
'value' => 'email',
]
]
]);
On the previous soultion. I created a loop to make the filters, columns and searchModel.
$items = [
array("id" => 1, "name" => "Cyrus", "email" => "risus#consequatdolorvitae.org"),
array("id" => 2, "name" => "Justin", "email" => "ac.facilisis.facilisis#at.ca"),
array("id" => 3, "name" => "Mason", "email" => "in.cursus.et#arcuacorci.ca"),
array("id" => 4, "name" => "Fulton", "email" => "a#faucibusorciluctus.edu"),
array("id" => 5, "name" => "Neville", "email" => "eleifend#consequatlectus.com"),
array("id" => 6, "name" => "Jasper", "email" => "lectus.justo#miAliquam.com"),
array("id" => 7, "name" => "Neville", "email" => "Morbi.non.sapien#dapibusquam.org"),
array("id" => 8, "name" => "Neville", "email" => "condimentum.eget#egestas.edu"),
array("id" => 9, "name" => "Ronan", "email" => "orci.adipiscing#interdumligulaeu.com"),
array("id" => 10, "name" => "Raphael", "email" => "nec.tempus#commodohendrerit.co.uk"),
];
$searchAttributes = ['id', 'name', 'email'];
$searchModel = [];
$searchColumns = [];
foreach ($searchAttributes as $searchAttribute) {
$filterName = 'filter' . $searchAttribute;
$filterValue = Yii::$app->request->getQueryParam($filterName, '');
$searchModel[$searchAttribute] = $filterValue;
$searchColumns[] = [
'attribute' => $searchAttribute,
'filter' => '<input class="form-control" name="' . $filterName . '" value="' . $filterValue . '" type="text">',
'value' => $searchAttribute,
];
$items = array_filter($items, function($item) use (&$filterValue, &$searchAttribute) {
return strlen($filterValue) > 0 ? stripos('/^' . strtolower($item[$searchAttribute]) . '/', strtolower($filterValue)) : true;
});
}
echo GridView::widget([
'dataProvider' => new ArrayDataProvider([
'allModels' => $items,
'sort' => [
'attributes' => $searchAttributes,
],
]),
'filterModel' => $searchModel,
'columns' => array_merge(
$searchColumns, [
['class' => 'yii\grid\ActionColumn']
]
)
]);
here are some improvements for the filtering function
function ($item) {
$mailfilter = strtolower(Yii::$app->request->getQueryParam('filteremail', ''));
if (strlen($mailfilter) > 0) {
return strpos(strtolower($item['email']), $mailfilter) !== false;
} else {
return true;
}
}
Use strtolower() in both places($item['email']) & mailfilter) function if you want your filter to be not case sensitive
Check also type for strpos() ("!== false" instead of "!= false") function, otherwise, it will not work while trying to filter for the first characters of the string
A dataprovider :
if ($this->load($params)) {
$name = strtolower(trim($this->name));
$resultData= array_filter($resultData, function ($role) use ($name){
return (empty($name) || strpos((strtolower(is_object($role) ? $role->name : $role['name'])),$name) !== false);
});
}
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
https://getyii.com/topic/736
This question already has answers here:
Push to array reference
(4 answers)
Closed 8 years ago.
In my Perl Programm, I used for testing the following static array definition:
my %data = (
56 => [
{ 'Titel' => 'Test 1',
'Subtitel' => 'Untertest 1',
'Beginn' => '00:05',
'Ende' => '00:50'
},
{ 'Titel' => 'Test 2',
'Subtitel' => 'Untertest 2',
'Beginn' => '00:50',
'Ende' => '01:40'
}
],
58 => [
{ 'Titel' => 'Test 3',
'Subtitel' => 'Untertest 3',
'Beginn' => '00:10',
'Ende' => '01:50'
}
],
51 => [
{ 'Titel' => 'Test 4',
'Subtitel' => 'Untertest 4',
'Beginn' => '00:05',
'Ende' => '00:20'
},
{ 'Titel' => 'Test 5',
'Subtitel' => 'Untertest 5',
'Beginn' => '00:20',
'Ende' => '00:40'
},
{ 'Titel' => 'Test 6',
'Subtitel' => 'Untertest 6',
'Beginn' => '00:40',
'Ende' => '01:05'
}
],
);
Now I like to change it, to get data from a database. My select returns 5 values: an id (like 56, 58 or 51 in my example) and the values for each Titel, Subtitel, Beginn and Ende.
How can I build the same array construct like in my static example?
Thanks in advance! Best regards
Daniel
Assuming you want it at the end, you need to push your hashref into the arrayref stored at $data{$id}:
push #{ $data{$id} }, {
Titel => $titel,
Subtitel => $subtitel,
Beginn => $beginn,
Ende => $ende,
};
Could be something like this. Sorry, it's been a while since I've done perl.
#!/usr/bin/perl
use Data::Dumper;
sub dataset2struc {
my $result = {};
foreach my $row (#_) {
my $id = $row->{'id'};
my $recref = $result->{$id} || ();
my #rec = #{$recref};
delete $row->{'id'};
push(\#rec, $row);
$result->{$id} = \#rec;
}
return $result;
}
my #dataset = ({"id" => 1, "a" => "b"}, {"id" => 2, "a" => "c"}, {"id" => 2, "a" => "d"});
print Dumper(dataset2struc(#dataset));
I want to group my results by countryid with the data shown below.
my #test = ();
my $st = qq[
SELECT id,countryID,abbrev
FROM myTable
];
my $q = $data->prepare($st);
$q->execute() or query_error($st);
while ( my $result = $q->fetchrow_hashref ) {
push #test, $result;
}
Using fetchrow_hashref I have no problem displayling the results
use Data::Dumper;
print STDERR Dumper(\#test);
returns
$VAR1 = [
{ 'id' => '1',
'countryID' => '1',
'title' => 'Title 1',
'abbrev' => 't1'
},
{ 'id' => '2',
'countryID' => '2',
'title' => 'Title 2',
'abbrev' => 't2'
},
{ 'id' => '3',
'countryID' => '3',
'title' => 'Title 3',
'abbrev' => 't3'
},
{ 'id' => '4',
'countryID' => '1',
'title' => 'Title 4',
'abbrev' => 't4'
}
];
I want to group it by countries as shown below.
$VAR1 = [
'countries' => {
'1' => [
{ 'id' => '1',
'title' => 'Title 1',
'abbrev' => 't1'
},
{ 'id' => '4',
'title' => 'Title 4',
'abbrev' => 't4'
}
],
'2' => [
{ 'id' => '2',
'title' => 'Title 2',
'abbrev' => 't2'
}
],
'3' => [
{ 'id' => '3',
'title' => 'Title 3',
'abbrev' => 't3'
}
]
}
];
How can I get this working in the while loop?
Ignoring the errors in your sample data structure, you are basically looking to convert form array of hashes to hash of hash of array of hashes. Once you have your initial data structure setup, you can do the following to create your new nested data structure:
for my $href ( #test ) {
my $id = $href->{countryID};
delete $href->{countryID};
push #{ $test2->{countries}{$id} }, $href;
}
Iterate each element of your array #test which basically is an array of hash references. Create a variable $id which will capture the countryID value from the hash. We delete it from the hash reference and then assign that hash reference to our new nested data structure which has countries as the first level key and the $id as the second level key.
We use push syntax to create our array of such references.
Note: As stated by thb in the comments, this does destroys your original data structure. If you'd like to retain the original structure, modify the code to the following:
for my $href ( #test ) {
my $copy = { %$href };
my $id = $copy->{countryID};
delete $copy->{countryID};
push #{ $test2->{countries}{$id} }, $copy;
}
You'll need to fix your syntax above a little (for example => instead of = >), but once you have done that, something like this should work nicely.
for (#$VAR1_orig) {
my %a = %$_;
my $countryID = $a{countryID};
delete $a{countryID};
push #{$VAR1->{countries}{$countryID}}, \%a;
}
(I have tried it on my computer, incidentally. It works.)
The above assumes that %$VAR1 is initially empty, then populates it according to #$VAR1_orig, after which you can do with $VAR1 whatever you like. (I assume that you know what %$ and #$ mean in Perl, but this is not a beginner's topic, as you may know. See man 1 perlref.)
Something like this, the input/output data structures might not be exactly what you have or want, you can patch that up.
use strict;
use Data::Dumper;
$a = [
{ 'id' => '1',
'countryID' => '1',
'title' => 'Title 1',
'abbrev' => 't1'
},
{ 'id' => '2',
'countryID' => '2',
'title' => 'Title 2',
'abbrev' => 't2'
},
{ 'id' => '3',
'countryID' => '3',
'title' => 'Title 3',
'abbrev' => 't3'
},
{ 'id' => '4',
'countryID' => '1',
'title' => 'Title 4',
'abbrev' => 't4'
}
];
my $b = {};
for my $item (#$a) {
if ( exists( $b->{ $item->{'countryID'} } ) ) {
push( #{ $b->{ $item->{'countryID'} } }, $item );
} else {
$b->{ $item->{'countryID'} } = [$item];
}
}
print Dumper($b);
The above prints:
$VAR1 = {
'1' => [
{ 'abbrev' => 't1',
'title' => 'Title 1',
'id' => '1',
'countryID' => '1'
},
{ 'abbrev' => 't4',
'title' => 'Title 4',
'id' => '4',
'countryID' => '1'
}
],
'3' => [
{ 'abbrev' => 't3',
'title' => 'Title 3',
'id' => '3',
'countryID' => '3'
}
],
'2' => [
{ 'abbrev' => 't2',
'title' => 'Title 2',
'id' => '2',
'countryID' => '2'
}
]
};
i'm trying to create a test module to test json encoding. i am having issues creating variables that will output correctly with the json encode/decode. if i use just the $cat_1 in the #cats array, it will work fine. however, using both, it prints out "HASH(..." as you can see below.
use strict;
use JSON;
use Data::Dump qw( dump );
my $cat_1 = {'name' => 'cat1', 'age' => '6', 'weight' => '10 kilos', 'type' => 'siamese'};
my $cat_2 = {'name' => 'cat2', 'age' => '10', 'weight' => '13 kilos', 'type' => 'siamese'};
my #cats;
push(#cats, $cat_1);
push(#cats, $cat_2);
my $dog_1 = {'name' => 'dog1', 'age' => '7', 'weight' => '20 kilos', 'type' => 'siamese'};
my $dog_2 = {'name' => 'dog2', 'age' => '5', 'weight' => '15 kilos', 'type' => 'siamese'};
my #dogs;
push(#dogs, $dog_1);
push(#dogs, $dog_2);
my $pets = {'cats' => #cats, 'dogs' => #dogs};
my $a = { 'id' => '123', 'name' => 'Joe Smith', 'city' => "Chicago", 'pets' => $pets };
my $json = JSON->new->allow_nonref;
my $encoded = $json->encode($a);
my $decoded = $json->decode( $encoded );
print "\ndump cat_1\n";
dump $cat_1;
print "\ndump cats\n";
dump #cats;
print "\n\nOriginal\n";
dump $a;
print "\n\n";
print "Encoded\n";
print $encoded;
print "\n\n";
print "Decoded\n";
dump $decoded;
print "\n\n";
output
dump cat_1
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" }
dump cats
(
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
{ age => 10, name => "cat2", type => "siamese", weight => "3 kilos" },
)
Original
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
Encoded
{"city":"Chicago","pets":{"HASH(0x1785f2d0)":{"weight":"3 kilos","name":"dog2","type":"siamese","age":"10"},"cats":{"weight":"10 kilos","name":"cat1","type":"siamese","age":"10"},"HASH(0x176c3170)":"dogs"},"name":"Joe Smith","id":"123"}
Decoded
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
This line
my $pets = {'cats' => #cats, 'dogs' => #dogs};
is a red flag. It's valid Perl, but it's not doing what you would expect. Perl will flatten your lists in this construction, so if #cats contains ($cat_1,$cat_2) and #dogs containts ($dog_1,$dog_2), your expression is parsed as
my $pets = { 'cats', $cat_1, $cat_2, 'dogs', $dog_1, $dog_2 };
which is like
my $pets = { 'cats' => $cat_1, $cat_2 => 'dogs', $dog_1 => $dog_2 }
with the hash references $cat_2 and $dog_1 getting stringified before being used as hash keys.
Hash values must be scalar values, not arrays. But array references are OK. Try:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
The problem is in the creation of $pets:
my $pets = {'cats' => #cats, 'dogs' => #dogs};
Is roughly equivalent to:
my $pets = {'cats', {name => 'cat1', ...}, {name => 'cat2', ...},
'dogs', {name => 'dog1', ...}, {name => 'dog2, ...} };
Which is the same as:
my $pets = {
'cats' => {name => 'cat1', ...},
{name => 'cat2'}, => 'dogs',
{name => 'dog1', ...}, => {name => 'dog2}
};
You want to use ArrayRefs:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
Which is:
my $pets = {
'cats' => [
{name => 'cat1', ...},
{name => 'cat2', ...},
],
'dogs' => [
{name => 'dog1', ...},
{name => 'dog2', ...},
],
};
Which is also how you could declare the whole data structure at once.