SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Enthusiast
    Join Date
    Aug 2004
    Location
    somewhere
    Posts
    74
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    database connection inside a function

    Hello,

    I'm getting the following errors:

    Warning: mysqli_connect() [function.mysqli-connect]: (28000/1045): Access denied for user 'test@'localhost' (using password: NO) in

    Warning: mysqli_error() expects exactly 1 parameter, 0 given in
    Unable to connect to MySQL:

    I have three files working with each other; config, functions, and view.

    config
    PHP Code:
    <?php

    /* Config */

    //Database Host
    $db_host 'localhost';

    //Database Name
    $db_database 'test';

    //Database Username
    $db_user 'test';

    //Database Password
    $db_pass 'test';

    ?>
    functions
    PHP Code:
    <?php
    //Connect To Database
    function connect_to_database()
    {
        
        require_once 
    'config.php';
        global 
    $db_host;
        global 
    $db_database;
        global 
    $db_user;
        global 
    $db_pass;

        
    $db_server mysqli_connect($db_host$db_user$db_pass);
        if (!
    $db_server) die("Unable to connect to MySQL: " mysqli_error());
        
    mysqli_select_db($db_server$db_database)
        or die(
    "Unable to select database: " mysqli_error());

    }
    ?>
    view
    PHP Code:
    <?php

    require_once 'functions.php';

    connect_to_database();
    ?>
    I'm failing to understand why the contents of connect_to_database() don't work. If I take the contents of connect_to_database() and put it in the view file, the connection works and I can print the contents of the database.

    view with the contents of connect_to_database()
    PHP Code:
    <?php

        
    require_once 'config.php';
        global 
    $db_host;
        global 
    $db_database;
        global 
    $db_user;
        global 
    $db_pass;

        
    $db_server mysqli_connect($db_host$db_user$db_pass);
        if (!
    $db_server) die("Unable to connect to MySQL: " mysqli_error());
        
    mysqli_select_db($db_server$db_database)
        or die(
    "Unable to select database: " mysqli_error());
    ?>
    This works.

  2. #2
    SitePoint Evangelist priti's Avatar
    Join Date
    Aug 2006
    Location
    India
    Posts
    488
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I think $db_host,$db_database defined global var are empty. In 'functions.php' try printing those vars.

    As you have defined DB related var in config.Hence, when you include this file those var comes in it's local scope. Any reason you are defining them as global?.

    Hope this helps.

  3. #3
    SitePoint Enthusiast derokorian's Avatar
    Join Date
    Jan 2011
    Location
    Ohio
    Posts
    57
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you are to use global, you would include both the config file and functions file from the other file. Otherwise as priti stated, including the file form within the function brings those vars into scope, and there should be no reason to call GLOBAL on them.

  4. #4
    I solve practical problems. bronze trophy
    Michael Morris's Avatar
    Join Date
    Jan 2008
    Location
    Knoxville TN
    Posts
    2,053
    Mentioned
    66 Post(s)
    Tagged
    0 Thread(s)
    First, Executable code as a configuration file is a bad practice. I recommend using ini files - the code to parse over them is internal to the PHP engine so no performance loss. Information on the formatting is in the entry for parse_ini_file

    Second, unless you have a specific reason to use the mysqli extension, use pdo. There is currently a debate on whether or not to remove all non pdo libraries from PHP core by default, relagating them to pecl libraries for inclusion by those remaining projects that need them, starting with PHP 5.4. Whether or not this will occur is not settled, but signs point to probably.

    The major advantage of PDO is it is object oriented, allowing you to extend it. This is my extension to it.

    Code php:
    <?php
    namespace Gazelle;
     
    /**
     * Gazelle core database extends the PDO library.
     * @author Michael
     *
     */
    class Database extends \PDO {
     
    	/**
    	 * CONSTRUCT. Convert the configuration array into a DSN and pass that down to
    	 * PDO.
    	 * @param array $config
    	 */
    	public function __construct( array $config ) {
    		assert ($config['database'] && $config['user'] && $config['password']);
     
    		if (isset($config['dsn'])) {
    			// If a DSN is set use it without question.
    			parent::__construct($config['dsn'], $config['user'], $config['password']);
    		} else {
    			// Otherwise hash the vars we were given into a DSN and pass that.
    			$params = array(
    				'driver' => isset($config['driver']) ? $config['driver'] : 'mysql',
    				'database' => $config['database'],
    				'user' => $config['user'],
    				'password' => $config['password'],
    				'server' => isset($config['server']) ? $config['server'] : 'localhost',
    				'port' => isset($config['port']) ? $config['port'] : '3306'
    			);
     
    			// Start underlying PDO library.
    			parent::__construct("{$params['driver']}:dbname={$params['database']};host={$params['server']};port={$params['port']}", 
    				$params['user'],
    				$params['password']
    			);
    		}
    	}
     
    	/**
    	 * Prepare and execute sql with it's parameters.
    	 * @param string $sql
    	 * @param array|null $params
    	 */
    	protected function prepareAndExecute( $sql, $params = null ) {
     
    		$s = $this->prepare( $sql );
     
    		if ( is_array($params)) {
    			$s->execute( $params );
    		} else {
    			$s->execute();			
    		}
     
    		if ($s->errorCode() != '00000') {
    			throw new DatabaseException ( print_r($s->errorInfo(), true) );
    		}
     
    		return $s;
    	}
     
    	/**
    	 * Run a query and return the result in a form suited to the result.
    	 * You should be able to predict the return based on the text of
    	 * your query, but if unsure use query all.
    	 * 
    	 * For any query you need to issue multiple times you will realize
    	 * better performance by using #prepare and then executing the
    	 * received statement object.
    	 * 
    	 * @param string sql statement - required
    	 * @param array sql parameters - optional
    	 * 
    	 * @return mixed
    	 */
    	public function quickQuery($sql, $params ) {		
    		$s = $this->prepareAndExecute($sql, $params);
     
    		$columns = $s->columnCount();
    		$rows = $s->rowCount();
     
    		// A single column and row - return the value found.
    		if ( $rows == 1 && $columns == 1 ) {
    			return $s->fetchColumn();
    		} 
    		// A pair of columns we presume column 1 is the index and column 2 the value.
    		// We maintain this format even if there was only a single row.
    		else if ( $columns == 2 ) {
    			$r = array();
    			while ($row = $s->fetch( parent::FETCH_NUM )){	
    				$r[$row[0]] = $row[1];
    			}
    			return $r;
    		} 
    		// Single row - return it.
    		else if ( $rows == 1 ) {
    			return $s->fetch( parent::FETCH_ASSOC );
    		} 
    		// Single column - return it
    		else if ( $columns == 1 ) {
    			return $s->fetchAll( parent::FETCH_COLUMN );
    		}
    		// Just shoot back everything.
    		else {
    			return $s->fetchAll( parent::FETCH_ASSOC );
    		}
    	}
     
    	/**
    	 * Get all results of a query. Unlike quickQuery, queryAll
    	 * doesn't try to figure out your intent - it returns
    	 * a full associative array.
    	 * 
    	 * @param string $sql
    	 * @param array $params
    	 */
    	public function queryAll( $sql, array $params = array() ) {
    		$s = $this->prepareAndExecute($sql, $params);
    		return $s->fetchAll( parent::FETCH_ASSOC );	
    	}
    }

    The relevant section of my configuration file:

    Code:
      db[class] = Gazelle\Database
      ;db[dsn] 
      db[driver] = mysql				
      db[user] = 'user'
      db[password] = 'password'  ; This is just a sample - not my real password of course.
      db[server] = localhost
      db[port] = 3306
      db[database] = gazelle
    This allows my outside code to read like this..

    Code php:
    $config = parse_ini_file('path/to/config.ini');
     
    $db = new \Gazelle\Database($config['db']);
     
    $result = $db->quickQuery( 'SELECT name FROM user WHERE id = 3' );

    Hope this helps.

  5. #5
    SitePoint Wizard lorenw's Avatar
    Join Date
    Feb 2005
    Location
    was rainy Oregon now sunny Florida
    Posts
    1,104
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I may be totally off base but I thought you could only declare global one time.
    Code:
    global $db_database, $db_user, $db_pass;
    Anyway, thats the way I do it.
    What I lack in acuracy I make up for in misteaks

  6. #6
    SitePoint Enthusiast derokorian's Avatar
    Join Date
    Jan 2011
    Location
    Ohio
    Posts
    57
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you include the file within the function with the variables and then you call GLOBAL on those vars, its replacing those vars with values that were outside the scope of the function... and they are not defined outside the scope of the function so it just makes them empty. Atleast I think thats why.

  7. #7
    Keeper of the SFL StarLion's Avatar
    Join Date
    Feb 2006
    Location
    Atlanta, GA, USA
    Posts
    3,748
    Mentioned
    73 Post(s)
    Tagged
    0 Thread(s)
    priti is correct.

    require_once (as well as include, include_once, and require), load the script and run it at the local level. You do not need to call for the global definition of those variables.

    i'm guessing test and localhost are predefined in your php.ini as the database connection defaults, which is why it appeared to read those variables but not the password.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •