How to retrieve the index of an element in a collection ?
My code :
$users = User::has('posts')->withCount('posts')->orderBy('posts_count')->take(50)->get();
if($users->contains(Auth::id())){
//get the index of auth user id
}
Thank's for help
You can use the collection search() method: https://laravel.com/docs/5.7/collections#method-search
$users = User::has('posts')->withCount('posts')->orderBy('posts_count')->take(50)->get();
$userIndex = $users->search(function($user) {
return $user->id === Auth::id();
});
Just be careful, because the index might be 0:
// DON'T do this
if($userIndex) {
// this will get skipped if the user is the first one in the collection
}
// Do this instead
if($userIndex !== false) {
// this will work
}
$users = User::has('posts')->withCount('posts')->orderBy('posts_count')->take(50)->get();
// this return a collection. So can do an if like this: $userIndex->count() > 0
$userIndex = $users->filter(function($user) {
return $user->id === Auth::id()
});
Related
The code works perfectly when I want to create a new tag from scratch, but when $skillsQuery->count() > 0 and enters in the if statement. It prints...
Method Illuminate\Database\Eloquent\Collection::tag does not exist.
How can I update tags using this package?
Controller
<?php
public function storeSkills(Request $request)
{
$id = auth()->user()->id;
$skillsQuery = Skill::where('created_by', $id)->get();
// If skill exists
if ($skillsQuery->count() > 0) {
$input = $request->all();
$tags = explode(", ", $input['name']);
// $skill = Skill::create($input);
$skillsQuery->tag($tags);
$skillsQuery->created_by = $id;
if ($skillsQuery->save()) {
return redirect()->route('profile')->with('success', 'Skills updated successfully');
} else {
return redirect()->route('profile')->with('error', 'Error updated your Skills!');
}
} else {
$input = $request->all();
$tags = explode(", ", $input['name']);
$skill = Skill::create($input);
$skill->tag($tags);
$skill->created_by = $id;
if ($skill->save())
return redirect()->route('profile')->with('success', 'Skills stored successfully');
else {
return redirect()->route('profile')->with('error', 'Error storing your Skills!');
}
}
}
The result of calling ->get() on a Illuminate\Database\Query is that you will receive an instance of a Illuminate\Database\Collection, which does not contain a ->tag() method. Even if it was a query (by removing ->get()) this still would not work, as you can't call a relationship method off of a collection.
If instead you loop over the skillsQuery then you will receive an instance of a Model object which then allows you to access functions and/or relationships off of it:
$skillsQuery->each(function ($skill) use ($tags) {
$skill->tag($tags); // or perhaps ->retag($tags); here
});
I use octobercms and User Extended plugin(Clacke). I try to render a pagination because for now i have a lot of registered users and they display on one page.
I use random users function from \classes\UserManager.php
public static function getRandomUserSet($limit = 7)
{
$returner = new Collection;
$userCount = User::all()->count();
if(!isset($userCount) || empty($userCount) || $userCount == 0)
return [];
if($userCount < $limit)
$limit = $userCount;
$users = User::all(); //paginate(5)
if(empty($users))
return $returner;
$users->random($limit);
$friends = FriendsManager::getAllFriends();
foreach($users as $user)
{
$userAdd = true;
if(!$friends->isEmpty())
{
foreach($friends as $friend)
{
if($user->id == $friend->id)
{
$userAdd = false;
break;
}
}
}
if($user->id == UserUtil::getLoggedInUser()->id)
$userAdd = false;
if($userAdd)
{
$returner->push($user);
}
}
return $returner->shuffle();
}
try to do this with changing return $returner->paginate(25); and $users = User::paginate(25); but throws me an error
An exception has been thrown during the rendering of a template
("Method paginate does not exist.").
After that i try to change directly in \components\User.php
public function randomUsers()
{
return UserManager::getRandomUserSet($this->property('maxItems'))->paginate(12);
}
But again the same error.
Tryed and with this code and render in default.htm {{ tests.render|raw }}
public function randomUsers()
{
$test = UserManager::getRandomUserSet($this->property('maxItems'));
return $test->paginate(10);
}
Again with no success. Could anyoune give me some navigation and help to fix this?
If you are using random users function from \classes\UserManager.php
I checked the code and found that its using Illuminate\Support\Collection Object. So, for that Collection Object pagination works differently
You need to use forPage method.
On the other hands paginate is method of Illuminate\Database\Eloquent\Collection <- so both collection are not same
Use forpage
// OLD return UserManager::getRandomUserSet($this->property('maxItems'))
// ->paginate(12);
TO
return UserManager::getRandomUserSet($this->property('maxItems'))
->forPage(1, 12);
forPage method works like forPage(<<PAGE_NO>>, <<NO_OF_ITEM_PER_PAGE>>);
so if you use forPage it will work fine.
if any doubt please comment.
Lets assume I have a helper called engine.
if( ! function_exists('engine') )
{
function engine($user_id_1, $user_id_2, $league, $log = true)
{
/*
* variables
*/
$questionsLevel = 1;
$user1 = \App\User::where('id', $user_id_1)->first();
$user2 = \App\User::where('id', $user_id_2)->first();
$league = \App\Models\League::where('id', $league)->first();
$users = $league->all_users;
/*
* check if users joined to league correctly
*/
$user1_ok = $user2_ok = false;
foreach($users as $user)
{
if( $user->id == $user_id_1 )
{
$user1_ok = true;
}
if( $user->id == $user_id_2)
{
$user2_ok = true;
}
$check_users = [
$user1_ok,
$user2_ok
];
}
if( in_array(false, $check_users) )
{
return [
'errcode' => 404,
'errmessage' => 'one ro both user/s did not joined to league'
];
}
//DO SOME STUFF
}//function engine
}
As you know, I can write a controller to do same.
Does anyone know Which is faster based on Laravel architecture? and how can I test performance in both cases?
I'm using laravel 5.7.*
Fastest would be a solution that does not load unnecessary data:
if(! function_exists('engine'))
{
function engine(int $user1, int $user2, int $league)
{
return League::query()
->where('id', $league)
->whereHas('users', function($query) use ($user1) {
$query->where('id', $user1);
})
->whereHas('users', function($query) use ($user2) {
$query->where('id', $user2);
})
->exists();
}
}
In general, I don't think such a function should return complex results like an error message though. For this particular job, you should use a controller action. The helper method should only return true or false in my opinion. You could also place the same logic in a service class though (probably the best solution).
About the performance, I do not think there will be any changes as same query will be executed as well as same number of operation will be done, for example the foreach() loop it is O(n) in both the cases, so what will be difference, but you may like to change your code to something like below or may use ternary operator also. The difference will be in organization of codes. In controller the testing will be easier.
Note: But how id will be both $user1 and $user2, so let's make it OR in stead of AND
foreach($users as $user)
{
if( $user->id == $user_id_1 )
{
$user1_ok = true;
}elseif( $user->id == $user_id_2)
{
$user2_ok = true;
}
$check_users = [
$user1_ok,
$user2_ok
];
}
to
foreach($users as $user)
{
if( in_array($user->id, [$user_id_1, $user_id_2])
{
$user1_ok = true;
}
$check_users = [
$user1_ok,
$user2_ok
];
}
or
foreach($users as $user)
{
if( $user->id == $user_id_1 )
{
$check_users['user1_ok'] = $user->id == $user_id_1 ? true : false;
}
if( $user->id == $user_id_2)
{
$check_users['user2_ok'] = true;
}
}
If you want to get enginees with user1_ok, user2_ok, you may like to run a query as #Namoshek has suggested.
or you may like to change the query to something like
League::query()->where('id', $league)
->whereHas('users', function($query) use ($user1, $user2) {
$query->where('id', $user1)->where('id', $user2);
})->exists();
but, how id will be both $user1 and $user2?so, if it is OR instead of AND.
League::query()->where('id', $league)
->whereHas('users', function($query) use ($user1, $user2) {
$query->whereIn('id', [$user1, $user2]);
})->exists();
or even $users = [$user1, $user2]; and
League::query()->where('id', $league)
->whereHas('users', function($query) use ($users) {
$query->whereIn('id', $users);
})->exists();
By the way, if you want this using these query, you just may put it in Engine model and user or reuse it when ever required. Also for helper, it can be reusable where as in controller it is not.
I would like to use attach() on a filtered Builder result:
$users = User::whereIn('type', array(1, 2))->get();
$usersType_1 = $users->filter(function($item) {
return $item->type == 1;
});
$usersType_2 = $users->filter(function($item) {
return $item->type == 2;
});
$usersType_1->role()->attach(3);
$usersType_2->role()->attach(4);
So, I need to attach the role based on the user type. The role() method is specified on the User model
The attach() part from the code above throws the following error: Method role() doesn't exist - which I assume happens because filter() returns a Collection.
Is there a working way to attach pivot entries on filtered Builder result? Or do I need to run 2 separate queries and run attach() on them respectively?
You couldn't use role method no collection instead of User model. Try by:
$users = User::whereIn('type', array(1, 2))->get();
$usersType_1 = $users->filter(function($item) {
if($item->type == 1) {
return $item->role()->attach(3);
}
})
->all();
$usersType_2 = $users->filter(function($item) {
if($item->type == 2) {
return $item->role()->attach(4);
}
})
->all();
Alternative :
$users = User::whereIn('type', array(1, 2))->get();
$usersType_1 = $users->filter(function($item) {
$item->type == 1;
})
->all();
$usersType_2 = $users->filter(function($item) {
return $item->type == 2;
})
->all();
$role1 = Role::find(3);
$role2 = Role::find(4);
$role1->users()->attach($usersType_1->puck('id'));
$role2->users()->attach($usersType_2->puck('id'));
Why not just do:
$usersType_1 = $users->where('type', 1); // or whereType(1)
$usersType_1->role()->attach(3);
$usersType_2 = $users->where('type', 2); // or whereType(1)
$usersType_2->role()->attach(4);
I think the "Method role() doesn't exist" exception occurs because you're filtering an Eloquent Collection.
EDIT: I see why this doesn't work. It's because you're trying to attach an entire collection to a role. It would work if you used find() and then attached a role.
So you should loop over all the users with type 1 and attach the role
foreach ($usersType_1 as $user) {
$user->role()->attach(3);
}
I'm trying to modify the json output of authenticate method of JWT in laravel to make it to display roles as an array.
So here i
created_at
:
"2016-08-18 12:33:14"
email
:
"dhenn.espiritu#gmail.com"
id
:
1
last_logged_in
:
"2016-09-21 16:37:35"
name
:
"Dhenn"
roles
:
"{0: admin,
1: user"}
updated_at
:
"2016-09-21 16:37:35"
But I can't. I tried to modify my jwt.auth php file but it returned me an error that i am setting a non property object.
Here's current setup of the jwt-auth.php
public function authenticate($token = false)
{
$id = $this->getPayload($token)->get('sub');
if (! $this->auth->byId($id)) {
return false;
}
$user = $this->auth->user();
return $user;
}
While, I'm having error trying this:
public function authenticate($token = false)
{
$id = $this->getPayload($token)->get('sub');
if (! $this->auth->byId($id)) {
return false;
}
$user = $this->auth->user();
foreach ($user as $roles) {
$roles->roles = explode(",", $roles->roles);
}
return $user;
}
You said this is your user object:
{ email : "dhenn.espiritu#gmail.com"
id : 1
last_logged_in : "2016-09-21 16:37:35"
name : "Dhenn"
roles : "{0: admin, 1: user"}
updated_at : "2016-09-21 16:37:35" }
Assuming $this->auth->user(); returns this, your iteration foreach ($user as $roles) { is not correct, since $user should be an object not an array. This way you try to go through each property of this object, but I figure you want to iterate of the roles array.
This should be something like:
foreach($user->roles as $role) ... // assuming roles is an array
But roles seems to be a encoded JSON string, so you need to decode it too.
foreach(json_decode($user->roles) as $role) ...
Or directly: $user->roles = json_decode($user->roles)
Try to add
protected $casts = ['roles' => 'array'];
to your User model. That should ensure that the attributes are parsed correctly.
Here is the link to the docs https://laravel.com/docs/5.3/eloquent-mutators#attribute-casting
OK, thanks all for your help. I figured out the answer.
Here's my code that worked finally.
public function authenticate($token = false)
{
$id = $this->getPayload($token)->get('sub');
if (! $this->auth->byId($id)) {
return false;
}
$user = $this->auth->user();
$user->roles = explode(",", $user->roles);
return $user;
}