Dumping SQL queries to the screen in Laravel - mysql

I'm trying to output the actual SQL queries to the screen. I've added the following route:
// Display all SQL executed in Eloquent
Event::listen('illuminate.query', function($query)
{
var_dump($query);
});
This works mostly, but some values come out as question marks:
select DATE_FORMAT(DATE(`created_at`),'%b %d') as `date`, created_at, COUNT(*) as `count`
from `contacts`
where `created_at` > ? and `list_name` = ? or `list_name` = ? or `list_name` = ?
group by `date`
order by `created_at` asc
Is there a way to get the full query to output the actual values I'm dynamically adding, rather than unhelpful '?' characters?

Yes, you can use this code:
Event::listen(
'illuminate.query',
function ($sql, $bindings, $time) {
$sql = str_replace(array('%', '?'), array('%%', "'%s'"), $sql);
$full_sql = vsprintf($sql, $bindings);
file_put_contents(storage_path() . DIRECTORY_SEPARATOR . 'logs'
. DIRECTORY_SEPARATOR . 'sql_log.sql', $full_sql . ";\n",
FILE_APPEND);
}
);
In mine I save output to file in local environment, you can of course display this query on screen.

Related

Laravel Eloquent: Query returns no records but SQL does

I have this query:
$query = City::query();
$query->select('id', 'name as default_name', 'translations->' . $request["lang"] . ' as name', 'country_id');
$query->where(function ($query) use ($request) {
$query->whereRaw('LOWER(translations->"$.' . $request["lang"] . '") like ?', "'%" . strtolower($request['search']) . "%'");
$query->orWhere('name', 'like', "'%" . strtolower($request->search) . "%'");
});
if ($request->country !== null) {
$query->whereRaw('country_id = '. $country);
}
$results = $query->get();
That translates to this SQL:
select `id`, `name` as `default_name`, json_unquote(json_extract(`translations`, '$."en"')) as `name`, `country_id`
from `cities`
where (LOWER(translations->"$.en") like '%barcelona%' or `name` like '%barcelona%')
and country_id = 207
Eloquent is not returning any records while SQL does:
Any clue on whats wrong here?
Thanks!
Is Ok the part?
if ($request->country !== null) {
$query->whereRaw('country_id = '. $country);
}
Its seems like
if ($request->country !== null) {
$query->where('country_id', $request->country);
}
And in the select part the JSON column not has $ operator.
This line in the code seemed to be the problem:
$query->orWhere('name', 'like', "'%" . strtolower($request->search) . "%'");
I found a solution using orWhereRaw():
$query->orWhereRaw('LOWER(`name`) LIKE ? ','%'. trim(strtolower($request['search'])) .'%')
This line converts column "name" data to lowercase and trims and lowers the search parameter.
I hope it help others in the future.

search result in month using mysql or cakephp

Hi everyone i have one question search result month in using MySql or Cakephp my table name is state_supplies and data are
MySql query is:
SELECT * FROM `state_supplies` WHERE created=DATE_FORMAT(NOW(), '%m')
Cakephp search code is
$this->StateSupply->find('all', array(
'conditions'=> array(
'unitid'=>$this->Session->read('Auth.User.unitid'),
'created'=>'MONTH(CURDATE())'
)
)
);
Try this:
In Mysql:
$first_day_this_month = date('Y-m-01 H:i:s'); // hard-coded '01' for first day
$last_day_this_month = date('Y-m-t H:i:s');
$sql="SELECT * FROM state_supplies WHERE created between '$first_day_this_month' and '$last_day_this_month' "
Cakephp code
Details
Update code for right answer
$this->StateSupply->find('all',array(
'conditions'=>array(
'unitid'=>$this->Session->read('Auth.User.unitid'),
'crop'=>$this->request->data['StateSupply']['crop'],
'state'=>$this->request->data['StateSupply']['state'],
'created BETWEEN ? AND ?'=>array(date('Y-m-01',strtotime('this month')),date('Y-m-t',strtotime('this month')))
)
)
);

MySQL query optimization in codeigniter

I have function in CodeIgniter to retrieve latest posts from 2 tables:
public function get_latest_comments($amount)
{
$query = $this->db->query('
SELECT *, FROM_UNIXTIME(date) AS timestamp
FROM comments
ORDER BY timestamp DESC
LIMIT 5
');
if ($query->num_rows() > 0) {
$result = $query->result_array();
for ($i = 0; $i < sizeof( $result ); $i++) {
$result[$i]['author_info'] = $this->comments_model->get_comment_author( $result[$i]['id'] );
$result[$i]['date'] = mdate( "%M %m, %Y", $result[$i]['date'] );
if ($result[$i]['section'] === 'blog') $loc = 'blog_posts';
if ($result[$i]['section'] === 'core') $loc = 'public_posts';
$this->db->select( 'title, slug' );
$query = $this->db->get_where( $loc, array('id' => $result[$i]['location']) );
$result[$i]['post_title'] = $query->row( 'title' );
$result[$i]['url'] = base_url() . $result[$i]['section'] . '/view/' . $query->row( 'slug' ) . '/';
}
return $result;
}
return false;
}
The problem is that it runs too slow. My page sometimes loads 7-8 seconds. I suspect this query running 2 times + similar query gathering latest comments slows down my page.
I have a bad feeling about queries inside the loop. How can I avoid that?
The structure of my table is:
users (id, username, mail ...
user_info ( user_id, name, surname
public_posts ( id, slug, text, author(user id) ...
blog_posts ( id, slug, text ...
comments ( id, text, author, location(post_id_, section(post_table) ...
Check by expalining your Query , Go to the mysql command line and type
EXPLAIN SELECT *, FROM_UNIXTIME(date) AS timestamp FROM comments ORDER BY timestamp DESC LIMIT 5
Explain will tell you everything about the query, On its bases you can decide for the indexing also.
Make a practice to expalin every select query before using it in the code.
Plus you can also do profiling when ever you think your code is taking time. In codeigniter Profiler class is available, please go through the below link.
https://www.codeigniter.com/userguide3/general/profiling.html

Make Zend\Db (zf2) between clause inclusive

I'm currently using Zend Framework 2 and a query with date ranges to obtain data out of a MySQL DB, and I came across the between clause that was previously not available in ZF1.
However, my code which looks something like this is not working correctly:
$dateStart = '2012-12-20';
$dateEnd = '2012-12-31';
$sql = new Sql($_db);
$select = $sql->select()
->from(array("t" => $table))
->columns(array("col1" => "col_as_1", "col2" => "col_as_2"));
$select->where->between("date", $dateStart, $dateEnd);
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute()->getResource()->fetchAll(\PDO::FETCH_ASSOC);
Apparently the between clause is not inclusive, I can only get results until 2012-12-30, is there a way to make it inclusive? I've been taking a look at the ZF2 docs but they are not very helpful and running the same query on MySQL query browser returns all of the data I need.
So you can try lessThanOrEqualTo and greaterThanOrEqualTo.
Between doesn't seem to provide this functionality: between($identifier, $minValue, $maxValue)
If you trace out your query with $select->__toString() you can see the query as string.
I don't have ZF2 on my computer but I could imagine that between in ZF2 will output date > '2012-12-20' AND date < '2012-12-31'.
NOTE THIS : WHEN USING between on Mysql
date_column_name between 'startDate' AND 'endDate'
NOTE : you should want to insert +1 date to endDate . Because of when you insert 2015-05-18 date to endDate.you can not get data of 2015-05-18.So you need to plus one date to endDate.
You can do it using this
$plusToDate = date('Y-m-d H:i:s', strtotime($toDate . ' + 1 day'));
The BETWEEN should be inclusive, are you sure there are no hours, minutes and seconds after the date, that would cause it not to select dates on 2012-12-31 since 2012-12-31 00:00:01 would technically be > 2012-12-31
Format must be same, use mysql DATE function
$select->where->between("DATE(date)", DATE('.$dateStart.'), DATE('.$dateEnd.'));
$from_date = date('Y-m-d', strtotime($AppCleaner->from_date ));
$to_date = date('Y-m-d', strtotime($AppCleaner->to_date ));
$select->where->between('appointment_date', $from_date . ' 00:00:00', $to_date . ' 23:59:59');
also, Use the between clause as below:
$sql = new Sql($this->adapter);
$select = $sql->select();
$select->from('app_posts');
$select->where->NEST->between( 'id', 30,40);
$select->group('app_posts.id');
// echo $select->getSqlString($this->adapter->getPlatform());
// exit;
$statement = $sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
$resultSet = new ResultSet();
$resultSet->initialize($result);
$posts = $resultSet->buffer()->toArray();
return $resultSet;
Try this:
//I have a static function to make conversion Data Format
public static function convertBrazilianDate2MySQLDatabase($dataBrazil) {
$array = explode("/", $dataBrazil);
$array = array_reverse($array);
$str = implode($array, "/");
return date("Y-m-d", strtotime($str));
}
//In My Service I built my sentence
$dtStart = \Estrutura\Helpers\Data::convertBrazilianDate2MySQLDatabase($dt_start) . ' 00:00:01';
$dtEnd = \Estrutura\Helpers\Data::convertBrazilianDate2MySQLDatabase($dt_end) . ' 23:59:59';
$select->where->between('field name in table', $dtStart, $dtEnd);
[...]

CodeIgniter: How to use WHERE clause and OR clause

I am using the following code to select from a MySQL database with a Code Igniter webapp:
$query = $this->db->get_where('mytable',array('id'=>10));
This works great! But I want to write the following MySQL statement using the CI library?
SELECT * FROM `mytable` WHERE `id`='10' OR `field`='value'
Any ideas?
Thanks!
$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);
You can use or_where() for that - example from the CI docs:
$this->db->where('name !=', $name);
$this->db->or_where('id >', $id);
// Produces: WHERE name != 'Joe' OR id > 50
You can use this :
$this->db->select('*');
$this->db->from('mytable');
$this->db->where(name,'Joe');
$bind = array('boss', 'active');
$this->db->where_in('status', $bind);
Active record method or_where is to be used:
$this->db->select("*")
->from("table_name")
->where("first", $first)
->or_where("second", $second);
$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);
Though I am 3/4 of a month late, you still execute the following after your where clauses are defined... $this->db->get("tbl_name");
What worked for me :
$where = '';
/* $this->db->like('ust.title',$query_data['search'])
->or_like('usr.f_name',$query_data['search'])
->or_like('usr.l_name',$query_data['search']);*/
$where .= "(ust.title like '%".$query_data['search']."%'";
$where .= " or usr.f_name like '%".$query_data['search']."%'";
$where .= "or usr.l_name like '%".$query_data['search']."%')";
$this->db->where($where);
$datas = $this->db->join(TBL_USERS.' AS usr','ust.user_id=usr.id')
->where_in('ust.id', $blog_list)
->select('ust.*,usr.f_name as f_name,usr.email as email,usr.avatar as avatar, usr.sex as sex')
->get_where(TBL_GURU_BLOG.' AS ust',[
'ust.deleted_at' => NULL,
'ust.status' => 1,
]);
I have to do this to create a query like this :
SELECT `ust`.*, `usr`.`f_name` as `f_name`, `usr`.`email` as `email`, `usr`.`avatar` as `avatar`, `usr`.`sex` as `sex` FROM `blog` AS `ust` JOIN `users` AS `usr` ON `ust`.`user_id`=`usr`.`id` WHERE (`ust`.`title` LIKE '%mer%' ESCAPE '!' OR `usr`.`f_name` LIKE '%lok%' ESCAPE '!' OR `usr`.`l_name` LIKE '%mer%' ESCAPE '!') AND `ust`.`id` IN('36', '37', '38') AND `ust`.`deleted_at` IS NULL AND `ust`.`status` = 1 ;