I have this php file. The lines marked as bold are showing up the error :"mysql_query() expecets parameter 2 to be a resources. Well, the similar syntax on the line on which I have commented 'No error??' is working just fine.
function checkAnswer($answerEntered,$quesId)
{
//This functions checks whether answer to question having ques_id = $quesId is satisfied by $answerEntered or not
$sql2="SELECT keywords FROM quiz1 WHERE ques_id=$quesId";
**$result2=mysql_query($sql2,$conn);**
$keywords=explode(mysql_result($result2,0));
$matches=false;
foreach($keywords as $currentKeyword)
{
if(strcasecmp($currentKeyword,$answerEntered)==0)
{
$matches=true;
}
}
return $matches;
}
$sql="SELECT answers FROM user_info WHERE user_id = $_SESSION[user_id]";
$result=mysql_query($sql,$conn); // No error??
$answerText=mysql_result($result,0);
//Retrieve answers entered by the user
$answerText=str_replace('<','',$answerText);
$answerText=str_replace('>',',',$answerText);
$answerText=substr($answerText,0,(strlen($answerText)-1));
$answers=explode(",",$answerText);
//Get the questions that have been assigned to the user.
$sql1="SELECT questions FROM user_info WHERE user_id = $_SESSION[user_id]";
**$result1=mysql_query($sql1,$conn);**
$quesIdList=mysql_result($result1,0);
$quesIdList=substr($quesIdList,0,(strlen($quesIdList)-1));
$quesIdArray=explode(",",$quesIdList);
$reportCard="";
$i=0;
foreach($quesIdArray as $currentQuesId)
{
$answerEnteredByUser=$answers[$i];
if(checkAnswer($answerEnteredByUser,$currentQuesId))
{
$reportCard=$reportCard+"1";
}
else
{
$reportCard=$reportCard+"0";
}
$i++;
}
echo $reportCard;
?>
Here is the file connect.php. It is working just fine for other PHP documents.
<?php
$conn= mysql_connect("localhost","root","password");
mysql_select_db("quiz",$conn);
?>
$result2=mysql_query($sql2,$conn);
$conn is not defined in the scope of your function (even if you're including the connect.php file before that.
although you can use the suggestion to make $conn global, it's usually better practice to not make something global just for the sake of globalizing it.
i would instead pass $conn to the function as a parameter. this way, you can reuse the same function you wrote with different connections.
$conn isn't declared as a global so the function cannot access it, as it is not defined within it.
Either simply add
global $conn;
To the top of the function to allow it to access the $conn.
Or you can remove $conn from the mysql_query() statement. By default it will use the current connection (as mentioned in the comments below).
Where do you set $conn? It doesn't look like you set a connection within that function
Related
This question already has answers here:
What does the variable $this mean in PHP?
(11 answers)
Closed 3 years ago.
I have this code:
class database{
var $conn;
function connect($server,$host_username,$host_password,$host_database){
$server = 'localhost';
$host_username = 'root';
$host_password = '';
$host_database = 'e-vent system db';
$conn= new mysqli($server,$host_username,$host_password,$host_database);
if ($conn->connect_error){
die("db connection error:". $conn->connect_error);
}
}
function read_db($table,$condition){
$read="SELECT * FROM ".$table." ".$condition;
$read_result=$conn->query($read);
if(!$read_result){
echo "select error:". mysqli_error($conn);
}
return $result;
}
}
And I get this error:
Notice: Undefined variable: conn in C:\xampp\htdocs\E-vent\database.php on line 19
How can I make the $conn variable visible to the read_db function?
Change this line:
if ($conn->connect_error){
to
if ($this->conn->connect_error){
means replace all:
$conn->query
to
$this->conn->query
Explanation: If you want to use a variable in the entire class scope then you have to use the class variable instead of local (function) scope variable. In this line:
$conn->connect_error
the $conn is a local variable whose scope is limited to the function only, but when you use $this->conn, it means you are referring to the class variable which is accessible in all the member functions of the class.
And put all the content of connect function in the class constructor so that this connection is initialized at the time of class initialization. (Thanks #Magnus for pointing this)
Have a look on the variable scope, it will help you to understand the concept.
You are using class variable into a function, it's basic rule of oops that to use class variable we must access it using object. so class variable can be used under same class using $this.
so your code must be:
$this->$conn->connect_error
Instead of
$conn->connect_error
You need to make the connection object a property of the class, using $this - specifically, $this->conn. Assign your connection-object to that property. You then need to reference $this->conn everywhere else within that class, instead of using $conn.
class database {
public $conn;
public function connect($server, $host_username, $host_password, $host_database)
{
$server = 'localhost';
$host_username = 'root';
$host_password = '';
$host_database = 'e-vent system db';
$this->conn = new mysqli($server, $host_username, $host_password, $host_database);
if ($this->conn->connect_error) {
die("db connection error:". $this->conn->connect_error);
}
}
public function read_db($table, $condition)
{
$read = "SELECT * FROM ".$table." ".$condition;
$read_result = $this->conn->query($read);
if (!$read_result) {
echo "select error:". mysqli_error($this->conn);
}
return $result;
}
}
That being said, a couple of things to note,
You are not using parameterized queries, and are injecting variables directly into the query -- this is not secure, and you should use a prepared statement with placeholders.
The connect() method takes in all the arguments, but you still overwrite them in the function. Alternatives are to remove the arguments, remove the hard-coded values, or use the hard-coded values if the argument is empty.
You should not return errors to the user while in production. During development, this is fine - but in production, hide them, log them and display something generic to the user instead (like a 500 page, or some other error page).
You should specify if your properties and methods are public, protected, static or private.
Better to use public access modifier without using var. What does PHP keyword 'var' do?.
Class properties must be defined as public, private, or protected. If declared using var, the property will be defined as public.
And also The PHP 4 method of declaring a variable with the var keyword is still supported for compatibility reasons (as a synonym for the public keyword). In PHP 5 before 5.1.3, its usage would generate an E_STRICT warning.
PHP variables - http://php.net/manual/en/language.variables.variable.php
Need to change as follows
class database{
public $conn
And here
$this->conn= new mysqli($server,$host_username,$host_password,$host_database);
And here
if ($this->conn->connect_error){
die("db connection error:". $this->conn->connect_error);
}
And here as well
$read_result=$this->conn->query($read);
I have a simple question. I'm not too good at programming yet but is this safe and correct?
Currently I am using functions to grab the username, avatars, etc.
Looks like this:
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
echo "Connection failed: " . $e->getMessage();
}
config.php ^^
function getUsername($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT username FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$name = $stmt->fetch();
return $name["username"];
}
function getProfilePicture($userid) {
require "config/config.php";
$stmt = $conn->prepare("SELECT profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$image = $stmt->fetch();
return $image["profilepicture"];
}
Is this correct and even more important, is this safe?
Yes, it's safe with respect to SQL injections.
Some other answers are getting off topic into XSS protection, but the code you show doesn't echo anything, it just fetches from the database and returns values from functions. I recommend against pre-escaping values as you return them from functions, because it's not certain that you'll be calling that function with the intention of echoing the result to an HTML response.
It's unnecessary to use is_int() because MySQL will automatically cast to an integer when you use a parameter in a numeric context. A non-numeric string is interpreted as zero. In other words, the following predicates give the same results.
WHERE id = 0
WHERE id = '0'
WHERE id = 'banana'
I recommend against connecting to the database in every function. MySQL's connection code is fairly quick (especially compared to some other RDBMS), but it's still wasteful to make a new connection for every SQL query. Instead, connect to the database once and pass the connection to the function.
When you connect to your database, you catch the exception and echo an error, but then your code is allowed to continue as if the connection succeeded. Instead, you should make your script die if there's a problem. Also, don't output the system error message to users, since they can't do anything with that information and it might reveal too much about your code. Log the error for your own troubleshooting, but output something more general.
You may also consider defining a function for your connection, and a class for your user. Here's an example, although I have not tested it:
function dbConnect() {
try {
$conn = new PDO("mysql:host=". $mysql_host .";dbname=" . $mysql_db ."", $mysql_username, $mysql_password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch(PDOException $e)
{
error_log("PDO connection failed: " . $e->getMessage());
die("Application failure, please contact administrator");
}
}
class User {
protected $row;
public function __construct($userid) {
global $conn;
if (!isset($conn)) {
$conn = dbConnect();
}
$stmt = $conn->prepare("SELECT username, profilepicture FROM accounts WHERE id = ? LIMIT 1");
$stmt->execute([$userid]);
$this->row = $stmt->fetch(PDO::FETCH_ASSOC);
}
function getUsername() {
return $this->row["username"]
}
function getProfilePicture() {
return $this->row["profilepicture"]
}
}
Usage:
$user = new User(123);
$username = $user->getUsername();
$profilePicture = $user->getProfilePicture();
That looks like it would work assuming that your config file is correct. Because it is a prepared statement it looks fine as far as security.
They are only passing in the id. One thing you could do to add some security is ensure that the $userid that is passed in is the proper type. (I am assuming an int).
For example if you are expecting an integer ID coming in and you get a string that might be phishy (possible SQL injection), but if you can confirm that it is an int (perhaps throw an error if it isn't) then you can be sure you are getting what you want.
You can use:
is_int($userid);
To ensure it is an int
More details for is_int() at http://php.net/manual/en/function.is-int.php
Hope this helps.
It is safe (at least this part of the code, I have no idea about the database connection part as pointed out by #icecub), but some things you should pay attention to are:
You only need to require your config.php once on the start of the file
You only need to prepare the statement once then call it on the function, preparing it every time might slow down your script:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. - PHP Docs
(Not an error but I personally recommend it) Use Object Orientation to help organize your code better and make easier to mantain/understand
As stated by #BHinkson, you could use is_int to validate the ID of the user (if you are using the IDs as numbers)
Regarding HTML escaping, I'd recommend that you already register your username and etc. HTML escaped.
hoping someone can help me, I am having the following error, looked online and tried a load of things but can't seem to figure it out, error:
Fatal error: Call to undefined method mysqli::mysqli_fetch_all() in C:\xampp\htdocs\cyberglide\core-class.php on line 38
heres my code:
<?php
class Core {
function db_connect() {
global $db_username;
global $db_password;
global $db_host;
global $db_database;
static $conn;
$conn = new mysqli($db_host, $db_username, $db_password, $db_database);
if ($conn->connect_error) {
return '<h1>'."Opps there seems to be a problem!".'</h1>'.'<p>'."Your Config file is not setup correctly.".'</p>';
}
return $conn;
}
function db_content() {
//this requires a get, update and delete sections, before its complete
$conn = $this->db_connect();
if(mysqli_connect_errno()){
echo mysqli_connect_error();
}
$query = "SELECT * FROM content";
// Escape Query
$query = $conn->real_escape_string($query);
// Execute Query
if($result = $conn->query($query)){
// Cycle through results
while($row = $conn->mysqli_fetch_all()){
//echo $row->column;
}
}
}
}
$core = new Core();
?>
I am trying to create a db_connect function, which I want to be able to call anywhere on the site that needs a database connection, I am trying to call that function on a function within the same class, I want it to grab and display the results from the database. I am running PHP 5.4.7, I am calling the database on a blank php file which includes a require to include the class file, then using this at the moment $core->db_content(); to test the function. I am building this application from scratch, running from MySQLi guides (not used MySQLi before, used to use normal MySQL query's) so if I am doing anything wrong please let me know, thanks everyone.
mysqli_fetch_all is a method of a mysqli_result, not mysqli.
So presumably it should be $result->fetch_all()
References:
http://php.net/manual/en/mysqli-result.fetch-all.php
Important: keep in mind mysqli_result::fetch_all returns the whole result set not a row as you assume in your code
There are three problems I see here.
while($row = $conn->mysqli_fetch_all()){
The method name is fetch_all() when used in the OOP way.
fetch_all() should be used with the $result object
fetch_all() is only available when the mysqlnd driver is installed - it frequently is not.
Reference
Only $result has that method. If you want to use it in a while loop use fetch_assoc(). fetch_all() returns an associative array with all the data already.
while($row = $result->fetch_assoc()){
}
thanks all, its working fine now, i had it as while($row = $conn->fetch_assoc()){
} before and changed to what i put above, but dident see it should of been $result instead of $conn, thanks for pointing that out.
i have a php site
in index file include connect to db function :
function connect(){
mysql_connect("localhost", "user", "pass") or die(mysql_error());
mysql_select_db("database");
}
and i use this function in everywhere i need connection
for example:
<?php
connect();
$lastnews_sql = mysql_query("SELECT text,time FROM small WHERE active='0' ORDER BY time DESC LIMIT 10");
if(mysql_num_rows($lastnews_sql)) {
while($Result123 = mysql_fetch_object($lastnews_sql)) {
?>
and use this selection:
text; ?>
in end of using :
<?php
}
}
mysql_close();
?>
there are more than 10 connect(); and mysql_close(); in index file
so there are too many connection error in index file
how can i optimize this metod ?
A singleton pattern seems to suit this down to the ground.
class Database
{
private static $instance;
public function getInstance()
{
if(self::$instance == null)
{
// Create a connection to the database.
// NOTE: Use PDO or mysqli. mysql is deprecated.
}
return self::$instance;
}
}
Use
In your classes, instead of calling connect, assuming you're using a PDO object, you could do something like:
$db = Database::getInstance();
$statement = $db->prepare("SELECT * FROM tblName WHERE val = :val");
$statement->bindParam(":val", $value);
$statement->execute();
$result = $statement->fetchAll();
Why this pattern ?
A Singleton pattern has the advantage of only having one instance of itself exist at one time. That means that you will only ever create one connection to the database.
Setting this up
Okay, so the first thing you want to do is to make a new file, let's call it Database.php. Inside Database.php, you want to pretty much write the code that I've written, only do NOT use mysql_*. Have a look at the PDO tutorial that I have provided, on how to connect to a database using a PDO object, and then you put that connection code inside the if statement, so it might look something like:
if(self::$instance == null)
{
self::$instance = new PDO('mssql:host=sqlserver;dbname=database', 'username', 'password');
}
Then, to use it in another class, put a require statement at the top. Something like:
require_once('Database.php');
Finally, look at the code I put in the use section, above. That is how you use it in your class.
Useful links
PDO Tutorial : http://php.net/manual/en/book.pdo.php
Singleton Pattern : http://www.oodesign.com/singleton-pattern.html
This question already has answers here:
Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?
(3 answers)
Closed 2 years ago.
I have a file that corrals my re-usable functions into one file (functions.php). It's include_once()'d on every page that needs it. I'm getting an error when my custom functions are trying to access a MySQL connection outside their own scope. The source is a bit like this:
<?php
// functions.php
$connect = mysql_connect("localhost", "user", "pass") or die("MySQL said: ".mysql_error());
mysql_select_db("database", $connect) or die("MySQL said: ".mysql_error()); // no error
/* ... */
function getmotd($user) {
$query = "SELECT cid FROM `users`
WHERE id = ".$user;
$query = mysql_query($query, $connect); // error occurs here, $connect is not a valid MySQL link-resource
/* ... */
}
?>
Why can't my function access variables declared above it's scope? I can get a successful connection by reproducing $connect's declaration within the function.
Any insight into how I can work around this or what I'm doing wrong here?
You can't access $connect because it is outside the scope of the function; that is, PHP can only see the variables within the function when it's inside it. You could use the global keyword to let PHP know the variable is outside the function's scope as Kemal suggests, but I think a better course of action is to pass the connection into the function. This will give you better encapsulation. If you learn to write your functions (and later classes) with passing in the resources and data you need (a practice known as "dependency injection"), you'll find you have cleaner and more maintainable code. Here's the example:
function getmotd($db, $user) {
$query = "SELECT cid FROM users WHERE id = " . (int)$user;
$result = mysql_query($query, $db);
/.../
}
$connect = mysql_connect(...);
mysql_select_db(...);
$motd = getmotd($connect, $user);
Hope this helps.
Use the global keyword.
Example
function getmotd($user) {
global $connect;
$query = "SELECT cid FROM `users`
WHERE id = ".$user;
$query = mysql_query($query, $connect); // error occurs here, $connect is not a valid MySQL link-resource
/* ... */
}
You can also do it like this
function getmotd($user) {
$query = "SELECT cid FROM `users`
WHERE id = ".$user;
$query = mysql_query($query, $GLOBALS['connect']); // error occurs here, $connect is not a valid MySQL link-resource
/* ... */
}
If you want to make re-usable codes, you'd probably be better off with OOP. Create a class for the database, and add some properties for the database info, and access them from the functions by using the this keyword.