Eloquent - Get specific columns from logged-in user - php

In Laravel $user = Auth::user() returns the currently logged in user. From this user I want to retrieve only a few columns into a key-value array. What are my options?
Example:
$user = Auth::user()->fetch('id', 'username', 'email');
should give me
[
"id" => 1,
"username" => "John Doe",
"email" => "john#doe.example"
]
I've searched the Eloquent documentation, but haven't found the function I'm looking for. Have I missed it? Does such a function not exist?

If your main objective is to get an array instead of an object, and extra fields in the array are not a problem given that your required fields are there, you could just cast the user model to array:
Auth::user()->toArray();
(array) Auth::user();
However, if you need the output to only have these 3 properties - you have to do a little bit of extra coding. What I would propose is to create a property in User model that contains a list of publicly exposed fields. Then override toArray() method (or create another method) that only returns fields from the list.

Auth::user() fetches a user object for you, so you are no longer in Eloquent and can't use Eloquent methods.
There's no method on a model that returns an array of given attributes (reference: https://laravel.com/api/5.2/Illuminate/Database/Eloquent/Model.html), but you can make one on your User model, for instance like this:
function myData($keys) {
return array_intersect_key($this->toArray(), array_flip($keys))
}
Then you can call it using $user->myData(['id', 'username', 'keys'])

Related

Chain an array of model relationships to query builder

How can I chain an array of relations to a query builder instance in Laravel?
I currently have an array of relations passed in from another part of the system. Something like this:
$relations = [
"company",
"staff",
"category",
]
I've then got an instance of a model, and want to loop and add each relation, then get a certain property on the model. The length of the relations array is dynamic.
$instance->company->staff->category->name;
How can I achieve something like this?
Edit: To add context as to why I'd like to do this, I have a class which is using reflection to retrieve the class to instantiate. I have a property being passed to it which is generated something like organization.company.staff.category.name, where the first item organization is the model, which is instantiated with reflection and the last item name is the property which should be retrieved.
The varying items between the first and last are relations to go through to retrieve the property. We are retrieving this from a JSON value for a reporting platform, so we want to do something like this where we are able to re-use the same code to retrieve data system-wide. The content organization.company.staff.category.name will obviously change per JSON value.
you can make a foreach, see my example
Example
$relations = [
"company",
"staff",
"category",
];
$producto = Producto::find(1);
foreach($relations as $relation){ $producto = $producto->$relation; )}
return $producto->name;

Does a one-to-one relationship in Laravel always need first()?

I have a one-to-one relationship between User and UserSettings models,
But (after $user = auth()->user()) when I try $user->settings()->something it throws an Undefined property error.
It's gone when I use $user->settings()->first()->something...
My question is, is this how it's supposed to work? or am I doing something wrong?
You cannot directly run $user->settings()->something.
Because when you call $user->settings(), it just return Illuminate\Database\Eloquent\Relations\HasOne object.
So it is not the model's object, you need to take the model's object and call its attribute like this.
$user->settings()->first()->something;
Dynamic Properties
Since you have one-to-one relationship between User and UserSettings.
If you have a one-to-one relationship in your User model:
public function settings()
{
return $this->hasOne('App\Models\UserSettings', 'user_id', 'id');
}
According to Laravel doc
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get (for one-to-many relationships) or first (for one-to-one relationships) method. It will then be accessible via a dynamic property by the same name as the relation.
So you can use eloquent's dynamic properties like this:
$user->settings->something; // settings is the dynamic property of $user.
This code will give you a result of collection.
$user->settings;
So calling 'something' is not available or it will return you of null, unless you get the specific index of it.
$user->settings()->something
while this one works because you used first() to get the first data of collection and accessed the properties of it .
$user->settings()->first()->something
The first method returns the first element in the collection that passes a given truth test
see docs here laravel docs
If you want to get the user settings itself simply do this:
$user->settings
Then you can get the fields of the settings doing this:
$user->settings->something
When you do this $user->settings() you can chain query after that. E.g.
$user->settings()->where('something', 'hello')->first()
That's why the output of $user->settings and $user->settings()->first() are the same.
Auth only gives you user info;
Try the following code:
$user = User::find(auth()->user()->id);//and then
$user->settings->something;

Getting data from a linked CakePHP3 entity

I have a User entity with a hasMany relationship to Profile via a user_id foreign key.
Within my User class I'm trying to create a virtual field so I can access the name property of the linked Profile entity
protected $_virtual = ['profile_name'];
protected function _getProfileName()
{
return $this->profile->name;
}
Whatever I try I get Trying to get property of non-object
I've also tried:
$this->_properties['profile']->name;
$this->profile->_properties['name'];
I know I can get this data by building a query up using Cake\ORM\Table but I has hoping to aovid that.
What am I doing wrong?
p.s. there is definitely linked data between the two tables.
The answer seems to be
That's not how it works
Instead, use 'eager loading' to get the linked entity data. That is to say use the contain method when using find():
e.g.
$users = TableRegistry::get('users');
$query = $users->find('all', ['contain' => ["Profiles"]])
->where(['id' => $userId])
->first();
or on the query object itself:
$query->contain(['Profiles']);
In this example $query will contain Profile entity objects along with the User entity
i.e. $query->profiles is an array of Profile entities

How to save multiple request parameters in laravel 5.2 ?

I am just learning laravel now. And I have this problem. I have passed 2 request parameters to my controller function. First request parameter holds an object value, but I converted it to a serialized form since the field of my table where it will be saved has a text datatype. The second request parameter holds a overall_total calculated value and it has a float datatype field. My problem is, how would I store it in my database? I have tried to use the create function but it returns an error. Some forums regarding this are not so clear. I just can't figure it out yet. Can somebody help me with this? Here are my codes.
function store
public function store(Request $request){
$serialize_po = serialize($request['purchase_orders']);
$overall_total = $request['overall_total'];
$purchase_orders_save = PurchaseOrder::create(?);
}
How would I save 2 parameters using create? or is there other way I can saved it?
Inside of $request['purchase_orders'] is shown in the image below
Inside of $request['overall_total'] is just a number. E.g. 310
My Database Table Structure is shown below
The create() function in Laravel accepts an associative array, where the array keys are the names of the columns, and the array values are the corresponding values for the columns.
So your store function might look something like this:
public function store(Request $request){
$serialize_po = serialize($request['purchase_orders']);
$overall_total = $request['overall_total'];
$purchase_orders_save = PurchaseOrder::create([
'purchase_orders' => $serialize_po,
'overall_total' => $overall_total
]);
}
One other thing to note is that as a safety precaution, Laravel does not allow the properties of a model to be filled in this fashion out of the box. You will need to list in your model using the $fillable property which keys you will allow to be filled by passing in an associative array. If you don't, you'll likely get a MassAssignmentException.
So in your model, you will likely need to have at least the following:
class PurchaseOrder extends Model
{
protected $fillable = ['purchase_orders', 'overall_total'];
}
There are more options and ways to do this, but that is the basic and typical scenario.
More info on using the create() method and handling mass assignment is available in the documentation: https://laravel.com/docs/5.2/eloquent#mass-assignment
Considering your model name is PurchaseOrder, you first need to create a new instance of it. Then, use the save method.
public function store(Request $request)
{
$purchaseOrder = new PurchaseOrder;
$purchaseOrder->overall_total = $request['overall_total'];
$purchaseOrder->purchase_orders = serialize($request['purchase_orders']);
$purchaseOrder->save();
}
See https://laravel.com/docs/5.2/eloquent#basic-inserts for more info.
Something like this :
DB::table('purchaseOrder')->insert(
['purchase_orders' => $serialize_po,'overall_total' => $overall_total]
);
See doc if you want to explore more.

Use collection->get() instead of collection->pluck()

I am using laravel-permission for managing roles and displaying content. Per the docs you can retrieve a users roles by using $roles = $user->roles()->pluck('name'). My problem is that the data returned is ["admin"] rather than just admin. I was reviewing the collections methods and it looked like get('name') would return what I was looking for. When I try to use the following command Auth::user()->roles()->get('name') I get
1/1
ErrorException in BelongsToMany.php line 360:
Argument 1 passed to Illuminate\Database\Eloquent\Relations\BelongsToMany::getSelectColumns() must be of the type array, string given
It seems to me like the get() method is expecting an array however, I'm trying to reference an item in the array. The raw output of Auth::user()->roles()->get() is [{"id":1,"name":"admin","created_at":"2016-03-10 06:24:47","updated_at":"2016-03-10 06:24:47","pivot":{"user_id":1,"role_id":1}}]
I have found a workaround for pulling the correct content, but it is using regex for removing the unwanted characters that are included in the pluck() method.
preg_replace('/\W/i','', Auth::user()->roles()->pluck('name'))
It seems like I'm missing something or approaching using the get() method incorrectly. Any advice is appreciated.
I think pluck() will return the value of the given column for each model in the collection, which would explain the array. In your case it looks like the user has only one role, so you get an array with only one item. If the user had multiple roles, you would likely get an array with multiple items in it.
On the other hand, the get() method is used to execute a query against the database after a query is built. The results of the query are what is returned. To return a collection of models with only a single value you will need to pass an array with just the one column you want, but that will just select models, which does not appear to be what you ultimately need.
You can try this instead: $roles = $user->roles()->first()->name
The call to first() will grab the first model in the collection returned by roles(), and then you can grab the name of the role from that model.
I typically throw some error checking around this:
$role = $user->roles()->first();
if (is_null($role)) {
//Handle what happens if no role comes back
}
$role_name = $role->name;
That's because an user can have many roles, so roles is a collection.
If you are 100% sure that a user will have only one role, you can easily do
Auth::user()->roles()->first()->name
That will get the first item of that collection (the role) and then its name.

Categories