This is a general example.
The application has 3 files.
conn.inc.php -- setting up the database connection
<?php
$db_host = "localhost";
$db_username = "root";
$db_pass = "";
$db_name = "hmt";
$conn = new mysqli($db_host, $db_username, $db_pass, $db_name);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
func.inc.php -- file including functions
<?php
function load_module($module_name){
$sqlCmd = "SELECT content FROM modules WHERE name='$module_name' LIMIT 1";
$result = $conn->query($sqlCmd);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$module_footer = $row["content"];
}
}else {
echo 'Error while loading module '.$module_name;
}
return $result;
$result->free_result();
}
?>
index.php -- the main page to display content
<?php
include 'conn.inc.php';
include 'func.inc.php';
if (!isset($_GET['page_name'])) { // if page_name is not set then reset it to the homepage
$page_name = 'module_footer';
}else{
$page_name = $_GET['module_footer'];
}
$module_content = load_module($page_name);
echo $module_content;
?>
Now my goal was to include functions inside the func.inc.php file and database into conn.inc.php, so as to keep separate and easier to read in the future.
My problem now is that the $conn variable declared in conn.inc.php cannot be used inside the function and it can't get my head around how to use it. I even tried using GLOBALS with no success.
The error for the files is this:
Notice: Undefined variable: conn in ./func.inc.php on line 4
Fatal error: Call to a member function query() on a non-object in ./func.inc.php on line 4
Which (I assume) is because the $conn variable is not in a global scope.
Now my question is. How can I keep the nested files but have the functions working? Is there a mistake in my approach or is it not possible to use a nested call to a mysql object?
Eventually you'll want to get into object-oriented coding but for now lets make what you have a little prettier.
When including files, you'll want to avoid things like global variables. They sound great, but end up being a pain when handling scope. So instead include a set of functions to call.
conn.inc.php
function getConnection(){
$db_host = "localhost";
$db_username = "root";
$db_pass = "";
$db_name = "hmt";
$conn = new mysqli($db_host, $db_username, $db_pass, $db_name);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
return $conn;
}
Then function.inc.php
<?php
function load_module($module_name){
$sqlCmd = "SELECT content FROM modules WHERE name='$module_name' LIMIT 1";
//Here is where we get our database connection.
$conn = getConnection();
$result = $conn->query($sqlCmd);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$module_footer = $row["content"];
}
}else {
echo 'Error while loading module '.$module_name;
}
return $result;
$result->free_result();
}
And finally finish up with your index page the way it is. So now, any page that wants a database connection will need to include the conn.inc.php and simply call getConnection() to get a mysqli connection object.
Think of your program as being a series of individual functions working together. And eventually you'll get to it being a series of objects working together. Nothing should be just floating off in global space. Try to encapsulate everything in some sort of function or object to be called over and over with consistent results.
You'd have to do something like this:
$conn = '';
function connect() {
global $conn;
... do db stuff
}
But this is usually bad practice. A more common method is to use a singleton object to "carry" your db handle, and you new that singleton everywhere you need to do DB operations.
function do_something() {
$conn = new DBSingleton();
... do db stuff
}
Related
This question already has answers here:
Call to a member function prepare() on a non-object PHP Help [duplicate]
(8 answers)
Closed 6 years ago.
I have a following code
//dsn.php
//Object Oriented way
$servername = "localhost";
$username = "root";
$password = "password";
$dbname = "database";
//check connection
$conn = new mysqli($servername, $username, $password, $dbname);
if($conn->connect_error) {
die("could not connect:".$conn->connect_error);
}
//index.php
include 'dsn.php';
function a() {
$sql = "sql command";
$result = $conn->query($sql);
//working
$conn->close();
}
function b() {
$sql = "sql command";
$result = $conn->query($sql);
//not working
$conn->close();
}
This will display warning and notice that says:
Warning: mysqli::query(): Couldn't fetch mysqli
Notice: Trying to get property of non-object
Warning: mysqli::close(): Couldn't fetch mysqli
However this one works:
include 'dsn.php';
function a() {
$sql = "sql command";
$result = $conn->query($sql);
//working
$conn->close();
}
function b() {
include $dsn.php
$sql = "sql command";
$result = $conn->query($sql);
//working
$conn->close();
}
How do I use just one include file for DSN and use repeatedly on other functions?
EDIT
sorry I forgot to mention
function a($conn) {}
function b($conn) {}
I passed the variable $conn but it still displays the warning and notice I mentioned above
When you include a file, you can imagine that in the background it is just copy-pasting that code into the current document.
There are 2 problems with your code...
The $conn variable is not in scope inside function a or b.
Even if it was in scope and accessible, you are closing the connection after each query. A better way to do it is to open the connection, run all queries and close the connection when it is no longer needed.
The second piece of code you gave works because it is creating a new variable $conn inside of b(), but this is not ideal as it will create a new database connection every time you execute that function.
Something like this may suit your needs:
include 'dsn.php';
function a($conn) {
$sql = "sql command";
$result = $conn->query($sql);
return $result;
}
function b($conn) {
$sql = "sql command";
$result = $conn->query($sql);
return $result;
}
$aResult = a($conn);
$bResult = b($conn);
$conn->close();
Notice that we are only including 'dsn.php' once, and then passing around that existing connection to the functions that need it.
This is very simple. On page load, the connection file is included which makes $conn the connection object available to the remaining codes. The $conn is used by the functiona() and it is then closed at the end of the function. $conn->close(); destroys the database connection object means, $conn is no more object hence it should not be treated as object. But the Function b() is treatong it as database connection object and resulting into error.
But if you again include the connection file, inside the function b() then $conn becomes available to the function as local object. And works as it should.
Do not close the $conn() on the any function till you are dealing with DB.
function a() {
incDbConnectionFile();
$sql = "sql command";
$result = $conn->query($sql);
//working
$conn->close();
}
function b() {
incDbConnectionFile();
$sql = "sql command";
$result = $conn->query($sql);
//working
$conn->close();
}
function incDbConnectionFile() {
include 'dsn.php';
}
Can any of you guys help me to reorganize this code? I'll try to explain the problem below.
I have a db_connection.php wich includes the following (just my db info and don't worry, i am just using it locally):
<?php
try {
$db = new PDO('mysql:host=localhost;dbname=webappeind;charset=utf8','root','');
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>
But the problem is i have the following file that also includes my db info, but i do not know how to reorganize my code to get it working with my separate php file.
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "webappeind";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
$sql = "SELECT * FROM zoekopdrachten ORDER BY titel DESC LIMIT 3";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output gegevens van elke rij
while($row = $result->fetch_assoc()) {
echo "<div class='recenttoegevoegd'>"."<a href='#'>".$row["titel"]."</a>"."</div>";
}
} else {
echo "0 resultaten";
}
?>
You can put the connection information in a separate file called, say, conn.php where you mention the code related to database opening, including credentials. Then, in the calling file, say putdata.php, you use the "require" or "require_once" command to include that conn.php. Let the conn.php file return a connection. Somewhat like this :
<?php
function GetMyConn() {
$server_name = "localhost";
$db_name = "db_name_goes_here";
$db_user = "user_name_goes_here";
$db_pass = "password_goes_here_muahhhaa";
$db_full_addr = "mysql:host=" . $server_name . ";" . "dbname=" . $db_name;
$MyConn = new PDO($db_full_addr, $db_user, $db_pass);
$MyConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $MyConn;
}
?>
In the calling file, you would say, something like :
require_once "GetConn.php";
$MyConnHere = GetMyConn();
$SqlHere = "Sql Statemetn goes here...."
$SqlHere2 = $MyConnHere->prepare($SqlHere);
$SqlHere2->execute();
Also, I suggest you can download the source code of some open source PHP application, such as mantissa, and see how they have organized their code files, folders and settings.
I´m trying to connect to my database with PDO and show some blogposts on a page.
However I´m getting this error message:
Fatal error: Uncaught exception 'PDOException' with message 'invalid
data source name' in index.php on line 61...
I´ve been searching for help but really can´t figure out what is wrong so if anyone have any idea it is much appreciated!
I have a separate connect.inc.php file which is included in the index.php file.
This is the connect.inc.php file:
<?php
class DB extends PDO
{
function database_connection() {
$db_host = "localhost";
$db_name = "blogdata";
$db_user = "username";
$db_pass = "password";
try {
global $db_host, $db_name, $db_user, $db_pass;
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
}
catch(PDOException $e) {
die( 'Query failed: ' . $e->getMessage() );
}
}
}
?>
And this is the section in the index.php file which is pointed out in the error message:
<?php
require 'connect.inc.php';
$db = new DB('blogdata');
$query = "SELECT * FROM blogposts";
if ($result = $db->query($query)) {
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
echo '
<section id="content">
<article class="post_title"><h3> ', $row['title'],' </h3></article>
<article class="post_message"> ', nl2br ($row['message']),' </article>
<article class="post_time"> ',$row['time'],' </article>
</section>
';
}
} ;
?>
Gotcha.
For some reason you are extending your class from PDO. So, your 'blogdata' is taken as a DSN.
Just get rid of your DB class and use raw PDO
connect.inc.php:
<?php
$db_host = "localhost";
$db_name = "blogdata";
$db_user = "username";
$db_pass = "password";
$db = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
index.php:
<?php
require 'connect.inc.php';
$query = "SELECT * FROM blogposts";
$result = $db->query($query);
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
Why are you declaring your DB variables global after initialising them? I can't test it but if memory serves that'll pull in existing values from global, overwriting the ones you've just declared.
I disagree with not using an inherited class though - being able to write a custom constructor means you can set all modes and attributes once and then just call the custom constructor to have it done automatically. Much cleaner than having to do it every time.
For future references, you could keep the DB class and refer to the following solution that hasn't much to do with the php class:
enter link description here
I'm in a bit of a pickle with freshening up my PHP a bit, it's been about 3 years since I last coded in PHP. Any insights are welcomed! I'll give you as much information as I possibly can to resolve this error so here goes!
Files
config.php
database.php
news.php
BLnews.php
index.php
Includes
config.php -> news.php
database.php -> news.php
news.php -> BLnews.php
BLnews.php -> index.php
Now the problem with my current code is that the database connection is being made but my database refuses to be selected. The query I have should work but due to my database not getting selected it's kind of annoying to get any data exchange going!
config.php
<?php
$dbhost = "localhost";
$dbuser = "root";
$dbpass = "";
$dbname = "test";
?>
database.php
<?php
class Database {
//-------------------------------------------
// Connects to the database
//-------------------------------------------
function connect() {
if (isset($dbhost) && isset($dbuser) && isset($dbpass) && isset($dbname)) {
$con = mysql_connect($dbhost, $dbuser, $dbpass) or die("Could not connect: " . mysql_error());
$selected_db = mysql_select_db($dbname, $con) or die("Could not select test DB");
}
}// end function connect
} // end class Database
?>
News.php
<?php
// include the config file and database class
include 'config.php';
include 'database.php';
...
?>
BLnews.php
<?php
// include the news class
include 'news.php';
// create an instance of the Database class and call it $db
$db = new Database;
$db -> connect();
class BLnews {
function getNews() {
$sql = "SELECT * FROM news";
if (isset($sql)) {
$result = mysql_query($sql) or die("Could not execute query. Reason: " .mysql_error());
}
return $result;
}
?>
index.php
<?php
...
include 'includes/BLnews.php';
$blNews = new BLnews();
$news = $blNews->getNews();
?>
...
<?php
while($row = mysql_fetch_array($news))
{
echo '<div class="post">';
echo '<h2> ' . $row["title"] .'</h2>';
echo '<p class="post-info">Posted by | <span class="date"> Posted on ' . $row["date"] . '</span></p>';
echo $row["content"];
echo '</div>';
}
?>
Well this is pretty much everything that should get the information going however due to the mysql_error in $result = mysql_query($sql) or die("Could not execute query. Reason: " .mysql_error()); I can see the error and it says:
Could not execute query. Reason: No database selected
I honestly have no idea why it would not work and I've been fiddling with it for quite some time now. Help is most welcomed and I thank you in advance!
Greets
Lemon
The values you use in your functions aren't set with a value. You likely need to convert the variables used to $this->dbName etc or otherwise assign values to the variables used.
Edit for users comment about variables defined in config.php:
You really should attempt to get the data appropriate for each class inside that class. Ultimately your variables are available to your entire app, there's no telling at this point if the variable was changed by a file including config.php but before database.php is called.
I would use a debugging tool and verify the values of the variables or just var_dump() them before the call.
Your Database class methods connect and selectDb try to read from variables that are not set ($dbhost, $dbname, $con, etc). You probably want to pass those values to a constructor and set them as class properties. Better yet, look into PDO (or an ORM) and forget creating your own db class.
This question already has answers here:
Giving my function access to outside variable
(6 answers)
Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?
(3 answers)
Closed 4 years ago.
Hello I am pretty sure they are in the same scope and am unsure why I am getting this error now as it was working before.
These are the other files in the same folder as
the php file :
dbh.php
recipeLookUp.php
It is line 9 that I am getting the error
this is the recipeLookUp.php
<?php
function lookup($sql,$column_name){
$results_search=array();
include_once 'dbh.php';
$results=mysqli_query($conn,$sql);
$resultsCheck = mysqli_num_rows($results);
if ($resultsCheck > 0) {
while ($row = mysqli_fetch_assoc($results)){
$info= $row[$column_name];
$results_search[]=$info;
}
return $results_search;
}
}
and here is my other file
<?php
$dbServername = 'localhost';
$dbUsername = 'root';
$dbPassword = '';
$dbName = 'Recipe';
$conn = mysqli_connect($dbServername,$dbUsername,$dbPassword,$dbName);
Im sure it probaly something small but I can't find it please help!!!
The include_once 'dbh.php'; within your function seems fishy. What are you gonna do if you have other functions which need to perform SQL queries as well?
Instead, I would put the include_once 'dbh.php'; outside (above) your function, and perhaps use require_once instead of include once. And then inside your function, put global $conn; above the mysqli_query call, so your $conn variable is defined there when you pass it along to mysqli_query.
However, if you are worried about creating unnecessary SQL connections (e.g. in case your lookup function is never actually called) I think it would be even better to put this in your dbh.php :
<?php
$conn = null;
function Query($sql)
{
global $conn;
if (!$conn) // will only connect if connection does not exist yet
{
$dbServername = 'localhost';
$dbUsername = 'root';
$dbPassword = 'xxxxxxxxxxx';
$dbName = 'Recipe';
$conn = mysqli_connect($dbServername,$dbUsername,$dbPassword,$dbName);
}
return mysqli_query($conn,$sql);
}
?>
And now in your main PHP file, or any PHP file where you include require_once 'dbh.php'; you can directly use Query($sql) to perform queries, which will take care of the connection itself (and only do so if necessary).