I am learning Yii2, when I do listing with custom query I am getting error:
The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.
I am getting data from query but when I put in dataprovider it is giving me error. Here is my code:
public function search($params) {
//$query = User::find();
$query = new \yii\db\Query;
$query = $query->select(['user.*','tbl_region.id','tbl_region.regionName'])
->from('user')
->join('LEFT JOIN','tbl_men_reg_info','tbl_men_reg_info.userID = user.id')
->join('LEFT JOIN','tbl_women_info','tbl_women_info.userID = user.id')
->join('LEFT JOIN','tbl_region','tbl_men_reg_info.region = tbl_region.id');
$command = $query->createCommand();
$query = $command->queryAll();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
return $dataProvider;
}
Can anyone please tell me how to do listing with custom query?
The error is kind of clear, you need to pass instance of yii\db\Query to data provider, so remove these lines:
$command = $query->createCommand();
$query = $command->queryAll();
and it should work.
Note that you also need to use SqlDataProvider instead of ActiveDataProvider, since models are not involved.
Also modifying variable with different type and meaning is considered bad practice:
$query = $command->queryAll();
It's not $query at this point, it's better to rename it for example as $rows or $results.
Related
I am very new to coding, especially with Symfony. But now my teacher has given me a task to create a query to search within 2 attributes. I have started writing the query, but there is still a lot lacking. I am wondering if someone can help, or send a link to help me finish it.
I need to make a search option which looks up into Artikelnummer and Omschrijving.
/**
* #Route("/artikel/zoek", name="zoekartikel")
*/
Public function zoek(Request $request){
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT a
FROM AppBundle:Artikel a
WHERE a.artikelnummer = input AND a.omschrijving LIKE input2'
);
$artikelen = $query->getResult();
return new Response($this->render('search.html.twig',
array('artikelen' => $artikelen)));
}
You need first to instantiate Result Mapping
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
Then
$query = $em-> createNativeQuery(
'SELECT a
FROM AppBundle:Artikel a
WHERE a.artikelnummer = ? AND a.omschrijving LIKE ?',
$rsm
);
$query->setParameter(1, 'input1'); // or var
$query->setParameter(2, 'input2'); // or var
$artikelen = $query->getResult();
return new Response($this->render('search.html.twig',
array('artikelen' => $artikelen)));
More docs here http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html
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;
I am trying create a query in one of my model.php
The query is like
public function getBedCategory(){
$query = (new \yii\db\Query())
->select('room_category')
->from('room_charges')
->innerJoin('patient_detail',
'patient_detail.bed_type = room_charges.room_name')
->where(['room_charges.room_name'=> 'patient_detail.bed_type',
'patient_detail.id'=> $this->id]);
$command = $query->createCommand();
$rows = $command->queryOne();
//var_dump($command);exit;
return $rows;
}
When doing a var_dump for $command I am getting the sql query like this:
SELECT `room_category` FROM `room_charges`
INNER JOIN `patient_detail` ON patient_detail.bed_type = room_charges.room_name
WHERE (`room_charges`.`room_name`=:qp0) AND (`patient_detail`.`id`=:qp1)
and on var_dump of $rows I am getting boolean:false
What I am doing wrong here and why I am getting this :qp0 and :qp1
Thanks for any suggestion.
As Tahir correctly stated :qp0 and :qp1 are place holders for the parameters. These are replaced by static values on execution of the query. Your problem is that patient_detail.bed_type should not be parametized. Your code should therefore read:
...
->where(['room_charges.room_name = patient_detail.bed_type',
'patient_detail.id'=> $this->id]);
For more information on where(), you can view the API page.
I am trying to do a query in my Laravel app and I want to use a normal structure for my query. This class either does use Eloquent so I need to find something to do a query totally raw.
Might be something like Model::query($query);. Only that doesn't work.
You may try this:
// query can't be select * from table where
Model::select(DB::raw('query'))->get();
An Example:
Model::select(DB::raw('query'))
->whereNull('deleted_at')
->orderBy('id')
->get();
Also, you may use something like this (Using Query Builder):
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
Also, you may try something like this (Using Query Builder):
$users = DB::select('select * from users where id = ?', array(1));
$users = DB::select( DB::raw("select * from users where username = :username"), array('username' => Input::get("username")));
Check more about Raw-Expressions on Laravel website.
You can use hydrate() function to convert your array to the Eloquent models, which Laravel itself internally uses to convert the query results to the models. It's not mentioned in the docs as far as I know.
Below code is equviolent to $userModels = User::where('id', '>', $userId)->get();:
$userData = DB::select('SELECT * FROM users WHERE id > ?', [$userId]);
$userModels = User::hydrate($userData);
hydrate() function is defined in \Illuminate\Database\Eloquent\Builder as:
/**
* Create a collection of models from plain arrays.
*
* #param array $items
* #return \Illuminate\Database\Eloquent\Collection
*/
public function hydrate(array $items) {}
use DB::statement('your raw query here'). Hope this helps.
I don't think you can by default. I've extended Eloquent and added the following method.
/**
* Creates models from the raw results (it does not check the fillable attributes and so on)
* #param array $rawResult
* #return Collection
*/
public static function modelsFromRawResults($rawResult = [])
{
$objects = [];
foreach($rawResult as $result)
{
$object = new static();
$object->setRawAttributes((array)$result, true);
$objects[] = $object;
}
return new Collection($objects);
}
You can then do something like this:
class User extends Elegant { // Elegant is my extension of Eloquent
public static function getWithSuperFancyQuery()
{
$result = DB::raw('super fancy query here, make sure you have the correct columns');
return static::modelsFromRawResults($result);
}
}
Old question, already answered, I know.
However, nobody seems to mention the Expression class.
Granted, this might not fix your problem because your question leaves it ambiguous as to where in the SQL the Raw condition needs to be included (is it in the SELECT statement or in the WHERE statement?). However, this piece of information you might find useful regardless.
Include the following class in your Model file:
use Illuminate\Database\Query\Expression;
Then inside the Model class define a new variable
protected $select_cols = [
'id', 'name', 'foo', 'bar',
Expression ('(select count(1) from sub_table where sub_table.x = top_table.x) as my_raw_col'), 'blah'
]
And add a scope:
public function scopeMyFind ($builder, $id) {
return parent::find ($id, $this->select_cols);
}
Then from your controller or logic-file, you simply call:
$rec = MyModel::myFind(1);
dd ($rec->id, $rec->blah, $rec->my_raw_col);
Happy days.
(Works in Laravel framework 5.5)
use Eloquent Model related to the query you're working on.
and do something like this:
$contactus = ContactUS::select('*')
->whereRaw('id IN (SELECT min(id) FROM users GROUP BY email)')
->orderByDesc('created_at')
->get();
You could shorten your result handling by writing
$objects = new Collection(array_map(function($entry) {
return (new static())->setRawAttributes((array) $entry, true);
}, $result));
if you want to select info it is DB::select(Statement goes here) just remember that some queries wont work unless you go to Config/Database.php and set connections = mysql make sure 'strict' = false
Just know that it can cause some security concerns
if ever you might also need this.
orderByRaw() function for your order by.
Like
WodSection::orderBy('score_type')
->orderByRaw('FIELD(score_type,"score_type") DESC')
->get();
I am just getting started with developing with Zend Framework 2 and I've run into a roadblock.
At it's simplest expression, the fetchAll function works:
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
However, when I attempt to mix in the join in the following way:
public function fetchAll()
{
$sql = new Sql($this->tableGateway->getAdapter());
$select = $sql->select();
$select->from('Entreprise')
->columns(array('id', 'nom', 'categorie_id'))
->join(array('C' => 'Categorie'), 'categorie_id = C.id', array('categorie' => 'nom'), \Zend\Db\Sql\Select::JOIN_INNER);
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
The resulting query is:
SELECT "Entreprise"."id" AS "id", "Entreprise"."nom" AS "nom", "Entreprise"."categorie_id" AS "categorie_id", "C"."nom" AS "categorie" FROM "Entreprise" INNER JOIN "Categorie" AS "C" ON "categorie_id" = "C"."id"
The table names, columns are fine since the query doesn't throw an error, but instead simply returns an empty result set. Even removing the join and just leaving the following code doesn't help.
public function fetchAll()
{
$sql = new Sql($this->tableGateway->getAdapter());
$select = $sql->select();
$select->from('Entreprise');
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
Which makes me believe it's simply something wrong with how I get the adapter or instantiate the select, but I just can't seem to figure it out or find any solution.
Can anyone help me figure what I'm doing wrong?
The following code works perfectly:
public function fetchAll()
{
$sql = new Sql($this->tableGateway->getAdapter());
$select = $sql->select();
$select->from('Entreprise')
->columns(array('id', 'nom', 'categorie_id'))
->join(array('C' => 'Categorie'), 'categorie_id = C.id', array('categorie' => 'nom'), \Zend\Db\Sql\Select::JOIN_INNER);
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
...it was a typo that had been entered by accident in another file...
Thanks Sam for the lead, ridiculously simple, but I just didn't think of trying!