In the code given below, I am trying to modify it in such a way that the db connection variables are used from a config file. This should make the password more secure as I can restrict the config file's permissions.
Kindly let me know if there is a way by which I can modify the code to get the db variables from another file/config file?
class ActivitycodesCollection {
var $list, $err, $sql;
// --- Private variables for database access
var $_db_host = "######";
var $_db_username = "######";
var $_db_passwd = "######";
var $_db_name = "######";
function query ($where="") {
mysql_pconnect ($this->_db_host, $this->_db_username, $this->_db_passwd);
mysql_select_db ($this->_db_name);
$where = "WHERE " . $where;
$sql = "SELECT * FROM activitycodes $where";
$result = mysql_query ($sql);
$this->err = mysql_error();
$this->sql = $sql;
if (mysql_num_rows($result) > 0) {
while (list($id) = mysql_fetch_array ($result)) {
$this->list[$id] = new activitycodes($id);
}
}
}
}
I tried including the config.ini file in this class/function but it threw an error like
unexpected T_VARIABLE, expecting T_FUNCTION
Your code is hopelessly outdated.
1) Don't use var for properties, use private or protected.
2) Don't use mysql_* functions, use PDO.
3) Don't keep connection details inside the class. Just require PDO connection in constructor.
4) Don't trust any data outside your scope - don't allow just write some untrusted text into your SQL query (you do it by $where variable).
5) Read books. "PHP Objects, Patterns, and Practice" will help you now, and "Clean code" - little bit later.
Example:
class ActivitycodesCollection
{
private $list;
private $PDO;
private $table_name;
public function __construct(\PDO $PDO, $table_name)
{
$this->PDO = $PDO;
$this->table_name = $table_name;
}
public function fetchByParameter($parameter)
{
$query = $this->PDO->prepare("SELECT `id` FROM `{$this->table_name}` WHERE "
." some_field = :parameter");
if (!$query)
{
return false;
}
if (!($query->execute(array(':parameter'=> $parameter))))
{
return false;
}
$results = $query->fetchAll(\PDO::FETCH_ASSOC);
if (!empty($result))
{
foreach ($results as $result)
{
$id = $result['id'];
$this->list[$id] = new ActivityCodes($id);
}
}
}
}
Without seeing the "config" file it's not possible to say how to write a parser for it. A simple solution would be to write some php code which sets the variables - but if you include / require it, the variables will be set in global scope - not within the method. But you could eval(file_get_contents($config_file_path)) - which would set the variables in local scope at the risk of providing a method for code injection.
BTW there are a large number of issues with the code you have provided. Leaving aside the potential risk of SQL injection, if the method parameter is null / blank, then the query will be malformed (consider function query ($where="1"). Relying on specific column ordering is bad practice.
It's also hard to imagine how yo restrict access to this config file when the only practical means would be via suphp or base opendir.
Putting the SQL connection data in a separate files does not increase security at all. Actually, storing them in a file that does not have a .php extension makes it less secure since it might be accessible by a user while the code of a PHP file is not visible to any users. You also cannot use more restrictive permissions on the config file than on your PHP files since whatever user PHP is running as (usually the webserver user) needs to access them.
Simply store the connection data in a PHP file:
<?php
define('DB_HOST', '...');
define('DB_NAME', '...');
define('DB_USER', '...');
define('DB_PASS', '...');
Then include this file (outside your class definition) and use the constants when making the connection.
You can use parse_ini_file in you constructor.
class ActivitycodesCollection {
var $list, $err, $sql;
const CONFIG_FILE = 'config.ini';
// --- Private variables for database access
var $_db_host = ''
var $_db_username = '';
var $_db_passwd = '';
var $_db_name = '';
public function ActivitycodesCollection() {
$config = parse_ini_file(self::CONFIG_FILE);
$this->_db_host = $config['db']['host'];
//etc
}
public function query ($where="") {
mysql_pconnect ($this->_db_host, $this->_db_username, $this->_db_passwd);
mysql_select_db ($this->_db_name);
$where = "WHERE " . $where;
$sql = "SELECT * FROM activitycodes $where";
$result = mysql_query ($sql);
$this->err = mysql_error();
$this->sql = $sql;
if (mysql_num_rows($result) > 0) {
while (list($id) = mysql_fetch_array ($result)) {
$this->list[$id] = new activitycodes($id);
}
}
}
And the ini file should be something like that :
[db]
host = localhost
name = foo
user = bar
pass = baz
Related
I am using global variable in my function and after research I found that is a bad practice in PHP instead of that I should use dependency injection but I have problem when changing global to dependency injection. What problem about my code? Thanks for help.
update.php (global)
<?php
include 'db_data.php';
class robot{
public function robotUpdate($conn3){
public function robotUpdate($conn3){
global $nasa;
global $id;
$r_update="UPDATE robot_heartbeat SET last_process_id =$id WHERE nasa_id=$nasa";
$robot_u=$conn3->query($r_update);
}
main.php
<?php
include 'db_data.php';
include 'db_sat.php';
$sql = "SELECT * FROM satellite1.show_activity ";
$result=$conn1->query($sql); //get data from db 1
while($row = $result->fetch_assoc()) {
$sql2 = "INSERT INTO analysis_data.show_activity SET
show_activity_id='".$row["id"]."',
game_show_id='".$row["game_show_id"]."',
account_id='".$row["account_id"]."',
account_code='".$row["account_code"]."',
login_id='".$row["login_id"]."',
$result=$conn3->prepare($sql2); //copy data from db1 into db2
$result->execute();
}
$robot_u = new robot();
$nasa = '2';
$id = $row["id"];
$robot_u->robotUpdate($conn3);
I tried:
update.php (Dependency injection)
<?php
include 'db_data.php';
class robot{
public function robotUpdate($conn3,$nasa,$id){
public function robotUpdate($conn3){
$r_update="UPDATE robot_heartbeat SET last_process_id =$id WHERE nasa_id=$nasa";
$robot_u=$conn3->query($r_update);
}
**main.php**(dependency injection)
$robot_u = new robot();
$robot_u->robotUpdate($conn3,$nasa,$id); //call function first
$nasa = '2'; //inject value
$id = $row["id"];
the value is injected during the function call:
$robot_u->robotUpdate($conn3,$nasa,$id);
So swap them around:
$robot_u = new robot();
$nasa = '2'; //inject value
$id = $row["id"];
$robot_u->robotUpdate($conn3,$nasa,$id);
That said, I noticed you pass a db connection into the class, you might want to consider, if you re-use the same connection over and over in the class to add a constructor
function __construct( $db_connection ) {
$this->db_connection = $db_connection;
}
And create a new instance of the class and pass the db connection there
$robot_u = new robot( $conn3 );
And every time in that class when you need your db connection, use $this->db_connection instead of passing $conn3
Three are lots of free resources around PHP OOP on the internet, would suggest reading some of them :-)
I'm new learner in php OOP, I want to create a class function to get register users info, how can I do that?
class Functions{
public static function getUserInfo($user_id){
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."'");
$rows = mysql_fetch_array($sql);
if(mysql_num_rows($sql) >= 1){
return $rows;
}
}
}
to echo user's info:
$user = new Functions();
$user->getUserInfo($_SESSION['user_id']);
echo $user->user_email;
I got nuthing output with 'undefined property' message, what is the proper way to create function to retrieve user's info? thanks.
Maybe that?
class Functions{
public static function getUserInfo($user_id){
if(empty($user_id)) {
return null;
}
// connect to db
$sql = mysql_query("SELECT * FROM members WHERE user_id='".$user_id."' LIMIT 1");
if(mysql_num_rows($sql) > 0){
$row = mysql_fetch_array($sql, MYSQL_ASSOC);
// close connection to db
return $row;
}
// close connection to db
return null;
}
}
$userID = !empty($_SESSION['user_id']) ? (int)$_SESSION['user_id'] : null;
$user = Functions::getUserInfo($userID);
if($user !== null) {
echo $user['user_email'];
}
This is ony example, use mysqli_* or PDO to manage data in database.
mysql_fetch_array returns array, not object.
$user['user_email'] should work.
In general as you mentioned OOP I would say your code is using classes, but it is not OOP (if I understand correctly how you're going to structure it). What you do is simply wrapping procedural code into a class.
With OOP you need to structure code such a way that it has self-contained objects, so creating "Functions" class containing various utility methods is generally a bad idea. Consider e.g. creating User object instead.
For database abstraction I would recommend checking PDO (http://www.php.net/manual/en/class.pdo.php).
I have a function which is using recursion to call itself and I need to know the correct syntax for calling itself.
Note: I am using Object oriented programming technique and the function is coming from a class file.
Below is my function
// Generate Unique Activation Code
//*********************************************************************************
public function generateUniqueActivationCode()
{
$mysql = new Mysql();
$string = new String();
$activation_code = $string->generateActivationCode();
// Is Activation Code Unique Check
$sql = "SELECT activation_id FROM ". TABLE_ACTIVATION_CODES ." WHERE activation_code='$activation_code' LIMIT 1";
$query = $mysql->query($sql);
if($mysql->rowCount($query) > 0)
{
// This function is calling itself recursively
return generateUniqueActivationCode(); // <- Is this syntax correct in Oops
}
else
{
return $activation_code;
}
}
Should the code to call it recursively be
return generateUniqueActivationCode();
OR
return $this->generateUniqueActivationCode();
or if something else other than these 2 ways.
Please let me know.
You would need to call it with the $this variable since your function is part of the instance. So:
return $this->generateUniqueActivationCode();
PS: Why not just try both methods and see if it generates any errors?
Recursion is the COMPLETELY WRONG WAY TO SOLVE THIS PROBLEM
Unlike iteration you're filling up the stack, and generating new objects needlessly.
The right way to solve the problem is to generate a random value within a scope which makes duplicates very unlikely, however without some external quantifier (such as a username) to define the scope then iteration is the way to go.
There are further issues with your code - really you should be adding records in the same place where you check for records.
I am using Object oriented programming technique and the function is coming from a class file
Then it's not a function, it's a method.
And your code is susceptibale to SQL injection.
A better solution would be:
class xxxx {
....
public function generateUniqueActivationCode($id)
{
if (!$this->mysql) $this->mysql = new Mysql();
if (!$this->string) $this->string = new String();
$limit=10;
do {
$activation_code = $string->generateActivationCode();
$ins=mysql_escape_string($activation_code);
$sql="INSERT INTO ". TABLE_ACTIVATION_CODES ." (activation_id, activation_code)"
. "VALUES ($id, '$ins)";
$query = $mysql->query($sql);
if (stristr($query->error(), 'duplicate')) {
continue;
}
return $query->error() ? false : $activation_code;
} while (limit--);
return false;
}
} // end class
Just had a quick question for those of you knowledgeable about performance. I have created a "MySQL" class, and every time I perform a query, I create a new MySQL object. See below
public function get_am_sales() {
$mysql = new MySQL();
$mysql->connect();
$query = "some query";
$mysql->query($query);
$result = $mysql->return_assoc();
unset($mysql);
return $result;
}
public function get_pm_sales() {
$mysql = new MySQL();
$mysql->connect();
$query = "some query";
$mysql->query($query);
$result = $mysql->return_assoc();
unset($mysql);
return $result;
}
public function get_comp_sales() {
$mysql = new MySQL();
$mysql->connect();
$query = "some query";
$mysql->query($query);
$result = $mysql->return_assoc();
unset($mysql);
return $result;
}
$sales = new Sales();
$amSales = $sales->get_am_sales();
$pmSales = $sales->get_pm_sales();
$compSales = $sales->get_comp_sales();
The code above obviously works, but I was wondering if this is a performance hit since I open and close a connection with every function call. I have tried to implement the class using one connection, but I get errors. See below
public function connect() {
$this->mysql = new MySQL();
$this->mysql->connect();
}
public function get_am_sales() {
$query = "SELECT site_id, dly_sls AS am_sales, cov_cnt AS am_covers
FROM v_sales_yesterday
WHERE am_pm = 'AM'
GROUP BY site_id
ORDER BY site_id ASC";
$this->mysql->query($query);
$result = $this->mysql->return_assoc();
return $result;
}
public function get_pm_sales() {
$query = "SELECT site_id, dly_sls AS pm_sales, cov_cnt AS pm_covers
FROM v_sales_today
WHERE am_pm = 'PM'
GROUP BY site_id
ORDER BY site_id ASC";
$this->mysql->query($query);
$result = $this->mysql->return_assoc();
return $result;
}
public function get_comp_sales() {
$query = "SELECT business_date, site_id, dly_sls AS comp_sales
FROM v_sales_today_comp
WHERE am_pm = 'PM'
GROUP BY site_id
ORDER BY site_id ASC";
$this->mysql->query($query);
$result = $this->mysql->return_assoc();
return $result;
}
public function disconnect() {
unset($this->mysql);
}
$sales = new Sales();
$sales->connect();
$amSales = $sales->get_am_sales();
$pmSales = $sales->get_pm_sales();
$compSales = $sales->get_comp_sales();
$sales->disconnect();
Does the mysql connection close after the "connect" function executes? If deemed necessary, what would be the best way to keep the connection open (using an object oriented approach)? Please let me know if you need anymore details, and I appreciate the help in advance.
This is like totally unnecessary. You dont have to open and close connections for each query. Are you using some kind of a framework? If not you must as all frameworks have active records and DB helpers to make interacting with DB easier. THis would be a great article for you
http://net.tutsplus.com/tutorials/php/real-world-oop-with-php-and-mysql/
has just what youre lookng for.
In general, you only want to create your MySQL instance once during the execution of the application.
If you have an overarching Application object then you could just create your MySQL instance inside of the Application object and access it from there.
The other alternative is to create a Singleton object for your MySQL instance that is then accessed via an 'instance()' method.
This way you only open a single connection during the execution cycle of your php script and it will be discarded at the end of script execution.
So now your code looks like so:
$query = "SELECT * FROM users";
$rs = Mysql::instance()->query($query);
If you need working examples of how to setup a Singleton instance for your purposes you can look at:
GacelaPHP
Kohana Database Class
Zend DB Adapter
I have a html page that calls a php object to get some data back from the database. It works fine, but the script was getting unwieldy so I decided to break some of it out into a bunch of functions.
So I have the following files:
// htdocs/map.php
<?php
include("config.php");
include("rmap.php");
$id = 1;
$gamenumber = getGameNumber($id);
echo $gamenumber;
?>
// htdocs/config.php
<?php
$_PATHS["base"] = dirname(dirname(__FILE__)) . "\\";
$_PATHS["includes"] = $_PATHS["base"] . "includes\\";
ini_set("include_path", "$_PATHS[includes]");
ini_set("display_errors", "1");
error_reporting(E_ALL);
include("prepend.php");
?>
// includes/prepend.php
<?php
include("session.php");
?>
// includes/session.php
<?php
includes("database.php");
class Session {
function Session() {
}
};
$session = new Session;
?>
// includes/database.php
<?php
include("constants.php");
class Database {
var $connection;
function Database() {
$this->connection = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die(mysql_error());
mysql_select_db(DB_NAME, $this->connection) or die(mysql_error());
}
function query($query) {
return mysql_query($query, $this->connection);
}
};
/* Create database connection */
$database = new Database;
?>
// includes/rmap.php
<?php
function getGameNumber($id) {
$query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
$result = $database->query($query); // line 5
return mysql_result($result, 0);
}
?>
And constants has a bunch of defines in it (DB_USER, etc).
So, map.php includes config.php. That in turn includes prepend.php which includes session.php and that includes database.php. map.php also includes rmap.php which tries to use the database object.
The problem is I get a
Fatal error: Call to a member function on a non-object in
C:\Develop\map\includes\rmap.php on line 5
The usual cause of this is that the $database object isn't created/initialised, but if I add code to show which gets called when (via echo "DB connection created"; and echo "using DB connection";) they are called (or at least displayed) in the correct order.
If I add include("database.php") to rmap.php I get errors about redefining the stuff in constants.php. If I use require_once I get the same errors as before.
What am I doing wrong here?
$database is not in the scope of function GetGameNumber.
The easiest, though not necessarily best, solution is
<?php
function getGameNumber($id) {
global $database; // added this
$query = "SELECT gamenumber FROM account_data WHERE usernum=$id";
$result = $database->query($query); // line 5
return mysql_result($result, 0);
}
?>
global is deemed not perfect because it violates the principles of OOP, and is said to have some impact on performance because a global variable and all its members are added to the function's scope. I don't know how much that really affects performance, though.
If you want to get into the issue, I asked a question on how to organize such things a while back and got some good answers and links.
You need to include
global $database;
at the top of getGameNumber(), since $database is defined outside of getGameNumber itself
Your $database varibleis not accessible from the function's scope automatically. You might need to declare it as global $database; in the function.
Scopes in PHP are explained in the documentation: http://de3.php.net/manual/en/language.variables.scope.php
Please also mind that PHP 4and MySQL3 are out of support for a looooong time and might contain security problems and other unfixed issues.