PHP + MySQL profiler - mysql

You know how vBulletin has a sql profiler when in debug mode? How would I go about building one for my own web application? It's built in procedural PHP.
Thanks.

http://dev.mysql.com/tech-resources/articles/using-new-query-profiler.html
The above link links how you can get al the sql profile information after any query.
Best way to implement it is to create a database class and have it have a "profile" flag to turn on logging of queries and the appropriate information as shown int he link above.
Example:
Class dbthing{
var $profile = false;
function __construct($profile = false){
if($profile){
$this->query('set profiling=1');
$this->profile = true;
}
...
}
function query($sql, $profile_this == false){
...
if($this->profile && !$profile_this)
$this->query("select sum(duration) as qtime from information_schema.profiling where query_id=1", true);
... // store the timing here
}
}

I use a database connection wrapper that I can place a profiling wrapper arround. This way I can discard the wrapper, or change it, without changing my base connector class.
class dbcon {
function query( $q ) {}
}
class profiled_dbcon()
{
private $dbcon;
private $thresh;
function __construct( dbcon $d, $thresh=false )
{
$this->dbcon = $d;
$this->thresh = $thresh;
}
function queury( $q )
{
$begin = microtime( true );
$result = this->dbcon->query();
$end = microtime( true );
if( $this->thresh && ($end - $begin) >= $this->thresh ) error_log( ... );
return $result;
}
}
For profiling with a 10 second threshold:
$dbc = new profiled_dbcon( new dbcon(), 10 );
I have it use error_log() what the times were. I would not log query performance back to the database server, that affects the database server performance. You'd rather have your web-heads absorb that impact.

Though late, Open PHP MyProfiler would help you achieve this, and you can extract functional sections from the code for your usage.

Related

When will the database connection be closed in prestashop 1.6.1.3 version?

When will the database connection be closed in prestashop 1.6.1.3 after a db instance is created by $db = Db::getInstance();
Do I need to close the database connection manually by writing any code db close function?
Or the db class in prestashop will handle this?
Actually when will be the PrestaShop db connection will be closed after a db object is created by $db = Db::getInstance();?
See below code which is a simple php file in my root directory of prestashop to update one of my tables and this page is called every one minute by cron job task ,here I am not closing the connection anywhere ,do we need to close it ?
$CheckStatusSql = "select * from ticket_status where item_id='$ItemID' and ticket_series='$TicketSeries' and status='BOOKED' ";
$db = Db::getInstance();
$result = $db->executeS($CheckStatusSql, false);
$ChangeStatus ='';
while ($row = $db->nextRow($result)) {
$status = $row['status'];
$booked_on = $row['booked_on'];
$ticket_no = $row['ticket_no'];
$to_time = strtotime(date("Y-m-d H:i:s"));// Time Now
$from_time = strtotime($booked_on); //Booked Time
$time_diff_minutes=round(abs($to_time - $from_time) / 60,2);
if($time_diff_minutes>$checkMinutes){
$ChangeStatus=$ChangeStatus."Booked ticket no: '".$ticket_no."' exceeds 30 Minutes and its now about ".$time_diff_minutes." minutes, status changed to AVAILABLE<br><br\>";
$updateSql = "UPDATE ticket_status SET status = 'AVAILABLE', booked_on = NULL WHERE item_id='$ItemID' and ticket_series='$TicketSeries' and status='BOOKED' and ticket_no='$ticket_no'";
$bookResult = $db->executeS($updateSql, false);
}
}
That is I am just including the config file (require 'config/config.inc.php';) and creating a db object and then executing my query as shown below :
require 'config/config.inc.php';
$checkMinutes = 30;// In minutes
$checkTimeInSeconds = $checkMinutes*60;
$sql = 'SELECT * FROM ps_ticket WHERE status=5';
$db = Db::getInstance();
$result = $db->executeS($sql, false);
$i=1;
while ($row = $db->nextRow($result)) {
$time = strtotime($row['hold_on']);
$curtime = time();
if(($curtime-$time) > $checkTimeInSeconds) { ///3600 seconds
$sql = 'UPDATE `'._DB_PREFIX_.'lopp_ticket`
SET
`id_customer` = 0,
`hold_on`=0,
`status` = 1
WHERE `ticket_id` = '.$row['ticket_id'];
if(Db::getInstance()->execute($sql)) {
echo $row['ticket_id'].' Updated'.'<br>';
}
}
else {
echo $row['ticket_no'].'No'.'<br>';
}
$i++;
}
So here do I need to close the db connection anywhere in the above code or PrestaShop will handle itself?
Because the server admin is saying too many database sessions are been opened by our code ,
Also Is there anyway to check from where too many db sessions are open/active always ?
As far as i know i never have closed a DB connection in Prestashop.
There documentation also does not explicitly state to close each DB request.
Looking into there source code they also never run a close command after a DB connection.
Looking into the classes\db\DbMySQLi.php class we can find the function below.
/**
* Destroys the database connection link.
*
* #see DbCore::disconnect()
*/
public function disconnect()
{
#$this->link->close();
}
Then we will look into classes\db\Db.php where we find that the function $this->disconnect() is called. So its safe to say they will close all there DB connections automatically.
/**
* Closes connection to database.
*/
public function __destruct()
{
if ($this->link) {
$this->disconnect();
}
}

Using json API pull to store in file or database

I am trying to pull data from the justin.tv API and store the echo I get in the below code in to a database or a file to be included in the sidebar of website. I am not sure on how to do this. The example of what I am trying to achieve is the live streamers list on the sidebar of teamliquid.net. Which I have done but doing it the way I have done it slows the site way down because it does about 50 json requests every time the page loads. I just need to get this in to a cached file that updates every 60 seconds or so. Any ideas?
<?php
$json_file = file_get_contents("http://api.justin.tv/api/stream/list.json?channel=colcatz");
$json_array = json_decode($json_file, true);
if ($json_array[0]['name'] == 'live_user_colcatz') echo 'coL.CatZ Live<br>';
$json_file = file_get_contents("http://api.justin.tv/api/stream/list.json?channel=coldrewbie");
$json_array = json_decode($json_file, true);
if ($json_array[0]['name'] == 'live_user_coldrewbie') echo 'coL.drewbie Live<br>';
?>
I'm not entirely sure how you would imagine this being cached, but the code below is an adaption of a block of code I've used in the past for some Twitter work. There are a few things that could probably be done better from a security perspective. Anyway, this gives you a generic way of grabbing the Feed, parsing through it, and then sending it to the database.
Warning: This assumes that there is a database connection already established within your own system.
(* Make sure you scroll to the bottom of the code window *)
/**
* Class SM
*
* Define a generic wrapper class with some system
* wide functionality. In this case we'll give it
* the ability to fetch a social media feed from
* another server for parsing and possibly caching.
*
*/
class SM {
private $api, $init, $url;
public function fetch_page_contents ($url) {
$init = curl_init();
try {
curl_setopt($init, CURLOPT_URL, $url);
curl_setopt($init, CURLOPT_HEADER, 0);
curl_setopt($init, CURLOPT_RETURNTRANSFER, 1);
} catch (Exception $e) {
error_log($e->getMessage());
}
$output = curl_exec($init);
curl_close($init);
return $output;
}
}
/**
* Class JustinTV
*
* Define a specific site wrapper for getting the
* timeline for a specific user from the JustinTV
* website. Optionally you can return the code as
* a JSON string or as a decoded PHP array with the
* $api_decode argument in the get_timeline function.
*
*/
class JustinTV extends SM {
private $timeline_document,
$api_user,
$api_format,
$api_url;
public function get_timeline ($api_user, $api_decode = 1, $api_format = 'json', $api_url = 'http://api.justin.tv/api/stream/list') {
$timeline_document = $api_url . '.' . $api_format . '?channel=' . $api_user;
$SM_init = new SM();
$decoded_json = json_decode($SM_init->fetch_page_contents($timeline_document));
// Make sure that our JSON is really JSON
if ($decoded_json === null && json_last_error() !== JSON_ERROR_NONE) {
error_log('Badly formed, dangerous, or altered JSON string detected. Exiting program.');
}
if ($api_decode == 1) {
return $decoded_json;
}
return $SM_init->fetch_page_contents($timeline_document);
}
}
/**
* Instantiation of the class
*
* Instantiate our JustinTV class, fetch a user timeline
* from JustinTV for the user colcatz. The loop through
* the results and enter each of the individual results
* into a database table called cache_sm_justintv.
*
*/
$SM_JustinTV = new JustinTV();
$user_timeline = $SM_JustinTV->get_timeline('colcatz');
foreach ($user_timeline AS $entry) {
// Here you could check whether the entry already exists in the system before you cache it, thus reducing duplicate ID's
$date = date('U');
$query = sprintf("INSERT INTO `cache_sm_justintv` (`id`, `cache_content`, `date`) VALUES (%d, '%s', )", $entry->id, $entry, $date);
$result = mysql_query($query);
// Do some other stuff and then close the MySQL Connection when your done
}

Magento: Get simple product color from custom table

I'm really struggling with this in Magento 1.10 Enterprise. I have a array of simple products color ids and I want to use this id to query the atb_color table. Raw query:
SELECT description FROM atb_colors WHERE option_id = 'my_color_id'
Here is a method I was trying to build:
public function getColorData($product){
$ids = $product->getTypeInstance()->getUsedProductIds();
foreach($ids as $id){
$simpleproduct = Mage::getModel('catalog/product')->load($id);
-->Query using my_color_id
}
}
I can use this to get name and quantity. If I put this in the foreach loop:
echo $simpleproduct->getName()." - ".(int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($simpleproduct)->getQty() . '<br />';
How would I run this query. Forgive me I am very new to Magento. It's somewhat difficult to grasp some of it. But I'm on a deadline to finish this one section of displaying color and size. Any help? Please, please!!
Thanks in advance
This is the weirdest hack, but if you are really in big hurry
public function getProductCustomColor($product)
{
$ids = $product->getTypeInstance()->getUsedProductIds();
foreach($ids as $id){
$simpleProduct = Mage::getModel('catalog/product')->load($id);
$select = $product->getResource()->getReadConnection()->select()
->from('atb_colors', array('description'))
->where('option_id = :my_color_id');
$colorDescription = $product->getResource()->getReadConnection()
->fetchOne($select, array('option_id' => $simpleProduct->getYourColorId()));
// ...
}
}
To everyone: never write code for magento in this way.

return statements inside a function

I was wondering how people handle return statements in a function. I have a method that allocates some memory but has a return false; statement when a function goes wrong. this statement is located about half way through the function so my memory is leaked if that function fails. This isn't the only return ...; statement I have in this function. What would stackoverflow recommend doing to clean up the code in a function with a few return statements in it?
if( true == OpenFtpConnection() )
{
AfxMessageBox( _T( "Connection to internet and ftp server found" ) );
// set the directory to where the xml file lives
if( false == FtpSetCurrentDirectory( m_ftpHandle, _T(_FTP_XML_LOCATION) ) )
return false;
HINTERNET xmlHandle = NULL;
WIN32_FIND_DATA fileData;
SYSTEMTIME fileWriteTime;
xmlHandle = FtpFindFirstFile( m_ftpHandle, _T("TPCFeed.xml"), &fileData, INTERNET_FLAG_RELOAD, 0 );
if( NULL == xmlHandle )
return false;
else
{
// get the write time of the ftp file
FileTimeToSystemTime( &fileData.ftLastWriteTime, &fileWriteTime );
// get the write time of the local file
HANDLE localFileHandle = NULL;
localFileHandle = CreateFile( _T(_XML_FILENAME_PATH), FILE_READ_ATTRIBUTES,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
NULL, NULL );
if( INVALID_HANDLE_VALUE == localFileHandle )
{
AfxMessageBox( _T( "opening file failed, file not found" ) );
return false;
}
else
{
CloseHandle( localFileHandle );
}
// close the FtpFindFirstFile() handle
InternetCloseHandle( xmlHandle );
}
// download xml file to disk
//if( false == FtpGetFile( m_ftpHandle, _T("TPCFeed.xml"), _T(_XML_FILENAME_PATH), FALSE,
// FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0 ) )
// return false;
}
else
{
AfxMessageBox( _T( "No Connection to internet or ftp server found" ) );
return false;
}
if( true == CloseFtpConnection() )
AfxMessageBox( _T( "Connection to internet closed" ) );
else
AfxMessageBox( _T( "Connection to internet not closed" ) );
Clarity is the most important thing. Many times, having multiple return points can make the program flow less obvious and thus more prone to bugs; but on the other hand, sometimes early returns are quite obvious; their meaning and purpose is clear. So I tend to avoid any hard rules about that.
You might get more mileage if you actually post the code you want to clean up though.
We've recently switched from the "one return per method" style to "return where it makes sense". Part of that switch was that we limit the number of lines in our methods to something reasonable (say 50 lines). By limiting the function size, the code becomes much more readable, and the multi-returns are natural, readable, and performant.
You haven't specified your programming language. Assuming it is C++: Use Boost's Smart Pointer. This not only handles multiple returns, but also exceptions thrown during method execution. If using Boost is not an option, it should be easy to create your own smart pointer class :-)

Update MySQL Value Through Img Src Variable Including jQuery

Thank-you to all who have helped me over the last few days.. Unfortunately I was working so I couldn't get back to you. I have included some code into what I thought would work, but for some reason the below code will not update in my SQL Database. I will provide the code and it's output if someone could please copy the code and see why it's not working... It's really doing my head in! Haha!
(The connection to the MySQL db + table is working fine).
// admin.php
<a href="#" id="chngeHref" /><img src="<?php echo "image.php?url=" . $row[2]; ?>?tid=<?php echo $row[0]; ?>&opn=<?php echo $row[1]; ?>" id="chnge" /></a>
// image.php?url=image.jpg?tid=3&opn=1
I was advised to do it this way to make it easier for me to pass the variables (tid and opn) through the process.
// update.php
$tid = $_GET['tid'];
$opn = $_GET['opn'];
if ($opn == "0") { $opn = "1"; } elseif ($opn == "1") { $opn = "0"; }
mysql_query("UPDATE catalogue SET opn = $opn WHERE tid = $tid ; ");
mysql_close();
// it's just a simple script to change a variable from 1 to 0 or 0 to 1 where tid = a specific number...
I have my jQuery stuff all tucked away in a lovely little file, because there is alot of it...
// navigate.js
$.extend({
getUrlVars: function() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value; });
return vars;
}
});
$("#chngeHref").click(function() {
var tid = $.getUrlVars()['tid'];
var opn = $.getUrlVars()['opn'];
$.ajax({
type: "POST",
url: "update.php",
data: "tid="+ tid +"& opn="+ opn,
success: function(){
$('#chnge').fadeTo('slow',0.4);
}
});
});
The .extend code i found on the net which finds the parameter and value of all those in the address line. I THINK this is where my issue might be, because the top code is never actually sending it to the address bar, it's being sent through jQuery to the update.php file.
I can only say thank-you soooo much in advance to anyone who can assist in this.
Phillip.
There are a few issues here bsides the SQL Injection vulnerability Nathan mentions, namely you're POSTing, so you need to use $_POST rather than $_GET to retrieve your variables. Also you have an extra space in the data block, this:
data: "tid="+ tid +"& opn="+ opn,
should be:
data: "tid="+ tid +"&opn="+ opn,
or a bit cleaner using object notation (so it also gets properly encoded):
data { tid: tid, opn: opn },
For the SQL Injection issue, instead of this:
mysql_query("UPDATE catalogue SET opn = $opn WHERE tid = $tid ; ");
At the very least escape the values, like this:
$tid = mysql_real_escape_string($_POST['tid']);
$opn = mysql_real_escape_string($_POST['opn']);
Or, go the parameterized query route, which is what I'd prefer.