id attribute in eloquent collection changes when converting to an array - php

I have a database with uuid's as the id column. I do a query using eloquent and it returns the correct information. I have attached an image below because its a big object to write.
So theres 2 items in this collection, they follow the same format but as you can see the first item has the id field which is the correct uuid.
To print this i am doing
$offers = Offer::list($display, false);
dd($offers);
So offers is the collection.
If i do...
$offers = Offer::list($display, false);
dd($offers->toArray());
I get the following...
The id has magically changed into single integers instead of the uuid string I had before.
Does anyone know why it would be doing this? thanks

Set the $incrementing property on your model to false, it is documented here on the primary keys section. By default Laravel assumes that the id field on your model is an incrementing integer, that is why models automatically cast id fields to integers.

Related

Laravel: Order by column value count?

I used to have a query like this
$topReferrals = User::orderBy('user_referrals', 'DESC')->get();
Recently I changed my database structure to not count user_referrals for each user in an int datatype, but to have a column for each user called referred_by and have its value who they have been referred by, I need to adapt my query to work with the new system.
I'm not quite sure how I would go about this, I was hoping someone could help?
Eloquent offers several means of counting relations. One approach would be to set the $withCount property on the User model:
// assuming your model has a referrals method.
protected $withCount = ['referrals'];
This will append an attribute on each queried model that can be used in subsequent queries or collection modifications.
User::all()->sortByDesc('referrals');
Just add referred_by column in User table as it denotes foreign key linked to the user.
Use query below to get count of users that have been referred for each referrer:
User::where('referred_by', $referred_user_id)->count();
OR
User::where('referred_by', $referred_user_id)->orderByDesc('referred_by')->get();
Note: Just make sure you have created a table for referrers to store all the details for referrers in case you want to grabs other data regarding them. You just need to add relations to the User model to directly access to the database.
public function hasReferrers () {
$this->hasOne('App\Referrer');
}
Where App\Referrer is model for your referrers table.
As I’ve understood the question, I think this is how I’d approach getting the number of referrals per user..
$all = User::all();
foreach ($all as $current) {
$current->referrals = User::where('referred_by', $current)->count();
}
$all->sortBy('referrals');
$all should now be a list of users sorted by the number of referrals.

Laravel model object retrieving relation model with where condition without "get" method

I'm working on octoberCMS(laravel framework), I have a doubt on retrieving relation model on where clause.
I have fetched a clothing_type record from "clothing type" model based on its primary key "id".
$clothing_type = ClothingType::where('id',post('clothingtype_id'))->where('status','Active')->first();
This "clothing type" model is related with "products" model, the relation is => each clothing type hasMany products.
Every thing works fine; Now my business logic has two cases, one is to get all the products of the clothing type and another is to get the first product of the clothing type. So I have used the $clothing_type->products to get all the products and $clothing_type->products->first() to get the first product.
Now I have to apply a condition for both the cases. The condition is that only the product whose status is "Active" should be fetched, hence
$products = $clothing_type->products->where('status','Active'); and$first_product_detail = $products->first();.
Every thing works as expected but how come the products are fetched without "get()" method. $clothing_type->products->where('status','Active')->get(); Since I'm new to relation I want to know how this works or is this a bad way to get records or improper assumption. But every thing works good.
$clothing_type = ClothingType::where('id',post('clothingtype_id'))->where('status','Active')->first();
if(count($clothing_type->products))
{
$products = $clothing_type->products->where('status','Active');
$first_product_detail = $products->first();
}
You are doing it the correct way. When you access the relationship as an attribute Eloquent automatically retrieves the records.
However, if you access the relationship as a method, you get the query itself, to which you can add your filters:
if(count($clothing_type->products))
{
$products = $clothing_type->products()->where('status','Active')->get();
$first_product_detail = $products->first();
}
This would solve your problems
(documentation is over here (see the first item))
Edit: Also note that the first method is not a method of Eloquent, but from Collection, which is pretty powerful!
Edit2:
I misread the part of your question where you want to know HOW this is possible. Both Eloquent and Collections have a where method. I assume you understand the working of the Eloquent one, but the one from Collection is pretty much the same (see documentation on the Collection where here)
I prefer the Eloquent one myself, because that limits the amount of records that is retrieved from the database. But if you need all the products (even the inactive ones) later on in your code, just use the Collection method to filter the active ones out
There is nothing to be afraid of...
first() and where()
are functions of both Illuminate\Database\Query\Builder as well as Illuminate\Support\Collection and all first does is limit the records to take 1 and then give you the first record. When you use Builder a query is made to get 1 record and 1 you use it on a collection, all records are first get() and then the first of those records is returned.
Here,
When you do,
$clothing_type->products, Laravel gives you a collection of products...
So...
$products is an object of Illuminate\Support\Collection
and
$products->first() calls for the first() function in that class.
Documentation on where and first methods of a collection...

yii2 multiple filter into search model

i have a db structure like this:
Addresses
id primary key auto_increment
name
surname
email
categories
id primary key auto_increment
name
address_category
id primary key auto_increment
addr_id
cate_id
on the gridview, into categories filter column i have inserted a select2 extension with multiple set to true and on the addressesSearch model i have added this code:
->andFilterWhere(['address_category.cate_id'=> $category]
it function but not like i want, yii make a IN query like cate_id IN (4,5,6) instead i need a query that find the address that are tagged with all the categories selected.
i hope to have explained well my problem
thanks
select2 multiple returns comma separated values. split it first, maybe check for integer values
->andFilterWhere(['IN', 'address_category.cate_id', array_map('intval', explode(',', $category))]);
i have find a solution, i don't know if is the best way but works.
$query->select(['addresses.*, (select count(*) as categories from address_category where cate_id IN ('.implode(",",$category).') and addr_id=addresses.id) as categories']);
$query->having(['categories' => count($category)]);
I believe the OP's working solution may use a calculated field in the query, and that possibly ties-in with a solution that eventually worked for me, so this might just be an alternative approach. Note: I tried everything to parse/manipulate the attribute, but nothing worked.
So create a field in your model using a (getter), that simply replicates the attribute, so in a model which has a getter for a Country name in a country table with country_id as the attribute, something like:
public function getCountrylink()
{
return $this->country_id;
}
This (countryLink) is then used as the attribute in the view/index and as a simple replacement in the modelSearch filter:
$query->andFilterWhere(['country_id' => $this->countryLink]);
N.B. You'll also need to add the calc field as a public variable and include as a safe entry in the rules in the modelSearch, as per standard instructions for establishing a calculated field (search for "Filter & Sort by calculated/related fields in GridView Yii 2.0").

Access a protected field from queried Eloquent object

I query an entity:
$trip_redirect_id = Trip::whereUniqueToken($unique_token)->select('id')->get();
and try to get the id value with $trip_redirect_id->id or $trip_redirect_id['id'] but I get exception that the field is not present.
When I dump the $trip_redirect_id object, I can see the id and it's value and they are correct (I checked with the database). But how can I access the value inside php?
You are using get() which is going to be returning a Collection of objects so you won't be able to get the attributes of the models unless you iterate through the collection, even if it's just one item in the collection, or just grab the first record. Use this instead:
Trip::whereUniqueToken($unique_token)->select('id')->first();
Turns out, if I use auto-incrementing IDs, I can access the id attribute of the newly created model, right after it has been created in the DB.
So, this is the whole fix:
$trip->save();
$trip_redirect_id = $trip->id;

CI DataMapper: Find with No Related Objects

My CodeIgniter/DataMapper site needs to display a list of categories. Each category has a many-to-many relationship with itself, for multiple parents/children. I want to initially select only the categories with with no parents, or in other words, with no objects connected through a specified relationship.
I've run through a couple of possibilities (like including the related object count in the select and adding it to the where clause, which doesn't work because WHERE is evaluated before generating the column values in SQL), but to no avail.
Advice? Thank you.
Found the solution: compare the related objects ID to NULL. If it's an integer auto-increment column, no values will actually be NULL, but if there are no related rows in the join, it will come out as NULL.
$c = new Category();
$top_level_categories = $c
->where_related_parents('id IS NULL')
->get();

Categories