Yii2 ActiveDataprovider get the related fields data - php

I have setup my dataprovider with left join as
$trucks = TblTrucks::find()
->leftJoin("tbl_checks", "tbl_checks.truck_id=tbl_trucks.id")
->Where(["town"=>$town])
->andWhere(["truck_status"=>6])
->andWhere(["between","tbl_trucks.created_at", $ts1, $ts2 ]);
$provider = new ActiveDataProvider([
'query' => $trucks,
'pagination' =>false,
]);
Now am getting thje data via
return $provider->getModels();
This returns only tbl_trucks data how can i still get the data in the tbl_checks

To get related field in model first of all your must have relation model TblChecks define relation in model TblTrucks acording to documentation
In you case it will be some like that:
public function getTblChecks()
{
return $this->hasOne(TblChecks::className(), ['truck_id' => 'id']);
//or, depending on the type of relation (on-to-one or one-to-maty)
return $this->hasMany(TblChecks::className(), ['truck_id' => 'id']);
}
Than use method joinWith:
$trucks = TblTrucks::find()
->joinWith(['tblChecks'])
->Where(["town"=>$town])
->andWhere(["truck_status"=>6])
->andWhere(["between","tbl_trucks.created_at", $ts1, $ts2 ]);
And then you can get relation field just call it:
$models = $provider->getModels();
$models[index]->tblChecks->needed_field
But if you need just array of modesl acording to your query you dont have to use ActiveDataProvider just call method all()
For example:
$trucks = TblTrucks::find()
->joinWith(['tblChecks'])
->Where(["town"=>$town])
->andWhere(["truck_status"=>6])
->andWhere(["between","tbl_trucks.created_at", $ts1, $ts2 ])->all();
And in var $trucks you will have array of models TblTrucks with relation models (TblChecks in this case) acording to your query.

Related

Laravel boolean returns "1"/"0" instead of true/false in query

I have a query that returns a boolean field (by the way, I'm on an SQL Server) on my REST API developed with Laravel and a few days ago it was returning the value as true/false, but now it returns that boolean value as String: "1"/"0".
Any idea on what could it be?
I tried using casting on my Model like this:
protected $casts = [
'status' => 'boolean',
];
This is my query:
return DB::table('dbo.visits as V')
->leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'V.id')
->select('R.id','R.status'); // status is the boolean
Thanks in advance.
When you're defining the following:
protected $casts = [
'status' => 'boolean',
];
You're defining it on the model. However, when you initiate your query using DB::table(), you're not using the model, so the binding doesn't actually apply. Initiate your query using your model:
return Visit::leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'dbo.visits.id')
->select('R.id','R.status'); // status is the boolean
Note: Had to adjust query to dbo.visits.id from V.id due to aliasing not being available at that point.
Defining casts is working when you are using Eloquent models. In code you provided you use query builder and then Eloquent models are not used at all, so no casts are done.
You could use Eloquent: API Resources
/*Controller*/
$sel_visit= Visit::leftJoin('dbo.reports AS R', 'R.id_visit', '=', 'dbo.visits.id')->select('R.id','R.status')->get(); // status is the boolean
VisitResource::collection($sel_visit);
Then using a API Resources
public function toArray($request)
{
if($this->status==1) { $status=true;} else {$status=false;}
return [
'id' => $this->id,
'status' => $status
];
}
What you would like to do is add this function to your model. Every time you use your model to retrieve data, this function matching the attribute name will be called to convert your raw data from the database to your desired format.
public function getStatusAttribute($value)
{
return $value ? 'Yes' : 'No';
}

Retrieve all models that are not associated with another model through pivot

I have three tables: users, organizations, organization_user. organization_user is a pivot table for the many-to-many relationship between users and organizations. The many-to-many relationships have been setup correctly in the corresponding models.
I need to obtain all users who are not associated with a given organization. How should this be done using eloquent. Below is what I have tried, but it is returning no results:
public function associate_user($organization_id){
$data = [
'organization' => \App\Organization::find($organization_id),
'users' => \App\User::whereDoesntHave('organizations', function($query) use ($organization_id){
$query->where('organization_id', $organization_id);
})
];
return view('admin.associateUser', $data);
}
You are never actually executing the query.
You need to call get() at the end of the query builder.
public function associate_user($organization_id) {
$data = [
'organization' => \App\Organization::find($organization_id),
'users' => \App\User::whereDoesntHave('organizations', function($query) use ($organization_id){
$query->where('organization_id', $organization_id);
})->get(); // Add the call to get()
];
return view('admin.associateUser', data);
}

Showing orders of user in laravel

I'm trying to give ability on user to see his orders. How can I query the database.. I'm trying something like this but I got empty page.. I mean nothing from database. May be my query ins't correct.
This is my controller
public function viewOrders() {
$user_order = self::$user->user_id;
$orders = Order::where('user_id', '=', $user_order);
return View::make('site.users.orders', [
'orders' => $orders
]);
}
Am I getting correctly user_id here? I'm not sure...
Update: I have this in my User model
public function orders() {
return $this->hasMany('Order', 'user_id', 'user_id');
}
Ok, so based on your route+button+model do it like this
$orders = self::$user->orders()->orderBy('order_id', 'asc')->get();
return View::make('site.users.orders', [
'orders' => $orders
]);
this should work.. You can remove orderBy clause if you don't need it.
If you have Authentication set properly you can do the following.
public function viewOrders(){
$user = Auth::user();
return view('site.users.orders',[
'orders' => $user->orders
]);
}
When you use the relationship without using the calling parentheses you get a collection of models which are queried if they're not already loaded. This is called lazy loading, if you want to load a relationship before accessing it you can use eager loading. In this case, it is not necessary though.

REST extra fields and join in Yii2

I have this schema in my database.
time_sheet
mission
position
order
One mission have many timesheets and one time sheet have just one mission.
One position have many missions and one mission have just one position.
One order have many positions and one position have just one order.
And in my class that extends from yii\rest\IndexAction I have this code (in the prepareDataProvider() method):
$query = $timeSheetModel->find()
->distinct()
->joinWith("mission")
->joinWith("mission.position")
->joinWith("mission.position.order")
->where("public.order.id = $id");
$results = new ActiveDataProvider([
'query' => $query,
]);
return $results;
So how to personalise my extra fields to get a json with the following structure:
timeSheet
mission
position
resource
order
To return specific fields, in your model for example you could override the fields method:
public function fields()
{
return [
'misson' => function($model) {
return $model->mission->id; // or anything else from the mission relation
},
... etc.
];
}
More info about the fields and extraFields methods is available in the yii2 doc - http://www.yiiframework.com/doc-2.0/guide-rest-resources.html#fields
Use ArrayDataProvider (http://www.yiiframework.com/doc-2.0/yii-data-arraydataprovider.html)
$query = new \yii\db\Query();
$query = $timeSheetModel->find()
->distinct()
->joinWith("mission")
->joinWith("mission.position")
->joinWith("mission.position.order")
->where("public.order.id = $id");
$results = new ArrayDataProvider([
'allModels' => $query->all(),
// Add pagination information if required
]);
$datas = $results->allModels;
foreach($datas as &$data) {
// Do your formatting here
}
$results->allModels = $datas;
return $results;

use 2 queries on one model or 1 query and make it toarray method to get other query

I need to get an associative array for a select input just like the following code below.
public function create() {
// queries the clients db table, orders by client_name and lists client_name and id
$client_optons = DB::table('clients')->orderBy('client_name', 'asc')->lists('client_name','id');
return View::make('projects.create', array('client_options' => $client_options));
}
However I will also need to get the entire model $clients.
public function create() {
$clients=Clients::all();
// queries the clients db table, orders by client_name and lists client_name and id
$client_optons = DB::table('clients')->orderBy('client_name', 'asc')->lists('client_name','id');
return View::make('projects.create', array('client_options' => $client_options));
}
Since I am already getting the entire model in my query, my question is should I use the 2 queries like shown above or is that bad performance/coding? Should I use 1 query and then play with the model to get $client options? (Like shown below) And do I do this with a loop or are there array functions that do it more succinctly?
public function create() {
$clients=Clients::all();
$clients_array = $clients->toArray();
$client_options = /*some code to create array('client_name'=>'id') */
return View::make('projects.create', array('client_options' => $client_options));
}
Fortunately the lists() function is also available on collections:
$clients = Clients::orderBy('client_name', 'asc')->get();
$client_options = $clients->lists('client_name', 'id');
return View::make('projects.create', array(
'client_options' => $client_options,
'clients' => $clients
));

Categories