CakePHP 3.0 - How do I return data from a deeper contain in the correct format? - query-builder

I'm working with a user's profile that has a state id in it, so I have this query:
$user = $this->Users->find()
->where(['Users.id' => $this->Auth->user('id')])
->contain(['UserProfiles' => function ($q) {
return $q
->select(['city', 'address_one', 'address_two', 'zip'])
->contain(['States' => function ($q) {
return $q
->select(['id']);
}]);
}])
->select('first_name', 'last_name')
->first();
This returns all of my data correctly except for States - instead, I get this back:
state {"id":6}
It was a little odd, so on the front end I tried:
echo $user->user_profile->state; // yields the string {"id": 6}
echo $user->user_profile->state->id; // error: trying to access property of non-object
echo $user->user_profile->state['id']; // index error, doesn't exist
So what's the deal? Why is this returned in this fashion? I don't have anything on the column specifying it as json or anything strange; just normal cake-baked objects. How do I spit out the id?

I found the issue thanks to the comments. Although I was saving the id in state_id and containing based on that column, an old column that wasn't deleted yet (states) was a text field and messed up the return value of the states contain, since the contain was also named 'state.'
I went into the database, renamed 'state' to 'old_state', and the ids again return in the standard format.

Related

How to apply an operation/functionality on one column during getting data of a table in Laravel Controller?

I want to get all the data of today's Date, but during getting it I want to apply an operation on the data of one column only NOT others. This operation is from another function.
$data = Net::whereDate('created_at', Carbon::today())->get();
I have two options:
During getting data, call to that function on the specific column
After getting data, put a loop and then apply that operation and save data into new object
In this table, there is a column called profit, and I want to encode this profit into alphabets by calling encode_code() function remaining the other data as it is.
I don't know how I can do this, please help me if anyone knows.
You can use a foreach loop to get each object from the collection and for each of those object,call the desired function.
$data = Net::whereDate('created_at', Carbon::today())->get();
foreach($data as $key => $dat)
{
$data[$key]->profit = encode_code($dat->profit);
}
I think you should call the function and turn it like this
I just didn't know what you wanted to do, so this is my best
$data = Net::whereDate('created_at', Carbon::today())->get();
foreach($data as $i => $d){
$data[$i]->profit = encode_codeļ¼ˆ$d->profit);
}
Of course you could loop through your result and encode each row, but this would prevent you from reusing this code.
Instead you could put that encode function directly into the model, so that you can reuse it everywhere:
public function getEncodedProfit() {
return encode_code($this->profit);
}
Now you can just use this function everywhere in your controllers or views like that:
echo $net->getEncodedProfit();

How can I extract the actual values from a database call for subsequent processing?

Apologies for such a vague question title, but I don't know the correct terminology to use for the problem I've got.
I'm developing a search function within which growers enter the name of their crop, the database is probed for the ID for that crop, and a second database call returns factsheets that are associated with that crop ID.
Usually, only one ID will be returned, but for some crops (e.g. asian pear, european pear), two IDs will be returned if the grower enters "pear".
My code returns the requisite ID(s), but I'm having trouble "extracting" the actual ID values from what is being returned (I don't know its name - it looks like objects within an array).
So my code
$cropID = Crop::where('name','like','%'.$search.'%')
->select('id')
->get();
returns, for $search = "pear",
$cropID = [{"id":4},{"id":112}]
I want to get the id values into a structure that I can loop through to search for factsheets associated with each ID, eg.
foreach($obj as $key => $value)
{
... do stuff with $value
}
What do I have to do with $cropID to smooth the way to subsequently get a foreach loop (if that's the correct approach) to work?
Thanks, Tom.
$crops = Crop::where('name','like','%'.$search.'%')
->select('id')
->get();
foreach($crops as $crop) {
echo $crop->id;
// Factsheet::where('crop_id', $crop->id)->get();
}
Or you can pluck it out
$cropIds = $crops->pluck('id');
foreach($cropIds as $id) {
echo $id;
// Factsheet::where('crop_id', $id)->get();
}

How to check if collection's column matches an array

Model CustomerDocuments holds customer docs, doc_id is a column in this model that signifies which document is there.
I have an array of needed document IDs, say $neededDocs = [1,2,3].
How do I check if my collection CustomerDocuments contains $neededDocs in each item of this collection.
if all $neededDocsare present in each CustomerDocuments.doc_id then return true, else, false.
I would like to preform this with collection->contains as follows:
CustomersDocuments::where('customer_id', $customer->id)
->contains('doc_id',$required_onboarding_docs)
->get();
Yet this syntax is wrong
I think you could probably achieve this with something like the following:
$documents = CustomersDocuments::where('customer_id', $customer->id)
->get()
->pluck('doc_id')
->toArray();
The above will output an array with all the doc_id.
return $documents == $neededDocs;
You could then just compare it with your $neededDocs array.
Edit: If you, however, want to check that each row in your collection contains a doc_id that is present in $neededDocs, you could do it like this:
$collection = CustomersDocuments::where('customer_id', $customer->id)->get();
return $collection->contains(function($value, $key) use ($neededDocs) {
return in_array($value->doc_id, $neededDocs);
});
I am not entirely sure which one you want, but these should do the trick.

Join query in laravel with data manipulation send to view

I am having 2 tables, users and profiledetails
I am able to run Join query and access the data and send to view.
But when I am manipulation the field 'dob' (date format) in profiledetails table. No Success, Please check the code below ,
webpagesConroller:
$users = DB::table('users')
->join('profiledetails', 'users.id', '=', 'profiledetails.user_id')
->select('users.*', 'profiledetails.dob')
->get();
$age = $users->dob->diffInYears(Carbon::now());
return view('webpages.index',compact('users'))->with($age);
View:
<li class="cate_head">Age : {{ $age}}</li>
Error:
Trying to get property of non-object
I have model Profiledetails added the mutators as below,
public function getAge(){
return $this->dob->diffInYears(Carbon::now());
}
public function getDOB(){
return $this->dob->format('d-m-Y');
}
Can I not use this method on another controller for Ex- webpagesController, If yes How.
Since you are using a raw query, the data returned is not an object but an array with the data.
Also you did not limit the query, meaning it could return multiple rows.
You'll probably need to get the data from the $users as:
//with the possibily of multiple rows. Index is the row which has to be used
$users[index]['dob']
//when you are sure it only returns one row
$users[0]['dob'] // or $users['dob'] not sure as of the moment
You want to check the differences with Carbon.
So you will probably need to make a Carbon object of the dob result and check it against the Carbon::now.
$age = Carbon::createFromFormat('Y-m-d', $users[0]['dob'])->diffForHumans();
// diffForHumans() uses the local time
Note that this only gets the age for one row (the index or the first because of [0]).
If you want to do it for every row use a for or foreach where you set the $users->age for every $user. But as these are not object/models but raw data, this will not work.
Hope this helps your question a bit

Get Attribute from Elequent where clause

So I have the following where clause where I am searching the name "Gold" inside of my tier table.
$tier = Tier::where(['name' => 'Gold'])->get(['id']);
dd($tier);
When I do the above the "id" is listed inside of the attributes but when I do as below it gives me
Undefined property: Illuminate\Database\Eloquent\Collection::$id
dd($tier->id);
All I want is to get the Id of the record where the name is "Gold".
To get actual model you should use first() instead of get(). Because there are potentially multiple rows that match get() will return a collection.
$tier = Tier::where(['name' => 'Gold'])->first(['id']);
dd($tier->id);
If you really need only the id there's even a simpler function to that, pluck().
It will get one attribute from the first result:
$id = Tier::where(['name' => 'Gold'])->pluck('id');

Resources