yii2 get sum and related model data together - activerecord

Below is my query. I want the sum of the hours. But when I write select, it does not return the data of the related model.
$query = JobPositions::find()
->select(['sum(assign_applicant.hours) as hours'])
->joinWith(['assign','position','shift'])
->groupBy(['position_id','shift_id']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
The below line return the data when I remove the select line from the above query.
$model->position->name
what should be the solution to this when I want both ?

Try add explictally the columns you need eg:
$query = JobPositions::find()
->select(['sum(assign_applicant.hours) as hours', 'name'])
->joinWith(['assign','position','shift'])
->groupBy(['position_id','shift_id']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
or
$query = JobPositions::find()
->select('*, sum(assign_applicant.hours) as hours')
->joinWith(['assign','position','shift'])
->groupBy(['position_id','shift_id']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);

Related

Get Raw SQL of Insert Statement

I am looking for a way to get the correct SQL queries for an INSERT statement. I'm having to export this data for use in another (non-laravel) system. The post at How to get the raw SQL for a Laravel delete/update/insert statement? got me part of the way there but my queries are still parameterized:
Post::all()->each(function($post)
{
$builder = DB::table('posts');
$insertStatement = $builder->getGrammar()->compileInsert($builder->select(['created_at', 'title']), [
'created_at' => $post->created_at,
'title' => $post->title
]);
Storage::disk('sql')->append('posts-latest.sql', $insertStatement);
dump($insertStatement);
}
this results in...
insert into `posts` (`created_at`, `title`) values (?, ?)
So I've managed to set the fields to be updated but how to swap out the parameters for real values?
You can do this:
Post::all()->each(function($post){
$builder = DB::table('posts');
$grammar = $builder->getGrammar();
$values = [
'created_at' => $post->created_at,
'title' => $post->title
];
$table = $grammar->wrapTable($builder->from);
if (!is_array(reset($values))) {
$values = [$values];
}
$columns = $grammar->columnize(array_keys(reset($values)));
$parameters = collect($values)->map(function ($record) use ($grammar) {
$record = array_map(function($rec){
$rec = str_replace("'", "''", $rec);
return "'$rec'";
},array_values($record));
return '('.implode(', ', $record).')';
})->implode(', ');
$insertStatement = "insert into $table ($columns) values $parameters";
// $insertStatement should contains everything you need for this post
});
I ended up discovering DB::pretend which will generate the query without running it. Then it's a case of substitution. It seems that there is no way to get the raw SQL without substitution due to the use of parameters.
Post::all()->each(function($post)
{
$builder = DB::table('posts');
$query = DB::pretend(function() use ($builder, $post)
{
return $builder->insert([
'created_at' => $post->created_at,
'title' => $post->title,
'content' => $post->content,
'featured_image_link' => $post->featured_image_link,
'slug' => $post->slug
]);
});
$bindings = [];
collect($query[0]['bindings'])->each(function($binding) use (&$bindings)
{
$binding = str_replace("'", "\\'", $binding);
$bindings[] = "'$binding'";
});
$insertStatement = Str::replaceArray('?', $bindings, $query[0]['query']);
Storage::disk('sql')->append('posts-latest.sql', $insertStatement.';');
});

add multiple langue using Astrotomic / laravel-translatable package and laravel

i am new in laravel and use Astrotomic / laravel-translatable package for translation
i have problem when i want to add two langue at same time.
i have name_en,name_ar,discription_an,disriptionar as inputs fields.
i get this error Creating default object from empty value
so how can I solve my problem
this is link of package https://github.com/Astrotomic/laravel-translatable
// start add data
public function store(CategoryRequest $request)
{
// prepare data
$validatedData = array(
'url' => $request->url,
'slug' => $request->slug,
'status' => $request->status,
'last_updated_by' => auth('admin')->user()->id,
'created_by' => auth('admin')->user()->id,
'created' => time(),
);
$translated = array(
'name_en' => $request->name_en,
'name_ar' => $request->name_ar,
'description_en' => $request->description_en,
'description_ar' => $request->description_ar,
);
//start define categoru is sub or main
$request ->sub ==1 ? $validatedData['parent_id'] = $request ->category_id: $validatedData['parent_id']=null;
// start update data
DB::beginTransaction();
$add = Category::create($validatedData);
$id = $add->id;
// strat update category report
$categoryReport = CategoryReport::create(
['status' =>$validatedData['status'],
'category_id' =>$id,
'created_by' =>$validatedData['created_by']
,'last_updated_by' =>$validatedData['last_updated_by']]);
$add->translate('ar')->name = $translated['name_ar'];
$add->translate('en')->name = $translated['name_en'];
$add->translate('ar')->description = $translated['description_ar'];
$add->translate('en')->description =$translated['description_en'];
$add ->save();
DB::commit();
return redirect()->back()->with('success','تم اضافه البيانات بنجاح');
}

How to sort a collection from a pagination result

I have this collection I have obtained with a pagination query:
$apps = $query->paginate(10);
The result is something like this:
I would like to sort this collection before to send it, especially the "data" array. I tried a lot of things with "sortBy" and "sortByDesc". Without success. Each time I use these methods, the pagination is "broken".
How to sort this kind of json obtained by pagination?
You can use orderBy, orderByDesc or orderByRaw to order the query before paginating the results:
docs:
$apps = $query->orderBy('created_at')->paginate(10);
use Illuminate\Pagination\LengthAwarePaginator;
$sortedApps = $query->get()->sortBy('name');
$result = $this->paginateCollection($sortedApps,50);
public function paginateCollection(
$collection,
$perPage,
$pageName = 'page',
$fragment = null
) : LengthAwarePaginator
{
$currentPage = LengthAwarePaginator::resolveCurrentPage($pageName);
$currentPageItems = $collection->slice(($currentPage - 1) * $perPage, $perPage);
parse_str(request()->getQueryString(), $query);
unset($query[$pageName]);
$paginator = new LengthAwarePaginator(
$currentPageItems,
$collection->count(),
$perPage,
$currentPage,
[
'pageName' => $pageName,
'path' => LengthAwarePaginator::resolveCurrentPath(),
'query' => $query,
'fragment' => $fragment
]
);
return $paginator;
}

Active record CONCAT select fields in a relationship not working

I have the following dataprovider. Parentgroups is related to parentchildren via one-many relationship.
I am trying the concat the ChildFirstName and ChildLastName but it is not displaying. Only ID and ParentID is displaying.
$query = Parentgroups::find();
$query->with(
[
'parents' => function( $query){
$query->select([ 'Name', 'ID' ]);
},
'parentchildren' => function ( $query ){
$query->select([ new \yii\db\Expression("CONCAT('ChildFirstName', 'ChildLastName') as childName"), 'ID', 'ParentID' ]);
}
]
);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
]);
I referred to this link: https://github.com/yiisoft/yii2/issues/8276
But it didn't worked for me. Any help would be appreciated. Thanks.
You need to add childName property into your child model, so it will be populated automatically by yii. Yii2 docs about selecting extra fields

Laravel 4 - Return the id of the current insert

I have the following query
public static function createConversation( $toUserId )
{
$now = date('Y-m-d H:i:s');
$currentId = Auth::user()->id;
$results = DB::table('pm_conversations')->insert(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
return $results;
}
How would i return the id of the row just inserted?
Cheers,
Instead of doing a raw query, why not create a model...
Call it Conversation, or whatever...
And then you can just do....
$result = Conversation::create(array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now ))->id;
Which will return an id...
Or if you're using Laravel 4, you can use the insertGetId method...In Laravel 3 its insert_get_id() I believe
$results = DB::table('pm_conversations')->insertGetId(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
This method requires that the id of the table be auto-incrementing, so watch out for that...
The last method, is that you can just return the last inserted mysql object....
Like so...
$result = DB::connection('mysql')->pdo->lastInsertId();
So if you choose that last road...
It'll go...
public static function createConversation( $toUserId )
{
$now = date('Y-m-d H:i:s');
$currentId = Auth::user()->id;
$results = DB::table('pm_conversations')->insert(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
$theid= DB::connection('mysql')->pdo->lastInsertId();
return $theid;
}
I would personally choose the first method of creating an actual model. That way you can actually have objects of the item in question.
Then instead of creating a model and just save()....you calll YourModel::create() and that will return the id of the latest model creation
You can use DB::getPdo()->lastInsertId().
Using Eloquent you can do:
$new = Conversation();
$new->currentId = $currentId;
$new->toUserId = $toUserId;
$new->ip = Request::getClientIp();
$new->time = $now;
$new->save();
$the_id = $new->id; //the id of created row
The way I made it work was I ran an insert statement, then I returned the inserted row ID (This is from a self-learning project to for invoicing):
WorkOrder::create(array(
'cust_id' => $c_id,
'date' => Input::get('date'),
'invoice' => Input::get('invoice'),
'qty' => Input::get('qty'),
'description' => Input::get('description'),
'unit_price' => Input::get('unit_price'),
'line_total' => Input::get('line_total'),
'notes' => Input::get('notes'),
'total' => Input::get('total')
));
$w_id = WorkOrder::where('cust_id', '=', $c_id)->pluck('w_order_id');
return $w_id;

Resources