Newer to creating php functions and mysql. I have function to connect to a database db_conect_nm(). This is in file db_fns.php, and contains the user and password to connect to my db. I created this to have a more secure db connection. I had it in a directory outside of public_html, and got error PHP Warning: mysqli::mysqli() [<a href='mysqli.mysqli'>mysqli.mysqli</a>]: (28000/1045): Access denied for user 'negoti7'#'localhost' (using password: NO) ...
Looking for solutions, I saw comments which indicated that perhaps this db user did not have permission from root, so I put it in a directory in public_html, same directory as program where it is being called. I still get the same error.
I have tested the connection without being a function, and it works. What is wrong, and why is this not working as a function? I really want to put this somewhere other than in the code directly and make it more secure.
db_fns.php content
<?php
//Database server
$host= 'localhost';
$nm_name= 'myname_databasename'; //sanitized data
$nm_user= 'myname_dbusername';
$nm_pword= 'password';
// db connect to nm database
function db_connect_nm()
{
$nm_connect = new mysqli($host, $nm_user, $nm_pword, $nm_name);
if (!$nm_connect)
throw new Exception('Could not connect to NM database currently');
else
return $nm_connect;
}
?>
I call it from nm_functions.php, db_fns.php is included there.
nm_functions.php
<?php require_once('sanitizedpathto/db_fns.php');
......some code
$conn_nm = db_connect_nm();
$result_sub = $conn_nm->query("select * from subscribers where uname='$username'");
.... more code
?>
Any ideas?
Thanks
Could it be the scope of the variables? Have you tried defining the variables inside the function to test?
Like this:
<?php
// db connect to nm database
function db_connect_nm()
{
//Database server
$host= 'localhost';
$nm_name= 'myname_databasename'; //sanitized data
$nm_user= 'myname_dbusername';
$nm_pword= 'password';
$nm_connect = new mysqli($host, $nm_user, $nm_pword, $nm_name);
if (!$nm_connect)
throw new Exception('Could not connect to NM database currently');
else
return $nm_connect;
}
?>
You are :
first, declaring some variables, outside of any functions
then, trying to use those variables from inside a function.
Variables declared outside of a function are not, by default, visible from inside that function.
About that, you should read the Variable scope section of the manual.
Two possible solutions :
Use the global keyword, to import those variables into your function -- making them visible
Or define constants, instead of variables -- which makes sense, for configuration values.
In the first case, your function would look like this :
// db connect to nm database
function db_connect_nm()
{
// Make these outside variables visible from inside the function
global $host, $nm_user, $nm_pword, $nm_name;
$nm_connect = new mysqli($host, $nm_user, $nm_pword, $nm_name);
if (!$nm_connect)
throw new Exception('Could not connect to NM database currently');
else
return $nm_connect;
}
And, in the second case, you'd first define the constants :
define('DB_HOST', 'localhost');
define('DB_DBNAME', 'myname_databasename');
define('DB_USER', 'myname_dbusername');
define('DB_PASSWORD', 'password');
And, then, use those constants :
// db connect to nm database
function db_connect_nm()
{
$nm_connect = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_DBNAME);
if (!$nm_connect)
throw new Exception('Could not connect to NM database currently');
else
return $nm_connect;
}
This second solution is probably more clean than the first one ;-)
Your connection variables are not scoped inside the connection function. You either need to pass them as parameters to the function (preferable) or use the global keyword inside to reference them:
function db_connect_nm($host, $nm_user, $nm_pword, $nm_name)
{
$nm_connect = new mysqli($host, $nm_user, $nm_pword, $nm_name);
//etc...
}
Alternate, not preferred:
function db_connect_nm()
{
global $host, $nm_user, $nm_pword, $nm_name;
$nm_connect = new mysqli($host, $nm_user, $nm_pword, $nm_name);
//etc...
}
Related
I am receiving the following error when loading my index page:
Fatal error: Call to a member function prepare() on a non-object in /Applications/MAMP/htdocs/parse/helloworld/helloworld/libraries/Database.php on line 32
I will place all of the relevant code below, sorry for the length but it should be fairly straight forward to read. The short version is I am practicing PDO and PHP classes so I am remaking an existing project I had on a different machine. (which is why a there is a lot of calls in the index file which acts more like a controller).
I am pulling my hair out here because it works on my other machine and from what i can tell the two projects are identical... I am just getting this error. I had this in my previous project, but that was because I had misspelled the database in the config file... I am 100% positive I did not do that again but I don't know what else I missed -- clearly the PDO class is not being made if I var_dump it returns null... Any and all help would be greatly appreciated (especially if it is in regards to my PDO class style I am just following a blog which seemed to make sense when it worked).
EDIT:
After some debugging it was clear that the try block in the database class was failing because a connection could not be established. This was clear after running $this->error = $e->getMessage() which returned:
string(119) "SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/Applications/MAMP/tmp/mysql/mysql.sock' (2)"
As the accepted answer below states the error indicates localhost trying to connect via a unix socket and mysqld not being able to able to accept unix socket connections.
So the original error leads to the ultimate question of: how do you connect to a unix socket when mysqld is not accepting unix socket connections and/or why does mysqld not accept unix socket connections?
End EDIT.
This is my (relevant) PDO class:
<?php
class Database {
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
private $dbh;
private $error;
private $stmt;
public function __construct() {
// Set DSN
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
// Set options
$options = array (
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
// Create a new PDO instanace
try {
$this->dbh = new PDO ($dsn, $this->user, $this->pass, $options);
} // Catch any errors
catch ( PDOException $e ) {
var_dump($dsn);
$this->error = $e->getMessage();
}
}
public function query($query) {
$this->stmt = $this->dbh->prepare($query);
}
This is the index file that gets called
<?php
require('core/init.php');
//Create objects...
$type = new Type;
$post = new Post;
$group = new Group;
$follower = new Follower;
//Create template object
$template = new Template('templates/front.php');
$template->types = $type->getAllTypes();
$template->groups = $group->getAllGroups();
$template->posts = $post->getAllPosts();
$template->replies = $post->getReplies();
$template->followers = $follower->getAllFollowers();
echo $template;
and these are the other relevant files:
config --
<?php
//DB Params
define("DB_HOST", "localhost");
define("DB_USER", "root");
define("DB_PASS", "root");
define("DB_NAME", "dobbletwo");
define("SITE_TITLE", "Welcome To Dooble!");
init --
//include configuration
require_once('config/config.php');
//helper functions
require_once('helpers/photo_helper.php');
require_once('helpers/system_helper.php');
//Autoload Classes
function __autoload($class_name){
require_once('libraries/'.$class_name . '.php');
}
for the sake of brevity (which may be far gone at this point I will only show one of the classes i load to prove that I am constructing the db(type, post, group, follower, template...)
<?php
class Type {
//Initialize DB variable
public $db;
/*
* Constructor
*/
public function __construct(){
$this->db = new Database;
}
the mysql libraries seem to interpret localhost as meaning you want to connect via a unix socket. your error indicates your mysqld isn't setup to accept unix socket connections.
to connect via tcp/ip instead, change define("DB_HOST", "localhost"); to define("DB_HOST", "127.0.0.1");
There is something, as a newbie, that a I want to understand about About database connections.
I am starting off from a tutorial on PHP which has this structure:
Connect.php:
<?php
$username = "dbusername";
$password = "dbpassword";
$host = "localhost";
$dbname = "dbname";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try
{
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
}
catch(PDOException $ex)
{
die("Failed to connect to the database: " . $ex->getMessage());
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
header('Content-Type: text/html; charset=utf-8');
session_start();
?>
Login.php:
<?php
require("connect.php");
// some code not important for this question,
//that handles login with a session…
?>
various_file_in_the_login_system.php:
<?php
require("connect.php");
// some code that checks if user is logged in with session_ …
// some code that does need the database connection to work
?>
All other files also contain that require("connect.php"); line. It works, but I just don’t know what these connection request to the server – I may not be using the right vocabulary -- end up doing to the server. They are superfluous if the connection is not timed out, are they not?
I found a post which talked about doing a singleton for PDO, and a post which makes me feel like never using persistent connections in my life.
Does this design causes excessive connection churning?
Perhaps servers can handle very many request for connection per second, perhaps a server has its own internal persistent connection mode, or implements connection pooling…
Or the PDO object handle the problem of asking connection too often for no reason…
PDO + Singleton : Why using it?
What are the disadvantages of using persistent connection in PDO
This is what I can recommend for your database connection:
Make a class for the connection:
class Database{
private static $link = null ;
public static function getConnection ( ) {
if (self :: $link) {
return self :: $link;
}
$dsn = "mysql:dbname=social_network;host=localhost";
$user = "user";
$password = "pass";
self :: $link = new PDO($dsn, $user, $password);
return self :: $link;
}
}
Then you can get the connection like this:
Database::getConnection();
The Singleton Pattern is hard to scale - However, I think it will probably be fine for your needs. It takes a lot of load off your database.
I don't think you will be able to avoid the multiple includes.
There is a php.ini setting for prepending a file to every script -> http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file
How about you change to
require_once('connect.php');
in all locations?
Also you should probably remove session_start() and HTTP header logic from a section of code that has to do with establishing a DB connection. This simply does not make sense there.
I am having a strange error while creating objects. While I create an objects in chronological orders as classed defined, it is going on good. But when I change the order or object creation, it gives error.
The classes I am using are as follows:
<?php
class dbClass{
private $dbHost, $dbUser, $dbPass, $dbName, $connection;
function __construct(){
require_once("system/configuration.php");
$this->dbHost = $database_host;
$this->dbUser = $database_username;
$this->dbPass = $database_password;
$this->dbName = $database_name;
}
function __destruct(){
if(!$this->connection){
} else{
mysql_close($this->connection);
}
}
function mysqlConnect(){
$this->connection = mysql_connect($this->dbHost, $this->dbUser, $this->dbPass) or die("MySQL connection failed!");
mysql_select_db($this->dbName,$this->connection);
}
function mysqlClose(){
if(!$this->connection){
} else{
mysql_close($this->connection);
}
}
}
class siteInfo{
private $wTitle, $wName, $wUrl;
function __construct(){
require_once("system/configuration.php");
$this->wTitle = $website_title;
$this->wName = $website_name;
$this->wUrl = $website_url;
}
function __destruct(){
}
function showInfo($keyword){
if($keyword=="wTitle"){
return $this->wTitle;
}
if($keyword=="wName"){
return $this->wName;
}
if($keyword=="wUrl"){
return $this->wUrl;
}
}
}
?>
The problem is when I create objects in the following order, it is working perfectly:
include("system/systemClass.php");
$dbConnection = new dbClass();
$dbConnection -> mysqlConnect();
$siteInfo = new siteInfo();
But if I change the order to following
include("system/systemClass.php");
$siteInfo = new siteInfo();
$dbConnection = new dbClass();
$dbConnection -> mysqlConnect();
It gives error!
Warning: mysql_connect() [function.mysql-connect]: Access denied for user '#####'#'localhost' (using password: NO) in /home/#####/public_html/#####/system/systemClass.php on line 19
MySQL connection failed!
Your problem comes from the unconventional use of a configuration file that is read ONCE, but should be used in all classes.
When you instantiate the dbclass first, the configuration is read, probably variables get assigned, and you use these in the constructor.
After that, instantiating siteinfo will not read that file again, which is less harmful, because you only end up with an empty object that does return a lot of null, but does work.
The other way round, you get a siteinfo object with all the info, but a nonworking dbclass.
My advice: Don't use a configuration file that way.
First step: Remove the require_once - you need that file to be read multiple times.
Second step: Don't read the file in the constructor. Add one or more parameters to the constructor function and pass the values you want to be used from the outside.
Info: You can use PHP code files that configure stuff, but you shouldn't define variables in them that get used outside. This will work equally well:
// configuration.php
return array(
'database_host' => "127.0.0.1",
'database_user' => "root",
// ...
);
// using it:
$config = require('configuration.php'); // the variable now has the returned array
I didn't realize there was an OO way to use mysqli, so I built a class called DB. During __construct it takes the hostname, username, password, and database name. Given the following code:
$myDB = new DB("localhost", "user", "password", "database");
$myDBConnect = $myDB->connect();
if(!$myDBConnect) {
echo "<strong>The following error has occurred: " . $myDB->getError();
}
The variable obviously contains FALSE because this if statement is currently returning TRUE. Here is the method from the DB class:
public function connect() {
// Create connection
$this->dbConnx = mysqli_connect($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
if(mysqli_connect_errno($this->dbConnx)) {
$this->dbError = mysqli_error($this->dbConnx);
return false;
}
}
I'm not getting any error detail. I tried adding or die(mysqli_error()); in the connect method, but it always just outputs the text from the file that $myDB is instantiated in. I also tried variations on the error reporting code, including having no argument in mysqli_connect_errno() and using $this->dbError = mysqli_connect_error() with and without the connection argument.
Is this needlessly complicating the OO way to use mysqli? or am I missing something simple that will allow me to move on using the code I've already got?
Thanks in advance for your time.
if is not variable
if(!$myDBConnect) {
^--remove variable sign here
EDIT:
your connection should be
$myDB = new mysqli("localhost", "user", "password", "database");
Maybe you forgot the return true statement in the "connect" method?
Also you should use PDO.
Your connect() function is returning false on failure and nothing on success, so it will always fail the if. Try adding return true; at the end of that function.
I have, what I think/hope, is a very simple PHP question. I have made a class to create database connections and issue common queries. I am trying to open two different database connections by creating two objects from the same database class. My code is as follows:
//connect to DB
$dbh = new DB('localhost', 'db1', 'user', 'pass');
//check connection
if(!$dbh->getStatus()) {
echo($dbh->getErrorMsg());
die;
}//if
//connect to DB 2
$dbh2 = new DB('localhost', 'db2', 'user', 'pass');
//check connection
if(!$dbh2->getStatus()) {
echo($dbh2->getErrorMsg());
die;
}//if
However, when I call a method for $dbh to query the database, it attempts to query with the credentials for $dbh2.
My DB constructor is below:
class DB {
function __construct($host, $db, $user, $pass) {
$dbh = mysql_connect($host, $user, $pass);
mysql_select_db($db, $dbh);
if(!$dbh) {
$this->status = false;
$this->error_msg = 'Error connecting to database: '.mysql_error();
return(false);
}//if
$this->dbh = $dbh;
$this->resetStatusAndErrors();
return($dbh);
}//_construct
Simple solution: Use PDO instead. It does exactly what you want, probably has better syntax and implementation and abstracts the interface for DB access.
You're not showing the full class, but the most probable reason is that you are not passing the current connection to the mysql_query() command.
Save $dbh as a property of your class, and add the connection parameter to each mysql_ function that accepts it:
mysql_query("SELECT * from.......", $this->dbh);
That said, if you are building this from scratch at the moment, take a look whether you don't want to use PDO instead. It is better, safer and more flexible than the old style mySQL library.
If you are using the mysql extension (using either mysqli or PDO_MySQL would give both superior performance, more features, etc., so check that for new code), you'll have to store the database handle, and use that on every mysql_* call:
class db {
....
function query($query){
return mysql_query($query, $this->dbh);//notice the second parameter.
}
}