So, I have a PHP class that has a method which updates a session variable called $_SESSION['location']. But the problem is, each time the method is called, it doesn't find the saved session variable, and tells me it isn't set. It's supposed to store a location ID, and the method pulls the next location from a MySQL database based on the session variable, then storing the new ID. But the place in the SQL code, that's supposed to include the variable, is empty.
I do have session_start() at the beginning of the page. I've tried manually setting the variable, and it doesn't do anything either. Also tried to reach that variable from another PHP page, and no luck either. Please help.
Small sample of my code:
class location {
#session_start();
function compass($dir) {
$select = $_SESSION['location'];
if($dir == "north") {
$currentlat = mysql_result(mysql_query("SELECT `lat` FROM `locationdb` WHERE id=".$select), 0, "lat");
$currentlon = mysql_result(mysql_query("SELECT `lon` FROM `locationdb` WHERE id=".$select), 0, "lon");
$sql = "[THE SQL CODE THAT GETS THE NEXT LOCATION]";
$id = mysql_result(mysql_query($sql), 0, "id");
$_SESSION['location'] = $id;
$return['loc'] = $this->display_location($id);
$return['lat'] = $this->display_lat($id);
$return['long'] = $this->display_long($id);
$return['id'] = $id;
}
return $return;
}
}
I have tested your code
**Dont use session_start() in this file.
For simple testing first add this inside your compass() function.
$_SESSION['location'] .= 'World';
Then create a php script with these codes.
<?php
session_start();
$_SESSION['location'] = 'Hello';
include_once('*your name of class file*');
$obj = new location();
$obj -> compass('north');
echo $_SESSION['location'];
?>
Run this script
If the output is "HelloWorld" then your $_SESSION['location'] is working.
Check your phpinfo(), to see if the session save path is defined. If not, define a directory to store the sessions. In your code:
session_save_path('/DIRECTORY IN YOUR SERVER');
Then try again.
This is closer to what your method should look like. There are some settings that will help reduce errors being thrown when running the function. With this function, and other suggestions, you should be able to remove the error your are getting.
class location
{
public function compass($dir = '')
{
// Set the $select by $_SESSION or by your function
$select = (isset($_SESSION['location']))? $_SESSION['location']: $this->myFunctionToSetDefault();
// I set $dir to empty so not to throw error
if($dir == "north") {
$currentlat = mysql_result(mysql_query("SELECT `lat` FROM `locationdb` WHERE id=".$select), 0, "lat");
$currentlon = mysql_result(mysql_query("SELECT `lon` FROM `locationdb` WHERE id=".$select), 0, "lon");
$sql = "[THE SQL CODE THAT GETS THE NEXT LOCATION]";
$id = mysql_result(mysql_query($sql), 0, "id");
$_SESSION['location'] = $id;
$return['loc'] = $this->display_location($id);
$return['lat'] = $this->display_lat($id);
$return['long'] = $this->display_long($id);
$return['id'] = $id;
}
// This will return empty otherwise may throw error if $return is not set
return (isset($return))? $return:'';
}
}
Related
During my create user process I make a few queries to various database's to get the new user setup. This script has been working fine for about a year and a half, but now something is off.
So the first thing I do is I check to see if a user exists with the credentials being submitted. I've thoroughly tested the check and I'm confident my issue isn't there.
If that check comes back false then the script continues to create the user.
public function registerUser() {
parse_str($_SERVER['QUERY_STRING'], $data);
$data = (object) $data;
$check = json_decode($this->checkUserExists($data->email));
if ($check->res) {
$res = new \stdClass();
$res->res = false;
$res->user_status = $check->user_status;
$res->msg = 'User exists.';
echo json_encode($res);
}
if (!$check->res) {
$this->createUser($data);
}
}
The problem arises after all the queries have been completed, the script does not seem to want to run the if statement at the bottom. I marked it with comment characters so it's easier to find, but I included the entire function for clarity, maybe I'm doing something that is causing the issue.
I tried invoking an error manually at various points during the script. And I am able to trigger an error all the way down to the bottom of the script.
private function createUser($data) {
$Crypt = new CryptController();
$AuthSelect = new AuthController();
$Time = new TimeController();
$remote_address = new RemoteAddressController();
$Session = new SessionController();
$AuthInsert = new AuthModel_Insert();
$hashed_password = $Crypt->create_hash($data->password);
$data->password = '';
$AuthData = json_decode($AuthSelect->getAuth());
$system_auth_id = $AuthData->system_auth_id;
$user_id = $Crypt->get_uuid();
$user_auth_id = $Crypt->get_uuid();
$user_createddate = $Time->time();
$user_updateddate = $Time->time();
$user_lastupdateddate = $Time->time();
$agent_ip = $remote_address->getIpAddress();
$userData = $this->createUserObject(
$user_id,
$user_auth_id,
$system_auth_id,
$hashed_password,
$user_createddate,
$user_updateddate,
$user_lastupdateddate,
$data
);
$agentData = $this->createAgentObject(
$user_id,
$agent_ip,
$data
);
//////////////////////////////////////////
$create_user = $AuthInsert->createNewUser(
$userData
);
$create_user_agent = $this->setUserAgent(
$agentData
);
$sessionKeyData = new \stdClass();
$sessionKeyData->user_id = $user_id;
$sessionKeyData->user_auth_id = $user_auth_id;
$sessionKeyData->system_auth_id = $system_auth_id;
$sessionKeyData->agent_id = $create_user_agent->agent->agent_id;
$set_session_key = $Session->setSessionKey(
$sessionKeyData
);
$send_activation_email = $this->createUserActivation(
$userData
);
if (
$create_user &&
$create_user_agent->res &&
$set_session_key->res &&
$send_activation_email->res) {
$res = new \stdClass();
$res->res = true;
$res->msg = 'New user successfully created.';
echo json_encode($res);
} else {
$res = new \stdClass();
$res->res = false;
$res->msg = 'Error: User creation process incomplete.';
echo json_encode($res);
}
//////////////////////////////////////////
trigger_error("Invoked Error: ",E_USER_ERROR);
}
The queries themselves go through just fine, all the tables are populated just fine. The issue is that after that happens the script doesn't finish. It seems to end the createUser() function and return to the registerUser() function at which point the user will exist so it will return false and echo that back to the client.
In my testing it seems my issue might be at the bottom with that if statement. But I've tested each of those queries individually and they do return the desired booleans to get the true condition. But, even the false condition doesn't go through which should return 'Error: User creation process incomplete.'. That doesn't happen either.
I'm hoping someone sees something I'm missing because I've been stuck on this problem for too long. I appreciate any guidance that might lead me to an answer. Thanks in advance.
Just for clarification the message I'm getting back is $res->msg = 'User exists.'; which comes from registeruser(). The message I'm expecting back is $res->msg = 'New user successfully created.'; which should come from createUser().
I'm having this error "Property Order->id_customer is empty" occur only when orders are inputted and submitted via the Selenium chromedriver. I'm running PrestaShop 1.6 and I do not get this error when I enter the same order details manually.
I don't think it's an issue with the actual selenium script, but possibly with the webdriver; I thought it could due to missing data in a cookie or not actually selecting fields but when I inspected the packet from the form submission nothing was missing when compared to the manual entry.
I've also emptied the prestashop cache and deleted all the browser data from chrome in case it was due to cached data but no such luck.
I did override multiple files related to the order submission to accommodate some project requirements, specifically PaymentModule, Order, & AdminOrdersController but I don't know how that could be the issue if the manual entry works fine. I've been debugging anyway since I've been grasping for ideas and so in case it's actually due to my override I've been trying to debug variables in them but keep running into issues; I can't actually output the variables, I tried looking at PrestaShop Logs (Dev_mode is on), echoing, var_dumping, using PrestaShop's p(), and saving to file but no data comes out.
I could really use a direct solution but I at least need some new ideas for debugging.
EDIT: Here are the overridden files.
PaymentModules.php:
$order_list = array();
$order_detail_list = array();
do {
//changed from generateReference()
$reference = Order::generateReferenceOrderID($extra_vars[0]);
} while (Order::getByReference($reference)->count());
$this->currentOrderReference = $reference;
Order.php:
Class Order extends OrderCore
{
//needed to abide by project requirements prefix system.
public static function generateReference(){
$id_shop = Context::getContext()->shop->id;
$ref_store = "ABCD";
if($id_shop == 1){
$ref_store = "TCPR";
}
else if ($id_shop == 2){
$ref_store = "LOER";
}
else if ($id_shop == 3){
$ref_store = "TCPW";
}
$AUTO_INCREMENT = Db::getInstance()->getValue("
SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'ts'
AND TABLE_NAME = 'orders'");
$last_id = Db::getInstance()->getValue("
SELECT MAX(id_order)
FROM '._DB_PREFIX_.'orders");
if($last_id < $AUTO_INCREMENT){
$last_id = $AUTO_INCREMENT - 1;
}
$result = $ref_store . str_pad((int)$last_id + 1, 5, '00000', STR_PAD_LEFT);
return $result;
}
public static function generateReferenceOrderID($order_id){
$ref_store = "SQSP";
$result = $ref_store . str_pad((int)$order_id, 5, '00000', STR_PAD_LEFT);
return $result;
}
}
AdminOrdersController.php:
$employee = new Employee((int)Context::getContext()->cookie->id_employee);
//passing order message into extra_vars for use in PaymentModule
$payment_module->validateOrder(
(int)$cart->id, (int)$id_order_state,
$cart->getOrderTotal(true, Cart::BOTH),
$payment_module->displayName,
$this->l('Manual order -- Employee:').' '.
substr($employee->firstname, 0, 1).'. '.$employee->lastname,
array(Tools::getValue('order_message')), null, false,
$cart->secure_key);
Hoping someone can help me with a Call to undefined function error I am getting in the following code:
$query = \FreePBX::Database()->query('SELECT model, dns, buttons, loadimage
FROM sccpdevmodel
WHERE dns > 0
ORDER BY model');
$res = $query->fetchAll();
foreach ($res as $row) {
$modelData['model'][] = $row[0];
$modelData['dns'][] = $row[1];
$modelData['buttons'][] = $row[2];
$modelData['loadimage'][] = $row[3];
}
return $modelData;
This first part seems to be ok then I get the error $modelData = sccp_get_model_data(); in this line.
<?php
$modelData = sccp_get_model_data();
$numModels = count($modelData['model']);
$addonData = sccp_get_addon_data();
$numAddons = count($addonData['model']);
?>
Any advice?
Here is a link to the source file if anyone can help please?
https://github.com/Cynjut/SCCP_Manager/tree/master
Make sure you are using an include or require statement to load your functions. I found what seems to be the full code base for this on github and didn't see where it loads in the functions you use.
Not sure if you want them conditionally loaded, but if not, you can include 'functions.inc.php'; at the top of the file that needs to use them.
I have lots of images into mysql database, which are painted so: <img src="/PrintImage.php?$id&width&height&quality" />.
The problem is that for each image, I am doing a call to the database through a class. To explain it better, here is the code:
edited: posted entirely class code
HTML View (example):
<img src="/PrintImage.php?id=10&width=120&height=120&quality=100" />
<img src="/PrintImage.php?id=20&width=120&height=120&quality=100" />
PrintImage.php
<?php
include_once($_SERVER['DOCUMENT_ROOT'].'/php/classes/Galerias.php');
$a = new \Galerias();
$i = $_GET['i'];
$w = $_GET['w'];
$h = $_GET['h'];
$q = $_GET['q'];
$a->Pintar($i, $w, $h, $q);
unset($a);
Gallery.php:
<?php
namespace Galerias;
include_once 'Database.php';
include_once 'Utils.php';
use \Database;
use \Utils;
class Galerias {
private $img_max_width = 1024;
private $img_max_height = 768;
private $img_quality = 85;
function __construct(){
$this->Database = new Database();
$this->Utils = new Utils();
}
public function Pintar($id, $width, $height, $quality){
$query = "select (select titulo from imagenes where id=$id) as titulo, (select imagen from imagenes where id=$id) as imagen";
$data = $this->Database->GetData($query);
$titulo = $data[0]['titulo'];
$tmp = $data[0]['imagen'];
$dataimg = $this->Utils->formatImage("string", $tmp, $width, $height, false);
$mime = $dataimg[1];
header("Content-type: $mime");
header("Content-Disposition: inline; filename=$titulo");
imagejpeg($dataimg[0], null, $quality);
}
}
Database.php:
<?php
namespace Database;
include_once 'Utils.php';
use \Utils;
class Database {
private $host = "localhost";
private $user = "user";
private $pass = "pass";
private $daba = "database";
private $link;
public $Utils;
function __construct(){
$this->Open();
$this->Utils = new Utils();
}
function __destruct(){
error_log('Database destruct');
}
private function Open(){
$this->link = mysql_connect($this->host, $this->user, $this->pass);
error_log('open succeeded');
mysql_select_db($this->daba, $this->link) or $this->Utils->newEx("Class Database->Open(): ".mysql_error());
}
private function Close(){
mysql_close($this->link) or $this->Utils->newEx("Class Database->Close(): ".mysql_error());
error_log('close succeeded');
}
public function GetData($query){
$data = array();
$query = mysql_query($query) or $this->Utils->newEx("Class Database->GetData(): ".mysql_error(), true);
while( $result = mysql_fetch_array($query) ){
$data[] = $result;
}
$this->FreeResults($query);
return $data;
}
public function InsertData($query){
if( !mysql_query($query) ){
$this->Utils->newEx("Class Database->InsertData(): ". mysql_error(), true);
return false;
}
return true;
}
public function DeleteData($query){
if( !mysql_query($query) ){
$this->Utils->newEx("Class Database->DeleteData(): ". mysql_error(), true);
return false;
}
return true;
}
public function FreeResults($res = null){
if( !is_null($res) ) mysql_free_result($res);
}
}
I am calling database too many times, because I have to load ~50/100 images per gallery.
The question is, how can I do this task efficiently? Thanks in advance
Your real question is: How can i minimize the amount of calls to the database.
The data is stored in the database so will have to do a call to retrieve the data. However what do you need to ask yourself, do i really need to ask the question every time?
In your current object model, you retrieve the unique data for every picture only when the object is created. This will add one call every time you want to read the info. This is a very common mistake to do and is something that (as you already realized) doesn't scale at all.
What you need is to make the object already have the data before the call. There is numerous ways to do this. Object Factories, Cached object, memcache, redis the list can be as long as there is active developers out there.
I'm inviting you to try to think outside the box and find a solution. Because if you understand the problem and solve it you will get a better grasp of object models and the pitfalls.
Lets take it again, are you sure you need to make the database call in the construction of the object? If you know the subset of the data you need, you should ask for in bulk. That will remove a lot of queries to the database.
Perhaps the Galerias could have function where you grab a lot of Pintar in one go?
I know this isn't a "do this" answer and probably will get down voted. But at least try :).
Also: Never use the query parameters $_GET $_POST directly without sanitize them first!!
Finally, I got the logical system to reduce -considerably- the amount of calls to the database. Before, I used a PHP file as image src to print images (with its headers, etc) directly from the database. This is a terrible fail. The problems to solve were:
I need to use a PHP file as image src, passing an ID, width, height and quality. And, of course, it has to be a friendly uri. So I can't use base64 encoding to print images. It has to be a PHP file (other file, other process, it isn't connected to the first one).
I use a shared hosting, the thinking of loading -nice- extensions like memcache is not viable.
Problem 2 tells me that I can't save images (or other data) in any place to use along the site. (It's wrong).
What I did (after thinking and searching and thinking...) is to use $_SESSION to store, previous serializing, all images. So, I solved all the problems. Now, have to look for a valid logic to populate the code. The result looks like this:
// Session Cache Class (static)
namespace SessionCache;
ini_set('memory_limit', '256M'); // this is the best issue of this system
session_start();
class SessionCache {
// todo: add the possible to expire the session
private static $SessionName = 'SessionCache';
public static function Check($name){
if( empty($_SESSION[self::$SessionName]) ) return false;
if( empty($_SESSION[self::$SessionName][$name]) ) return false;
else return true;
}
public static function Set($name, $data){
if( self::Check($name) ) return;
$data = serialize($data);
$_SESSION[self::$SessionName][$name] = $data;
}
public static function Get($name){
if( self::Check($name) ){
$data = unserialize($_SESSION[self::$SessionName][$name]);
return $data;
}
else return null;
}
public static function Flush($name){
if( self::Check($name) ) unset($_SESSION[self::$SessionName][$name]);
}
public static function Destroy(){
session_destroy();
}
}
Now, the (current) logic:
// Images Class. Here I use some extra stuff. Feel free to read the comments
namespace AdminPanel;
include_once 'SessionCache.php';
include_once 'Database.php';
include_once 'Utils.php';
use \AdminPanel\Database;
use \AdminPanel\Utils;
use SessionCache\SessionCache;
use stdClass;
class Patrocinios {
private $cache_name = 'Patrocinadores';
private $img_width = 225;
private $img_height = 70;
private $img_quality = 100;
public function __construct(){
$this->Database = new \AdminPanel\Database();
$this->Utils = new \AdminPanel\Utils();
}
private function CreateImageCache(){
if( SessionCache::Check($this->cache_name) ) return null;
$query = "select * from patrocinadores";
$this->Database->Open();
$data = $this->Database->GetData($query);
$this->Database->Close();
$patros = new stdClass();
if( count($data) > 0 ){
for( $i=0; $i<count($data); $i++ ){
$id = $data[$i]['id'];
$nombre = $data[$i]['nombre'];
$uri = $data[$i]['web'];
$mimetype = $data[$i]['tipo'];
$imagedata = $data[$i]['imagen'];
$patros->patro[$id] = new stdClass();
$patros->patro[$id]->id = $id;
$patros->patro[$id]->nombre = $nombre;
$patros->patro[$id]->uri = $uri;
$patros->patro[$id]->mimetype = $mimetype;
$patros->patro[$id]->data = $imagedata; // the image BLOB
}
}
SessionCache::Set($this->cache_name, $patros);
}
public function GetPatrocinadores(){ // this method is the only one called from the main view
$this->CreateImageCache();
$patros = SessionCache::Get($this->cache_name);
return $patros;
}
public function Pintar($id, $width, $height, $quality){ // this method is called from the PHP file used to print the images
if( !SessionCache::Check($this->cache_name) ) $patros = $this->GetPatrocinadores();
else $patros = SessionCache::Get($this->cache_name);
$dataimg = $this->Utils->formatImage("string", $patros->patro[$id]->data, $width, $height); // creates new image with desired measures and quality
header('Content-Type: '.$patros->patro[$id]->mimetype);
header('Content-Length: '.strlen($patros->patro[$id]->data));
imagejpeg($dataimg[0], null, $quality);
}
}
I just have a variable with the name of the session object ($cache_name). First I check if exists (from previous call). If not, I populate a stdClass() object with the information from the database and store it in the session.
<ul id="ulPatrocinadores">
<?php
include_once $_SERVER['DOCUMENT_ROOT'].'/php/classes/Patrocinios.php';
$p = new \AdminPanel\Patrocinios();
$patros = $p->GetPatrocinadores();
$str = '';
foreach( $patros as $value ){
foreach( $value as $patro ){
$id = $patro->id;
$nombre = str_replace(" ", "_", $patro->nombre);
$web = $patro->uri;
$str .= '<li>';
$str .= '<img src="/'.$nombre.'_pat-i='.$id.'&w=225&h=70&q=85" alt="'.$nombre.'" />';
}
}
echo $str;
?>
</ul>
Above is the main view which images are printed. Note that anchors and image sources goes to the PHP file that calls to the method Pintar(). I use a RewriteRule to redirect it.
<?php
include_once '../scripts/PrintPartner.php';
$a = new \AdminPanel\Patrocinios();
$i = $_GET['i'];
$w = $_GET['w'];
$h = $_GET['h'];
$q = $_GET['q'];
$a->Pintar($i, $w, $h, $q);
unset($a);
And so, I finally achieve it. I don't know if this is a good system because $_SESSION is relational to php memory_limit, but after two days of thinking about it, I couldn't get something better.
What I achieve:
Before: one query for each image to the database. Now: one query for all images for one session (or the time that I could need).
Keep of the friendly uris with creating of the image file on the fly as needed, still using a PHP file as image src.
A good system to reduce calls to the database, also using a shared hosting.
Hope this experience helps someone.
well i'm writing a php code to edit tags and data inside those tags but i'm having big trouble getting my head around the thing.
basically i have an xml file similar to this but bigger
<users>
<user1>
<password></password>
</user1>
</users>
and the php code i'm using to try and change the user1 tag is this
function mod_user() {
// Get global Variables
global $access_level;
// Pull the data from the form
$entered_new_username = $_POST['mod_user_new_username'];
$entered_pass = $_POST['mod_user_new_password'];
$entered_confirm_pass = $_POST['mod_user_confirm_new_password'];
$entered_new_roll = $_POST['mod_user_new_roll'];
$entered_new_access_level = $_POST['mod_user_new_access_level'];
// Grab the old username from the last page as well so we know who we are looking for
$current_username = $_POST['mod_user_old_username'];
// !!-------- First thing is first. we need to run checks to make sure that this operation can be completed ----------------!!
// Check to see if the user exist. we just use the normal phaser since we are only reading and it's much easier to make loop through
$xml = simplexml_load_file('../users/users.xml');
// read the xml file find the user to be modified
foreach ($xml->children() as $xml_user_get)
{
$xml_user = ($xml_user_get->getName());
if ($xml_user == $entered_new_username){
// Set array to send data back
//$a = array ("error"=>103, "entered_user"=>$new_user, "entered_roll"=>$new_roll, "entered_access"=>$new_access_level);
// Add to session to be sent back to other page
// $_SESSION['add_error'] = $a;
die("Username Already exist - Pass");
// header('location: ../admin.php?page=usermanage&task=adduser');
}
}
// Check the passwords and make sure they match
if ($entered_pass == $entered_confirm_pass) {
// Encrypt the new password and unset the old password variables so they don't stay in memory un-encrytped
$new_password = hash('sha512', $entered_pass);
unset ($entered_pass, $entered_confirm_pass, $_POST['mod_user_new_password'], $_POST['mod_user_confirm_pass']);
}
else {
die("passwords did not match - Pass");
}
if ($entered_new_access_level != "") {
if ($entered_new_access_level < $access_level){
die("Access level is not sufficiant to grant access - Pass");
}
}
// Now to load up the xml file and commit changes.
$doc = new DOMDocument;
$doc->formatOutput = true;
$doc->perserveWhiteSpace = false;
$doc->load('../users/users.xml');
$old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0);
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($entered_new_username, $old_user);
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
}
when run with just the username entered for change i get this error
Catchable fatal error: Argument 1 passed to DOMNode::replaceChild() must be an instance of DOMNode, string given, called in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 252 and defined in E:\xampp\htdocs\CGS-Intranet\admin\html\useraction.php on line 201
could someone explain to me how to do this or show me how they'd do it.. it might make a little sense to me to see how it's done :s
thanks
$entered_new_username is a string so you'll need to wrap it with a DOM object, via something like$doc->createElement()
$xml_old_user = $doc->getElementsByTagName('users')->item(0)->getElementsByTagName($current_username)->item(0)->replaceChild($doc->createElement($entered_new_username), $old_user);
This may not be quite right, but hopefully it points you in the correct direction.
alright got it writing and replacing the node that i want but i have ran into other issues i have to work out (IE: it's replacing the whole tree rather then just changing the node name)
anyway the code i used is
// For initial debugging - to be deleted
if ($old_user == $current_username)
echo "old username found and matches";
// Check the variables to see if there is something to change in the data.
if ($entered_new_username != "") {
try {
$new_node_name = $doc->createElement($entered_new_username);
$old_user->parentNode->replaceChild($new_node_name, $old_user);
}
catch (DOMException $e) {
echo $e;
}
echo "Username is now: " . $current_username;
}
if ($new_pass != "") {
$current_password = $doc->getElementsByTagName($current_user)->item(0)->getElementsByTagName('password')->item(0)->nodeValue;
//$replace_password = $doc
}
$doc->save('../users/users.xml');