i am having strange issue with yii framework. on localhost, ajax response takes 200ms (which is fast and i am satsified) where as on my live server, same function take 4 to 7 seconds.
below is my php ajax function:-
public function actionOpenpopup() {
$this->checkAjaxRequest();
$user_id = $_GET['uid'];
$rows = Yii::app()->db->createCommand()
->select('*')
->from('saved_designs')
->where('uid=:id', array(':id' => $user_id))
->order('date desc')
->queryAll();
$i = 0;
foreach ($rows as $row) {
$rows[$i] = $row;
$i++;
}
if ($rows) {
echo json_encode($rows);
}
else
echo json_encode(null);
}
function checkAjaxRequest() {
if (Yii::app()->request->isAjaxRequest) {
header('Content-Type: application/json; charset="UTF-8"');
return true;
} else {
throw new CHttpException('403', 'Forbidden Access');
exit;
}
}
javascript code is:-
function sendAjaxCall(data){
$.ajax({
type : 'GET',
url : 'index.php/request/openpopup',
datatype : 'json',
data :data,
success: function (data) {
console.log(data);
}
});
}
*Note:- So far database has only 10 to 20 records. Also On live server, all my ajax calls give me slow response.
I would try a few things. First off after you echo your json I would kill your script to make sure nothing else runs:
if ($rows) {
echo json_encode($rows);
die();
}
Also on your index.php make sure you have the site taken out of debug mode, if you have either of the middle two lines that start with defined() enabled each page load Yii is recreating cached files and it can take a while, especially if you have extensions like bootstrap included. I have had this exact issue when doing some work for someone and their site was hosted on GoDaddy. For some reason the file creation was really slow and was really dragging everything.
<?php
$yii=dirname(__FILE__).'/../framework/yii.php';
$config=dirname(__FILE__).'/protected/config/test.php';
//defined('YII_DEBUG') or define('YII_DEBUG',true);
//defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
require_once($yii);
Yii::createWebApplication($config)->run();
Also are any other functions running slow? Any errors in your error log?
Another option to help debug create another action that doesn't require a AJAX call. It is much easier to debug this way instead of relying on ajax, plus it helps you narrow down the source of the problem. Plus don't know why but you get your array of rows then re-populate your array of rows, this is very redundant.
public function actionCheckpopup() {
$user_id = $_GET['uid'];
$rows = Yii::app()->db->createCommand()
->select('*')
->from('saved_designs')
->where('uid=:id', array(':id' => $user_id))
->order('date desc')
->queryAll();
echo json_encode($rows);
die();
}
Then simply use a browser and go to http://yoursite.com/index.php/request/checkpopup?uid=1
Related
I have a long task for a slim controller, I would like to early end the output to client and then continue the backend elaboration.
$app->get("/test",function() use($app){
$app->render("page.html"); //this is the client output
$app->easlyStop(); //a slim hypothetical command to call
$task=new MyTask();
$task->longAsyncTask(); //this take a few, client don't have to wait.
});
Is there a solution with Slim?
The easiest option here is to call a method with a system call and return before it finishes:
exec('/bin/php /path/to/a/script.php > /dev/null &');
Note that this is a simplification as PHP is request oriented, which means that a new process is started for every request, and the webserver sends the response to the user once the request is finished. You could use flush and other techniques, but these are prone to errors and depends on the configurations of the webserver too.
This is a method for Slim controller with Json view:
$app->get( '/test/', function () use($app) {
$app->view = new Json();
try{
//here the output of Json view
$model=["myjsondata"=>[]];
$app->render(200,$model);
}catch (\Slim\Exception\Stop $e) {}
//following code is copied from Slim->run() to early output
$app->response()->headers->replace(["Content-Length"=>$app->response()->length()]);
$app->response()->headers->replace(["Connection"=>"close"]);
list($status, $headers, $body) = $app->response->finalize();
\Slim\Http\Util::serializeCookies($headers, $app->response->cookies, $app->settings);
if (headers_sent() === false) {
if (strpos(PHP_SAPI, 'cgi') === 0) {
header(sprintf('Status: %s', \Slim\Http\Response::getMessageForCode($status)));
} else {
header(sprintf('HTTP/%s %s', $app->config('http.version'), \Slim\Http\Response::getMessageForCode($status)));
}
foreach ($headers as $name => $value) {
$hValues = explode("\n", $value);
foreach ($hValues as $hVal) {
header("$name: $hVal", false);
}
}
}
if (!$app->request->isHead()) {
echo $body;
}
//early output to client
ob_end_flush();
ob_flush();
flush();
if (session_id()) session_write_close();
//my async job
sleep(5);
});
I think this can be easily insert in a Slim plugin. This works only with Json view becase this is my need but it can be used with Twig or other Slim views getting output with ob* php functions instead of catching the Stop() exception.
I've got a batch processing/rendering task. This is done by streaming data from the database formatting it in the desired way and streaming it to the client via StreamedResponse. I want the processing and streaming to be as light as possible.
$responseStream->setCallback(function () use ($statement) {
echo '{"data":[';
$firstRow = $statement->fetch();
echo json_encode(arrayFromRow($firstRow));
while (is_object($statement) AND ($row = $statement->fetch()) !== FALSE) {
echo ',';
echo json_encode(arrayFromRow($row));
}
echo ']}';
});
This is the stream and works fine. I want to add translations to the arrayFromRow function. Could you point me to some symfony2 doc for programmatic access to the message files? Is there an API for this?
Thanks
You could set
$translator=$this->get('translator');
In your action, and then use it in your callback functio, the same way you use your $statement
I have a simple AJAX call that retrieves text from a file, pushes it into a table, and displays it. The call works without issue when testing on a Mac running Apache 2.2.26/PHP 5.3 and on an Ubuntu box running Apache 2.2.1.6/PHP 5.3. It does not work on RedHat running Apache 2.2.4/PHP 5.1. Naturally, the RedHat box is the only place where I need it to be working.
The call returns 200 OK but no content. Even if nothing is found in the file (or it's inaccessible), the table header is echoed so if permissions were a problem I would still expect to see something. But to be sure, I verified the file is readable by all users.
Code has been redacted and simplified.
My ajax function:
function ajax(page,targetElement,ajaxFunction,getValues)
{
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState===4 && xmlhttp.status===200)
{
document.getElementById(targetElement).innerHTML=xmlhttp.responseText;
}
};
xmlhttp.open('GET','/appdir/dir/filedir/'+page+'_funcs.php?function='+ajaxFunction+'&'+getValues+'&'+new Date().getTime(),false);
xmlhttp.setRequestHeader('cache-control','no-cache');
xmlhttp.send();
}
I call it like this:
ajax('pagename','destelement','load_info');
And return the results:
// Custom file handler
function warn_error($errno, $errstr) {
// Common function for warning-prone functions
throw new Exception($errstr, $errno);
}
function get_file_contents() {
// File operation failure would return a warning
// So handle specially to suppress the default message
set_error_handler('warn_error');
try
{
$fh = fopen(dirname(dirname(__FILE__))."/datafile.txt","r");
}
catch (Exception $e)
{
// Craft a nice-looking error message and get out of here
$info = "<tr><td class=\"center\" colspan=\"9\"><b>Fatal Error: </b>Could not load customer data.</td></tr>";
restore_error_handler();
return $info;
}
restore_error_handler();
// Got the file so get and return its contents
while (!feof($fh))
{
$line = fgets($fh);
// Be sure to avoid empty lines in our array
if (!empty($line))
{
$info[] = explode(",",$line);
}
}
fclose($fh);
return $info;
}
function load_info() {
// Start the table
$content .= "<table>
<th>Head1</th>
<th>Head2</th>
<th>Head3</th>
<th>Head4</th>";
// Get the data
// Returns all contents in an array if successful,
// Returns an error string if it fails
$info = get_file_contents();
if (!is_array($info))
{
// String was returned because of an error
echo $content.$info;
exit();
}
// Got valid data array, so loop through it to build the table
foreach ($info as $detail)
{
list($field1,$field2,$field3,$field4) = $detail;
$content .= "<tr>
<td>$field1</td>
<td>$field2</td>
<td>$field3</td>
<td>$field4</td>
</tr>";
}
$content .= "</table>";
echo $content;
}
Where it works, the response header indicates the connection as keep-alive; where it fails, the connection is closed. I don't know if that matters.
I've looked all over SO and the net for some clues but "no content" issues invariably point to same-origin policy problems. In my case, all content is on the same server.
I'm at a loss as to what to do/where to look next.
file_get_contents() expects a parameter. It does not know what you want, so it returned false. Also, you used get_file_contents() which is the wrong order.
This turned out to be a PHP version issue. In the load_info function I was using filter_input(INPUT_GET,"value"), but that was not available in PHP 5.1. I pulled that from my initial code post because I didn't think it was part of the problem. Lesson learned.
Ok folks,
I have an odd issue with a function of mine.
public function getOutages($Site)
{
// pull a json data dump of all outages
If(!$Site){
echo '[{}]';
}else{
$this->load->database('default', TRUE);
$this->db->where('Clear', '0');
$this->db->where('FracID', $Site);
$query = $this->db->get('vw_Outages');
echo json_encode($query->result_array());
}
}
This when accesed directly will not echo anything. By enabling the profiler though it functions fine and outputs the data.
public function getOutages($Site)
{
$this->output->enable_profiler(TRUE);
// pull a json data dump of all outages
If(!$Site){
echo '[{}]';
}else{
$this->load->database('default', TRUE);
$this->db->where('Clear', '0');
$this->db->where('FracID', $Site);
$query = $this->db->get('vw_Outages');
echo json_encode($query->result_array());
}
}
Any insight into this would be more then welcome :D .
CodeIgniter has an output buffering system (which also allows it to do things like cache controller output, set headers, and collect view output). You don't usually echo from a controller method. Do this instead:
public function mymethod() {
$anobject = array();
$output = json_encode($anobject);
$this->output->set_content_type('application/json');
$this->output->set_output($output);
}
See the CodeIgniter documentation for the Output class.
Maybe you have output buffering or compression enabled-this could cause problems like this. Also check that the variable you're trying to output isn't empty. If this doesn't help, try using a view to display data.
I'm having this weird problem right now, I'm just working on a small admin backend thing that will allow users to upload a file and download it again, simple stuff.
I'm using PHP OOP with Classes and functions and things. Still pretty new at it. Currently on one page I have a "getRecentLinks" function that will call information from a couple tables and put it all out on the page in a table, it works just fine. One of the options on this page is to download the file that was uploaded to that individual row. So I just want it to be a link you click on to say, file-download.php?id=3.
Now on file-download.php I'm currently just testing to get the information on the page before I add the headers and things in there. So I just have a simple
$l = new Links();
$file = $l->getFileInfo($_GET['id']);
print_r($file);
this SHOULD just return information from the database, id, name of file, size, data, and mimetype.
Now this doesn't work. I have no idea why but it doesn't.
Now on my page where I have the getRecentLinks() function it works just fine. I even brought in the getRecentLinks() into my file-download.php page so it's setup like this.
$l = new Links();
$l->getRecentLinks();
$file = $l->getFileInfo($_GET['id']);
print_r($file);
This works just fine and dandy, The second I remove getRecentLinks() it stops calling information from getFileInfo() and I cannot figure it out. I mean it's not a huge deal i could just keep #l->getRecentLinks() there but I can see this getting annoying if I have to add it to every page I want to do something, I'm just at the start of this project.
Here's the code in the Links class
public function getFileInfo($id)
{
$result = $this->runQuery("SELECT * FROM file WHERE id ='".mysql_real_escape_string($id)."'");
$resultSet = $this->fetch($result);
return $resultSet;
}
and
public function getRecentLinks()
{
$result = $this->runQuery("SELECT * FROM links ORDER BY date DESC");
while($j = $this->fetch($result))
{
$resultSet[] = $j;
}
return $resultSet;
}
And heres my connections and fetch functions a friend helped me develop
public function runQuery($sql) {
$this->connection = mysql_connect($this->dbhost, $this->dbuser, $this->dbpass);
if(!$this->connection) {
die("MySQL is down.");
} else {
mysql_select_db($this->dbname);
}
$result = mysql_query($sql,$this->connection) or die(mysql_error());
return $result;
}
public function fetch($result)
{
$resultSet = mysql_fetch_assoc($result);
return $resultSet;
}
mysql_real_escape_string requires a connection. Since getRecentLinks opens a connection it works. But you call mysql_real_escape_string before runQuery (in execution order) in getFileInfo. In this case, I assume the id is an integer, so you're better off and a lot cheaper to call intval($_GET['id']).