Yii-How to write this query in yii? - php

I am trying to fetch the no of records, but I am unable to write this query in yii. My sql query is given below.
select count(review) from review_business where (date_created>=DATE_FORMAT(NOW() ,'%Y-11-01')) and (date_created<=DATE_FORMAT(NOW() ,'%Y-12-01')) . I am currently writing this query in yii is given below.
$results=Yii::app()->db->createCommand()
->Select('count(review)')
->from('review_business')
->where('date_created'>=DATE_FORMAT(NOW() ,'%Y-11-01'))
->queryAll();
But I am getting this error Fatal error: Call to undefined function NOW() in G:\www\ba.dev\protected\views\business\stats.php on line 19. I am sure it is because of my poor yii query. Kindly correct my query.

If you are willing to run the entire query and not use the active record pattern You can try built-in YII commands to do that.
$query = 'select * from post where category=:category';
$list= Yii::app()->db->createCommand($query)->bindValue('category',$category)->queryAll();
Explanation: $query should be obvious and =:category is binding the variable category dynamically to the query for security reasons. In next line I am creating the query and substituting the value of category variable by using bindValue() function, finally queryAll retrieves all the records in the database. Hope it is clear now.
In your case
$query = "select count(review) as result from review_business where (date_created>=DATE_FORMAT(NOW() ,'%Y-11-01')) and (date_created<=DATE_FORMAT(NOW() ,'%Y-12-01'))" ;
$list= Yii::app()->db->createCommand($query)->queryAll();
Now you can access the result like this:
foreach ($rows as $row) {
$result = $row["result"];
}

Try this,
$results=Yii::app()->db->createCommand()
->Select('count(review)')
->from('review_business')
->where('date_created >=DATE_FORMAT(NOW() ,"%Y-11-01")')
->queryScalar();

Related

Generate The Raw MySQL Query From Laravel Query Builder

How can i get mysql query of a laravel query
Convert:
App\User::where('balance','>',0)->where(...)->get();
To:
SELECT * FROM users WHERE `balance`>0 and ...
use toSql() method of laravel to get the query to be executed like
App\User::where('balance','>',0)->where(...)->toSql();
But Laravel will not show you parameters in your query, because they are bound after preparation of the query. To get the bind parameters, use this
$query=App\User::where('balance','>',0)->where(...);
print_r($query->getBindings() );
enable the query log as DB::enableQueryLog() and then output to the screen the last queries ran you can use this,
dd(DB::getQueryLog());
you can add this function to your helpers
function getRealQuery($query, $dumpIt = false)
{
$params = array_map(function ($item) {
return "'{$item}'";
}, $query->getBindings());
$result = str_replace_array('\?', $params, $query->toSql());
if ($dumpIt) {
dd($result);
}
return $result;
}
and use like this:
getRealQuery(App\User::where('balance','>',0)->where(...),true)
Method 1
To print a single query, use toSql() method of laravel to get the query to be executed like
App\User::where('balance','>',0)->where(...)->toSql();
Method 2
Laravel can optionally log in memory all queries that have been run for the current request. But in some cases, such as when inserting a large number of rows, this can cause the application to use excess memory, so you should avoid this.
To enable the log, you may use the enableQueryLog method as
DB::connection()->enableQueryLog();
To get an array of the executed queries, you may use the getQueryLog method as
$queries = DB::getQueryLog();
you can get more details here Laravel Enable Query Log
Method 3
Another approach to display all queries used in Laravel without enabling the query log install the LaravelDebugBar from here Laravel Debug Bar.
It is a package that allows you to quickly and easily keep tabs on your application during development.
To print the raw sql query, try:
DB::enableQueryLog();
// Your query here
$queries = DB::getQueryLog();
print_r($queries);
Reference
Here is a helper function who tells you the last SQL executed.
use DB;
public static function getLastSQL()
{
$queries = DB::getQueryLog();
$last_query = end($queries);
// last_query is the SQL with with data binding like
// {
// select ? from sometable where field = ? and field2 = ? ;
// param1,
// param2,
// param3,
// }
// which is hard to read.
$last_query = bindDataToQuery($last_query);
// here, last_query is the last SQL you have executed as normal SQL
// select param1 from sometable where field=param2 and field2 = param3;
return $last_query
}
Here is the bindDataToQuery function, who fill the '?' blanks with real params.
protected static function bindDataToQuery($queryItem){
$query = $queryItem['query'];
$bindings = $queryItem['bindings'];
$arr = explode('?',$query);
$res = '';
foreach($arr as $idx => $ele){
if($idx < count($arr) - 1){
$res = $res.$ele."'".$bindings[$idx]."'";
}
}
$res = $res.$arr[count($arr) -1];
return $res;
}
It is so strange that the laravel haven't support any way to get the raw sql easily, it is now version 6 after all...
Here's a workaround I used by myself to quickly get the raw sql with parameters without installing any extension...
Just deliberately make your original sql WRONG
Like change
DB::table('user')
to
DB::table('user1')
where the table "user1" does not exist at all!
Then run it again.
Sure there will be an exception reported by laravel.
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'user1' doesn't exist (SQL: ...)
And now you can see the raw sql with parameters is right after the string "(SQL:"
Change back from the wrong table name to the right one and there you go!
In Laravel 5.4 (I didn't check this in other versions), add this function into the
"App"=>"Providers"=>"AppServiceProvider.php" .
public function boot()
{
if (App::isLocal()) {
DB::listen(
function ($sql) {
// $sql is an object with the properties:
// sql: The query
// bindings: the sql query variables
// time: The execution time for the query
// connectionName: The name of the connection
// To save the executed queries to file:
// Process the sql and the bindings:
foreach ($sql->bindings as $i => $binding) {
if ($binding instanceof \DateTime) {
$sql->bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
} else {
if (is_string($binding)) {
$sql->bindings[$i] = "'$binding'";
}
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $sql->sql);
$query = vsprintf($query, $sql->bindings);
// Save the query to file
/*$logFile = fopen(
storage_path('logs' . DIRECTORY_SEPARATOR . date('Y-m-d') . '_query.log'),
'a+'
);*/
Log::notice("[USER] $query");
}
);
}
}
After that install,
https://github.com/ARCANEDEV/LogViewer
and then you can see every executed SQL queries without editing the code.
To get mysql query in laravel you need to log your query as
DB::enableQueryLog();
App\User::where('balance','>',0)->where(...)->get();
print_r(DB::getQueryLog());
Check reference : https://laravel.com/docs/5.0/database#query-logging
Instead of interfering with the application with print statements or "dds", I do the following when I want to see the generated SQL:
DB::listen(function ($query) {
Log::info($query->sql, $query->bindings);
});
// (DB and Log are the facades in Illuminate\Support\Facades namespace)
This will output the sql to the Laravel log (located at storage/logs/laravel.log). A useful command for following writes to this file is
tail -n0 -f storage/logs/laravel.log
A simple way to display all queries used in Laravel without any code changes at all is to install the LaravelDebugBar (https://laravel-news.com/laravel-debugbar).
As part of the functionality you get a tab which will show you all of the queries that a page has used.
Try this:
$results = App\User::where('balance','>',0)->where(...)->toSql();
dd($results);
Note: get() has been replaced with toSql() to display the raw SQL query.
A very simple and shortcut way is below
Write the name of column wrong like write 'balancedd' in spite of 'balance' and the query will be displayed on error screen when you execute code with all the parameters and error that column not found.
DB::enableQueryLog();
(Query)
$d= DB::getQueryLog(); print"<pre>"; print_r ($d); print"</pre>";
you will get the mysql query that is just run.
There is actually no such thing in Laravel and even PHP, since PHP internally sends the parameters with query string to the database where it (possibly) become parsed into raw query string.
The accepted answer is actually optimistic solution, kind of "optionally works".

SQL query result to string

I'm using SQL in Yii framework.
I need to show the person's latest active week (it's number and date).So I wrote following code:
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
return $query;
}
Now , I checked this query on the server and it works fine (almost) but first thing: I need to convert it into string , because yii's CgridView can't read it , and I couldn't find a working solution for this.
Second: on the server , it gave me the max date indeed , but not it's correct number , but the first number available. How can I fix this as well?
Queries like that should never be used in objective framework. If yu want to execute your own query, you should do it this way:
$sql = "your sql code";
$array = Yii::app()->db->createCommand($sql)->queryAll();
As result you will get multidimensional array with selected columns and rows
If you want to use it in grid view, you should do it this way:
$count = Yii::app()->db->createCommand($sql)->queryScalar();
$dataProvider = new CSqlDataProvider($sql, array('totalItemCount'=>$count));
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'grid-id',
'dataProvider'=> $dataProvider,
));
You can also use connection other than Yii::app()->db. Check CDbConnection class in docs.
edit: if you wanna use queries like mysql_fetch_assoc, check out also queryRow() method instead of queryAll()
Use Mysql_fetch _array
public function latestWeek()
{
$datalogin=//the login is working fine
$sql ="SELECT w.number,MAX(w.start_date)
FROM tbl_person_week t, tbl_week w
WHERE t.person_id=$this->id AND t.week_id=w.id";
$query = mysqli_query($datalogin, $sql);
while($row = mysqli_fetch_array($query)){
echo $row;
}
}
Assuming from your qu. that you want the week number and start date as one string, you have to concatenate the two columns in the sql.
You also need to specify that the week number is from the row with the maximum start date, which isn't as simple as you might first think.
I don't like injecting the person_id straight into SQL, it isn't awful in this case but is a bad habit to get into security-wise. There are binding methods available in the framework and I agree with Arek, that you should lean on the yii framework as much as possible.
To get the scalar string value, if you are insisting on using your own SQL.. I suggest the following:
$sql='
SELECT CONCAT('Week ',tw.number,' starting ',tw.start_date)
FROM tbl_week tw
JOIN (
SELECT MAX(twi.start_date) max_start_date
FROM tbl_week twi
JOIN tbl_person_week tpwi
ON tpwi.week_id = twi.id
AND tpwi.person_id = :person_id
) i
ON tw.start_date = i.max_start_date;
';
$command=Yii::app()->db->createCommand($sql);
$command->bindParam(":person_id", $this->id);
return $command->queryScalar();

Echo query before execution and without execution in codeigniter Active Record

I am looking for a way to see generated string of the query but without executing it.
Note that the query hasn't been executed before. (I do not want $this->db->last_query();)
I hope there be a method with a name like $this->db->echo_query_string($table_name = ''); to be used exactly like $this->db->get($table_name = ''); BUT THE ONLY DIFFERENCE BE THAT get() executes the code, but echo_query_string() just echoes the string of query without execution.
You can see the compiled query by either of these functions
/* SELECT */ $this->db->_compile_select();
/* INSERT */ $this->db->_insert();
/* UPDATE */ $this->db->_update();
You don't need to change any file in codeigniter because it already provides a method to do that.
Using
echo $this->db->last_query();
will produce
select * from some_table...
And this is it.
I added this little method in DB_active_rec.php
function return_query()
{
return $this->_compile_select();
}
Usage
$this->db->select('id,user_name')->from('user')->where('id',1);
$string = $this->db->return_query();
echo $string;
Result
SELECT `id`, `user_name` FROM (`user`) WHERE `id` = 1
In this way you are bound to use
$this->db->from()
Instead of
$this->db->get()
Which runs the query
You can use some public methods to get SQL queries
Get a SELECT query
$sql = $this->db->get_compiled_select();
Get a INSERT query
$sql = $this->db->get_compiled_insert();
Get a UPDATE query
$sql = $this->db->get_compiled_update();
Get a DELETE query
$sql = $this->db->get_compiled_delete();
As of version 3 of Codeigniter, please refer to this url and also to this.
echo $this->db->update_string(); OR echo $this->db->get_compiled_update();
echo $this->db->insert_string(); OR $this->db->get_compiled_insert();
echo $this->db->get_compiled_delete();
echo $this->db->get_compiled_select();
From CI 3.1.11 The below code will help you
$this->db->get_compiled_select()
Form more details visit https://codeigniter.com/userguide3/database/query_builder.html#selecting-data

modify and redo last query in codeigniter

Can I get last query made with active record class and modify some parts of it and redo that query in codeigniter. I am trying to get total pages for my pagination. I can't directly write my query because it is dynamically created on runtime within some for loops and if statements depending on the form submitted to the page.
Do you run your query twice because of the total pages? If yes, check SQL_CALC_FOUND_ROWS and FOUND_ROWS() in SQL.
$this->db->select("SQL_CALC_FOUND_ROwS id",false);
$this->db->any_AR_function(....);
$this->db->limit(...);
$result = $this->db->get();
After this you can call this:
$this->db->select("FOUND_ROWS() as count",false);
$count = $this->db->get();
I hope this is what you want.
You can get last query using:
$last_query = $this->db->last_query();
You can modify this query and then do:
$query = $this->db->query($modified_query);
foreach($query->result() as $row)
{
}

Strange error "sqlsrv_fetch_array(): 16 is not a valid ss_sqlsrv_stmt resource" since ReturnDatesAsStrings

I am using the sqlsrv driver for IIS so I can connect to a MS SQL server in PHP.
I've managed to convert a lot of my original mysql_ code and all going well, until I tried to SELECT some DateTime fields from the database. They were coming back as Date objects in PHP rather than strings, I found the fix which is adding this to the connection array:
'ReturnDatesAsStrings'=>1
Since doing that though my code is broken when trying to populate my recordset:
function row_read($recordset) {
if (!$recordset) {
die('<br><br>Invalid query :<br><br><bold>' . $this->sql . '</bold><br><br>' . sqlsrv_error());
}
$rs = sqlsrv_fetch_array($recordset);
return $rs;
}
The error is: sqlsrv_fetch_array(): 16 is not a valid ss_sqlsrv_stmt resource
There is such little amount of help on that error in Google so this is my only shot! I just don't get it.
row_read is called from within a While: while ($row = $db->row_read($rs)) {
Any ideas?
Just to add more code and logic - I do a simple SELECT of all my orders, then as it loops through them, I do another 2 SELECT's on the orders table then the customer table. It's falling down when I try these extra 2 'gets':
$this->db->sql = "SELECT * FROM TicketOrders";
$rs = $this->db->query($this->db->sql);
$this->htmlList->path("skin/search.bookings");
if ($this->db->row_count != 0) {
while ($row = $this->db->row_read($rs)) {
// Load the order row
$this->TicketOrders->get($this->db, $row['Id']);
// Load the customer row
$this->Customers->get($this->db, $row['CustomerId']);
Did you pass this resource variable by another function? If yes, you can try by executing the sqlsrv_query and executing sqlsrv_fetch_array in one function; don’t pass the ss_sqlsrv_stmt resource by another function. Hope that it will help.
Does your program involves a nested query function?
If so, the next question is: are you opening the same database in the inner query function?
Try these changes:
comment out the lines that open the database, including the { and } that enclose the function,
change the name of connection and array variables between the outer loop and the inner loop.
In other words, the outer loop may have:
$tring = sqlsrv_query($myConn, $dbx_str1);
while( $rs_row1 = sqlsrv_fetch_array($tring, SQLSRV_FETCH_ASSOC))
and the inner loop would have:
$tring2 = sqlsrv_query($myConn, $dbx_str2);
while( $rs_row2 = sqlsrv_fetch_array($tring2, SQLSRV_FETCH_ASSOC))
sqlsrv_fetch_array need a ss_sqlsrv_stmt resource. There must be something wrong with your SQL.

Categories