Using different database in NTICompass CodeIgniter Subqueries - codeigniter

Pardon for my beginner in object oriented PHP Codeigniter. I am confused about using $this->subquery->defaultDB() in https://github.com/NTICompass/CodeIgniter-Subqueries?
$db2 = $this->load->database('db2', TRUE);
$this->load->library('Subquery');
$this->subquery->defaultDB($db2)
$sub = $this->subquery->start_subquery('select');
$sub->select('number')->from('numbers')->where('numberID', 2);
$this->subquery->end_subquery('number');
$query = $db2->get('mytable');
but the subquery still use the default database not db2. Am I doing something wrong? Thank you.

I have created issue to its repository and the author said he will fix it on a few days.
If you are in a rush using this code, I have an alternative. I add forth param defaultDB to be used in subquery. Hope it helps. Cheers!
function start_subquery($statement, $join_type='', $join_on=1, $defaultDB=''){
$db = $this->CI->load->database($defaultDB, true);
$this->dbStack[] = $db;
$this->statement[] = $statement;
if(strtolower($statement) == 'join'){
$this->join_type[] = $join_type;
$this->join_on[] = $join_on;
}
return $db;
}

Related

In Laravel, how do you bind parameters in DB raw query when you set model attribute?

For example, I have my codes.
$news = new News();
$news->title = 'hello world';
$new->user = $user_id,
$news->urlcc = DB::raw('crc32("'.$args['newsShortUrlInput'].'")');
$news->save();
$news->refresh();
Here with attribute $news->urlcc comes from user input after using mysql function crc32();
For the SQL injection issue, above codes not safe.
So, my question is how to bind the parameters in DB::raw() with Laravel model something like below.
$news->urlcc = DB::raw('crc32(:newsShortUrlInput)', ['newsShortUrlInput' => $args['newsShortUrlInput]);
Thanks,
I found one solution, not sure it is right or perfect solution.
In News model class to rewrite setAttribute, see below.
public function setUrlcrcAttribute($shortUrl)
{
$this->attributes['urlcrc'] = $this->getConnection()->select('select crc32(?) as urlcrc', [$shortUrl])[0]->urlcrc;
}
In your service class to create a new model like below.
$news = new News();
$news->title = 'hello world';
$new->user = $user_id,
$news->urlcrc = $args['newsShortUrlInput']; // Laravel model will try to build the real attribute urlcrc
$news->save();
$news->refresh();
It works to me, but not sure this is perfect solution or not.

Laravel: two models in one controller method

Let me explain about my problem.
I am currently using Laravel 5.0. Here is my structure
Table: bgts, Model: Bgt, Controller: BgtController
Table: bgthistories, Model: BgtHistory
Now I want to do these:
Everytimes creating new item into bgts table, I want to make a copy and insert into bgthistories table. Then, everytimes that record is updated, i'll copy one more version, still insert into bgthistories.
Here is store() method.
public function store(Request $request) {
$bgt = new Bgt();
$history = $this->coppy($bgt);
$uploader = new UploadController('/data/uploads/bgt');
$bgt->name = $request['name'];
$bgt->avatar = $uploader->avatar($request);
$bgt->attachments($uploader->attachments($request));
//dd($bgt);
$bgt->save();
$history->save();
return redirect('bgt');
}
And this is the coping:
public function coppy($bgt) {
$array = $this->$bgt->toArray();
$version = new BgtHistory();
foreach($array as $key => $value) {
$version->$key = $value;
}
return $version;
}
I create migration tables already. Everything is ready. But, when I call
$bgt->save();
$history->save();
It did not work. If I remove $history->save();, it create new record ok. I think the save() method that built-in in Model provided by Laravel is problem. Can anyone tell me how to solve this.
I tried to build the raw query then executed it by DB:statement but it did not work too. Every try to execute anything with DB is failing.
Please research before re-inventing the wheel.
(Same stuff different sites in case one is down)
http://packalyst.com/packages/package/mpociot/versionable
https://packagist.org/packages/mpociot/versionable
https://github.com/mpociot/versionable
Cheers and good luck ;)

Laravel 4 SQL log / console

Is there something similar in Laravel that allows you to see the actual SQL being executed?
In Rails, for example, you can see the SQL in console. In Django you have a toolbar.
Is there something like that in Laravel 4?
To clarify: My question is how to do it without code. Is there something that is built-in in Laravel that does not require me to write code in app?
UPDATE: Preferably I'd like to see CLI queries as well (for example php artisan migrate)
If you are using Laravel 4, use this:
$queries = DB::getQueryLog();
$last_query = end($queries);
I do this in Laravel 4.
Just set it once in app/start/global.php or anywhere but make sure it is loaded and then it will start logging all your SQL queries.
Event::listen("illuminate.query", function($query, $bindings, $time, $name){
\Log::sql($query."\n");
\Log::sql(json_encode($bindings)."\n");
});
Here is a quick Javascript snippet you can throw onto your master page template.
As long as it's included, all queries will be output to your browser's Javascript Console.
It prints them in an easily readable list, making it simple to browse around your site and see what queries are executing on each page.
When you're done debugging, just remove it from your template.
<script type="text/javascript">
var queries = {{ json_encode(DB::getQueryLog()) }};
console.log('/****************************** Database Queries ******************************/');
console.log(' ');
$.each(queries, function(id, query) {
console.log(' ' + query.time + ' | ' + query.query + ' | ' + query.bindings[0]);
});
console.log(' ');
console.log('/****************************** End Queries ***********************************/');
</script>
There is a Composer package for that: https://packagist.org/packages/loic-sharma/profiler
It will give you a toolbar at the bottom with SQL queries, log messages, etc. Make sure you set debug to true in your configuration.
Here's another nice debugging option for Laravel 4:
https://github.com/barryvdh/laravel-debugbar
I came up with a really simple way (if you are using php artisan serve and PHP 5.4) - add this to app/start/local.php:
DB::listen(function($sql, $bindings, $time)
{
file_put_contents('php://stderr', "[SQL] {$sql} in {$time} s\n" .
" bindinds: ".json_encode($bindings)."\n");
});
but hoping to find a more official solution.
This will print SQL statements like this:
[SQL] select 1 in 0.06s
This code is directly taken form other source but i wanted to make it easy for you as follow it worked for me on PHPStorm using my terminal window i was able to see a complete log but ,after login there was some Sentry thing.
1.add
'log'=>true
inside your config/database.php and below the place ur database name ex.mysql
then add below code toroutes.php above all no under any route configuration , since u can make that under a give route configuration but , u only see when that route is called.
to see this output /goto / app/storage/log/somelogfile.log
if (Config::get('database.log', false))
{
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
{
$data = compact('bindings', 'time', 'name');
// Format binding data for sql insertion
foreach ($bindings as $i => $binding)
{
if ($binding instanceof \DateTime)
{
$bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
}
else if (is_string($binding))
{
$bindings[$i] = "'$binding'";
}
}
// Insert bindings into query
$query = str_replace(array('%', '?'), array('%%', '%s'), $query);
$query = vsprintf($query, $bindings);
Log::info($query, $data);
});
}
Dont forget to make break point .... or ping me :)
In QueryBuilder instance there is a method toSql().
echo DB::table('employees')->toSql()
would return:
select * from `employees`
This is the easiest method to shows the queries.

codeigniter count_all_results

I'm working with the latest codeIgniter released, and i'm also working with jquery datatables from datatables.net
I've written this function: https://gist.github.com/4478424 which, as is works fine. Except when I filter by using the text box typing something in. The filter itself happens, but my count is completely off.
I tried to add in $res = $this->db->count_all_results() before my get, and it stops the get from working at all. What I need to accomplish, if ($data['sSearch'] != '') then to utilize the entire query without the limit to see how many total rows with the search filter exists.
If you need to see any other code other than whats in my gist, just ask and I will go ahead and post it.
$this->db->count_all_results() replaces $this->db->get() in a database call.
I.E. you can call either count_all_results() or get(), but not both.
You need to do two seperate active record calls. One to assign the results #, and one to get the actual results.
Something like this for the count:
$this->db->select('id');
$this->db->from('table');
$this->db->where($your_conditions);
$num_results = $this->db->count_all_results();
And for the actual query (which you should already have):
$this->db->select($your_columns);
$this->db->from('table');
$this->db->where($your_conditions);
$this->db->limit($limit);
$query = $this->db->get();
Have you read up on https://www.codeigniter.com/userguide2/database/active_record.html#caching ?
I see you are trying to do some pagination where you need the "real" total results and at the same time limiting.
This is my practice in most of my codes I do in CI.
$this->db->start_cache();
// All your conditions without limit
$this->db->from();
$this->db->where(); // and etc...
$this->db->stop_cache();
$total_rows = $this->db->count_all_results(); // This will get the real total rows
// Limit the rows now so to return per page result
$this->db->limit($per_page, $offset);
$result = $this->db->get();
return array(
'total_rows' => $total_rows,
'result' => $result,
); // Return this back to the controller.
I typed the codes above without testing but it should work something like this. I do this in all of my projects.
You dont actually have to have the from either, you can include the table name in the count_all_results like so.
$this->db->count_all_results('table_name');
Count first with no_reset_flag.
$this->db->count_all_results('', FALSE);
$rows = $this->db->get()->result_array();
system/database/DB_query_builder.php
public function count_all_results($table = '', $reset = TRUE) { ... }
The
$this->db->count_all_results();
actually replaces the:
$this->db->get();
So you can't actually have both.
If you want to do have both get and to calculate the num rows at the same query you can easily do this:
$this->db->from(....);
$this->db->where(....);
$db_results = $this->get();
$results = $db_results->result();
$num_rows = $db_results->num_rows();
Try this
/**
* #param $column_name : Use In Choosing Column name
* #param $where : Use In Condition Statement
* #param $table_name : Name of Database Table
* Description : Count all results
*/
function count_all_results($column_name = array(),$where=array(), $table_name = array())
{
$this->db->select($column_name);
// If Where is not NULL
if(!empty($where) && count($where) > 0 )
{
$this->db->where($where);
}
// Return Count Column
return $this->db->count_all_results($table_name[0]);//table_name array sub 0
}
Then Simple Call the Method
Like this
$this->my_model->count_all_results(['column_name'],['where'],['table name']);
If your queries contain a group by, using count_all_results fails. I wrote a simple method to work around this. The key to preventing writing your queries twice is to put them all inside a private method that can be called twice. Here is some sample code:
class Report extends CI_Model {
...
public function get($page=0){
$this->_complex_query();
$this->db->limit($this->results_per_page, $page*$this->results_per_page);
$sales = $this->db->get()->result(); //no table needed in get()
$this->_complex_query();
$num_results = $this->_count_results();
$num_pages = ceil($num_results/$this->results_per_page);
//return data to your controller
}
private function _complex_query(){
$this->db->where('a', $value);
$this->db->join('(subquery) as s', 's.id = table.s_id');
$this->db->group_by('table.column_a');
$this->db->from('table'); //crucial - we specify all tables here
}
private function _count_results(){
$query = $this->db->get_compiled_select();
$count_query = "SELECT count(*) as num_rows FROM (".$query.") count_wrap";
$r = $this->db->query($count_query)->row();
return $r->num_rows;
}
}

Joomla: Write and call a helper function in a component

Fledgling Joomla / PHP developer, hitting a wall understanding how to do this. Everything I found searching has been for older versions of Joomla or other frameworks and so it's all confusing the first time around.
I want to have a helper function that I can call from anywhere in my component. Basically it takes a userID input and returns their full name, let's say hair color and height. Here's the function:
function get_profile_info($userID) {
$db =& JFactory::getDBO();
$query = $db->getQuery(true);
$query->SELECT('u.id as UserID
, u.name AS Name
, up.profile_value AS Hair
, up2.profile_value AS Height
');
$query->FROM (' #__users AS u');
$query->LEFTJOIN (' #__user_profiles AS up ON u.id = up.user_id AND up.ordering = 1');
$query->LEFTJOIN (' #__user_profiles AS up ON u.id = up.user_id AND up.ordering = 2');
$query->WHERE(' u.id = '.$userID.'');
$query->GROUPBY (' u.id
, u.name
, up.profile_value
');
$db->setQuery($query);
return $query;
}
I'd put this in a file called "lookups.php" within the "helpers" folder of my component...but here's where I'm not sure what to do next. Top of lookups.php has the obligatory:
<?php defined ( '_JEXEC' ) or die;
So two questions:
1) Do I put everything in a class or keep it as a series of functions (since there will be others)?
2) How do I pass the userID and get back the values of Name, Hair, and Height in the view (view.html.php / default.php)?
Thank you!
==================================
Edit: Based on #Shaz 's response below here's where I'm at (again, just starting off and trying to wrap my head around some of this):
lookups.php
abstract class LookupHelper {
var $Name;
var $Hair;
var $Height;
public function get_profile_info($userID) {
...
(same as above until the next line)
$db->setQuery($query);
$result=$db->loadRow();
$Name = $result[1];
$Hair = $result[2];
$Height = $result[3];
$getprofileinfo = array(Name=>$Name, Hair=>$Hair, Height=>$Height);
$return $getprofileinfo;
}
}
Then in my default.php (will probably move to view.html.php):
$getprofileinfo = Jview::loadHelper('lookups'); //got an error without this
$getprofileinfo = LookupHelper::get_profile_info($userID);
$Name = $getprofileinfo[Name];
$Hair = $getprofileinfo[Hair];
$Height = $getprofileinfo[Height];
So...it's working - but it seems like there's a much easier way of doing this (specifically manually creating an array then recalling by position). Thoughts?
Thank you!!
Create the helper class and include there all your functions:
abstract class HelloWorldHelper
{
/* functions */
}
Call the function and store the result:
$var = HelloWorldHelper::get_profile_info($thatId);
Is not possible to write your helper class inside of an existing helper Joomla file that's already being calling by all your components?
By default Joomla have helper classes doing stuff, so all you have to do is to expand the core helper classes with your owns.

Resources