Avatar of rgb192
rgb192Flag for United States of America asked on

Fatal error: Call to a member function real_escape_string() on a non-object in

from lynda.com php object oriented tutorial

class.Address.inc
<?php

/**
 * Physical address. 
 */
class Address {
  
  const ADDRESS_TYPE_RESIDENCE = 1;
  const ADDRESS_TYPE_BUSINESS = 2;
  const ADDRESS_TYPE_PARK = 3;
  
  // Address types.
  static public $valid_address_types = array(
    Address::ADDRESS_TYPE_RESIDENCE => 'Residence',
    Address::ADDRESS_TYPE_BUSINESS => 'Business',
    Address::ADDRESS_TYPE_PARK => 'Park',
  );
  
  // Street address.
  public $street_address_1;
  public $street_address_2;
  
  // Name of the City.
  public $city_name;
  
  // Name of the subdivison.
  public $subdivision_name;
  
  // Postal code.
  protected $_postal_code;
  
  // Name of the Country.
  public $country_name;
  
  // Primary key of an Address.
  protected $_address_id;
  
  // Address type id.
  protected $_address_type_id;
  
  // When the record was created and last updated.
  protected $_time_created;
  protected $_time_updated;
  
  /**
   * Constructor.
   * @param array $data Optional array of property names and values.
   */
  function __construct($data = array()) {
    $this->_time_created = time();
    
    // Ensure that the Address can be populated.
    if (!is_array($data)) {
      trigger_error('Unable to construct address with a ' . get_class($name));
    }
    
    // If there is at least one value, populate the Address with it.
    if (count($data) > 0) {
      foreach ($data as $name => $value) {
        // Special case for protected properties.
        if (in_array($name, array(
          'time_created',
          'time_updated',
        ))) {
          $name = '_' . $name;
        }
        $this->$name = $value;
      }
    }
  }
  
  /**
   * Magic __get.
   * @param string $name 
   * @return mixed
   */
  function __get($name) {
    // Postal code lookup if unset.
    if (!$this->_postal_code) {
      $this->_postal_code = $this->_postal_code_guess();
    }
    
    // Attempt to return a protected property by name.
    $protected_property_name = '_' . $name;
    if (property_exists($this, $protected_property_name)) {
      return $this->$protected_property_name;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined property via __get: ' . $name);
    return NULL;
  }
  
  /**
   * Magic __set.
   * @param string $name
   * @param mixed $value 
   */
  function __set($name, $value) {
    // Only set valid address type id.
    if ('address_type_id' == $name) {
      $this->_setAddressTypeId($value);
      return;
    }
    // Allow anything to set the postal code.
    if ('postal_code' == $name) {
      $this->$name = $value;
      return;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined or unallowed property via __set(): ' . $name);
  }
  
  /**
   * Magic __toString.
   * @return string 
   */
  function __toString() {
    return $this->display();
  }
  
  /**
   * Guess the postal code given the subdivision and city name.
   * @todo Replace with a database lookup.
   * @return string 
   */
  protected function _postal_code_guess() {
    $db = Database::getInstance();
    $mysqli = $db->getConnection();
    $sql_query = 'SELECT postal_code ';
    $sql_query.= 'FROM location ';
    
    $city_name = $mysqli->real_escape_string($this->city_name);
    $sql_query .= 'WHERE city_name = "' . $city_name . '" ';
    
    $subdivision_name = $mysqli->real_escape_string($this->subdivision_name);
    $sql_query .= 'AND subdivision_name = "' .$subdivision_name . '"';
    
    $result = $mysqli->query($sql_query);
    
    if ($row = $result->fetch_assoc()){
      return $row['postal_code'];
    }
  }
  
  /**
   * Display an address in HTML.
   * @return string 
   */
  function display() {
    $output = '';
    
    // Street address.
    $output .= $this->street_address_1;
    if ($this->street_address_2) {
      $output .= '<br/>' . $this->street_address_2;
    }
    
    // City, Subdivision Postal.
    $output .= '<br/>';
    $output .= $this->city_name . ', ' . $this->subdivision_name;
    $output .= ' ' . $this->postal_code;
    
    // Country.
    $output .= '<br/>';
    $output .= $this->country_name;
    
    return $output;
  }
  
  /**
   * Determine if an address type is valid.
   * @param int $address_type_id
   * @return boolean
   */
  static public function isValidAddressTypeId($address_type_id) {
    return array_key_exists($address_type_id, self::$valid_address_types);
  }
  
  /**
   * If valid, set the address type id.
   * @param int $address_type_id 
   */
  protected function _setAddressTypeId($address_type_id) {
    if (self::isValidAddressTypeId($address_type_id)) {
      $this->_address_type_id = $address_type_id;
    }
  }
}

Open in new window


class.Database.inc
<?php
/**
* mysqli database: only one connection is allowed
*/
class Database{
  private $_connection;
  //store the single instance
  private static $_instance;
  /**
  * get an instance of the database
  * @return Database
  * 
  */
  public static function getInstance(){
    if (!self::$_instance){
      self::$_instance= new self();
    }
    return self::$_instance;
  }
  /**
  * constructor
  */
  public function __construct(){
    $this->connection = new mysqli('localhost','username','pass','dbname');
    //error handling
    if (mysqli_connect_error()){
      trigger_error('Failed to connect to MySql: '.mysqli_connect_error(),E_USER_ERROR);
    }

  }
  
  
    /**
    * Empty clone magic method to prevent duplication.
    */
    private function __clone(){}
    /**
    * get the mysqli connection
    */
    public function getConnection(){
      return $this->_connection;
    }  
}

Open in new window


demo.php
<?php

require 'class.Address.inc';
require 'class.Database.inc';
echo '<h2>Instantiating Address</h2>';
$address = new Address;

echo '<h2>Setting properties...</h2>';
$address->street_address_1 = '555 Fake Street';
$address->city_name = 'Townsville';
$address->subdivision_name = 'State';
$address->country_name = 'United States of America';
$address->address_type_id = 1;
echo $address;

echo '<h2>Testing Address __construct with an array</h2>';
$address_2 = new Address(array(
  'street_address_1' => '123 Phony Ave',
  'city_name' => 'Villageland',
  'subdivision_name' => 'Region',
  'postal_code' => '67890',
  'country_name' => 'Canada',
));
echo $address_2;

Open in new window



ouput
Instantiating Address
Setting properties...

Fatal error: Call to a member function real_escape_string() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 134
PHP

Avatar of undefined
Last Comment
rgb192

8/22/2022 - Mon
Ray Paseur

Looks like the error occurs in here (this starts at line 128 of Address)

  protected function _postal_code_guess() {
    $db = Database::getInstance();
    $mysqli = $db->getConnection();
    $sql_query = 'SELECT postal_code ';
    $sql_query.= 'FROM location ';
    
    $city_name = $mysqli->real_escape_string($this->city_name);
    $sql_query .= 'WHERE city_name = "' . $city_name . '" ';
    
    $subdivision_name = $mysqli->real_escape_string($this->subdivision_name);
    $sql_query .= 'AND subdivision_name = "' .$subdivision_name . '"';
    
    $result = $mysqli->query($sql_query);
    
    if ($row = $result->fetch_assoc()){
      return $row['postal_code'];
    }
  }

Open in new window

Suggest you use our friend var_dump() to see what is contained in the variables.

It may not be related, but this code looks a bit goofy, like perhaps it is incomplete?  In the constructor at line 54 we have this:

trigger_error('Unable to construct address with a ' . get_class($name));

At that point the variable $name is undefined.  Code smell.
ASKER
rgb192

var_dump($address)
object(Address)#1 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377861541) ["_time_updated:protected"]=> NULL }

I can not see the output for
var_dump($address2)



also when I comment $mysqli->real_escape_string

I get this new error

Fatal error: Call to a member function query() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140
Ray Paseur

See also line 23 of class Database.  The connection is made with OOP notation, but the error test is made with procedural code.  I don't know if that would cause an error to be overlooked because I would never try something like that.  I think you want to change the if (mysqli_connect_error()) to if ($mysqli->connect_error)
http://php.net/manual/en/mysqli.connect-error.php

public function __construct(){
    $this->connection = new mysqli('localhost','username','pass','dbname');
    //error handling
    if (mysqli_connect_error()){
      trigger_error('Failed to connect to MySql: '.mysqli_connect_error(),E_USER_ERROR);
    }

Open in new window

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Ray Paseur

Go back to this:
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452073

Use var_dump() with $db and $mysqli in the postal code function.
ASKER
rgb192

if ($mysqli->connect_error)

database still connects

in demo.php
var_dump($db);
var_dump($mysqli);

NULL NULL

I do not see any output when I add to postal code function
var_dump($db);
var_dump($mysqli);
Argenti

Fatal error: Call to a member function [...] on a non-object...

Is your $mysqli variable properly initialized ??
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Argenti

well... you cannot query() on a NULL object, sorry :(
ASKER
rgb192

when I put var_dump($db) after the $db = Database::getInstance();
object(Database)#2 (2) { ["_connection:private"]=> NULL ["connection"]=> object(mysqli)#3 (0) { }

var_dump($mysqli) after
 $mysqli = $db->getConnection();

NULL
ASKER
rgb192

>>Is your $mysqli variable properly initialized ??

how to check
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Ray Paseur

The constructor says

$this->connection

getConnection() says

return $this->_connection;

You need to get those two things to be the same, then try it again.  Probably you want to use the one with the leading underscore because of this:

private $_connection;

Also, are you using error_reporting(E_ALL) ?
ASKER
rgb192

this is mysql, which I can see in mysql workbench query editor
CREATE TABLE IF NOT EXISTS `address` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `address_type_id` int(11) NOT NULL,
  `time_created` int(11) NOT NULL,
  `time_updated` int(11) NOT NULL,
  `street_address_1` varchar(255) NOT NULL,
  `street_address_2` varchar(255) NOT NULL,
  `city_name` varchar(255) NOT NULL,
  `subdivision_name` varchar(255) NOT NULL,
  `postal_code` varchar(20) NOT NULL,
  `country_name` varchar(255) NOT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;

INSERT INTO `address` (`address_id`, `address_type_id`, `time_created`, `time_updated`, `street_address_1`, `street_address_2`, `city_name`, `subdivision_name`, `postal_code`, `country_name`) VALUES
(1, 1, 762483360, 0, '300 Oracle Parkway', '', 'Redwood City', 'California', '94065', 'United States');

CREATE TABLE IF NOT EXISTS `location` (
  `location_id` int(11) NOT NULL AUTO_INCREMENT,
  `city_name` varchar(255) NOT NULL,
  `city_latitude` double NOT NULL,
  `city_longitude` double NOT NULL,
  `subdivision_name` varchar(255) NOT NULL,
  `postal_code` varchar(20) NOT NULL,
  PRIMARY KEY (`location_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

INSERT INTO `location` (`location_id`, `city_name`, `city_latitude`, `city_longitude`, `subdivision_name`, `postal_code`) VALUES
(1, 'Townsville', 38.7153408676386, -75.0866805016994, 'State', '12345'),
(2, 'Villageland', 33.1156463623047, -117.120277404785, 'Region', '67890'),
(3, 'Hamlet', 43.6666296, -92.9746367, 'Territory', '34567'),
(4, 'Redwood City', 37.5311965942383, -122.2646484375, 'California', '94065');

Open in new window

Ray Paseur

The queries are (probably) OK.  It's the use of an uninitialized variable that's causing the problem -- at least that's what I think.

Class Database, line 24

$this->_connection = new mysqli('localhost','username','pass','dbname');
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
rgb192

where does the

The constructor says

$this->connection


  function __construct($data = array()) {
    $this->_time_created = time();
    
    // Ensure that the Address can be populated.
    if (!is_array($data)) {
      trigger_error('Unable to construct address with a ' . get_class($name));
    }
    
    // If there is at least one value, populate the Address with it.
    if (count($data) > 0) {
      foreach ($data as $name => $value) {
        // Special case for protected properties.
        if (in_array($name, array(
          'time_created',
          'time_updated',
        ))) {
          $name = '_' . $name;
        }
        $this->$name = $value;
      }
    }
  }

Open in new window

ASKER
rgb192

The queries are (probably) OK.  It's the use of an uninitialized variable that's causing the problem -- at least that's what I think.

Class Database, line 24

$this->_connection = new mysqli('localhost','username','pass','dbname');


I am using my database connection (which I do not show to experts-exchange.com)


now with
error_reporting(E_ALL)

output is
Instantiating Address
Setting properties...
object(Address)#1 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377863706) ["_time_updated:protected"]=> NULL }
Notice: Undefined variable: db in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 15
NULL
Notice: Undefined variable: mysqli in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 16
NULL
Notice: Use of undefined constant connect_error - assumed 'connect_error' in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Database.inc on line 26

Notice: Undefined variable: mysqli_ in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Database.inc on line 26
object(Database)#2 (2) { ["_connection:private"]=> NULL ["connection"]=> object(mysqli)#3 (0) { } } whatNULL
Fatal error: Call to a member function query() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140
Ray Paseur

I believe the error is in Class.Database.inc which is posted above with the original question.

Have a look at this:
object(Database)#2 (2) {
["_connection:private"]=> NULL
["connection"]=> object(mysqli)#3 (0) { }
}

What that tells me is that I am looking at the var_dump() output of an object instance of the Database class.  The object has two properties.  The _connection property is private and NULL (this is because it was declared private in the class definition, but no value was assigned).  The connection property contains an object instance of the mysqli class.  Note the difference between these two properties -- one starts with a leading underscore and is private.  The other is apparently accidentally created by a typographical error in the Database class constructor.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
ASKER
rgb192

So how could I
var_dump from the database class
or
edit the database class
Ray Paseur

Let's try this.  Go find the Database class that you're actually using in these tests.  Blot out the password, then post the entire Database class in the code snippet here.  I'll show you what I think needs to change.
ASKER
rgb192

I do not understand

I posted class.Database.inc in the first part of the question

I also posted .sql file
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452133
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ray Paseur

OK, I think I was confused by this:
I am using my database connection (which I do not show to experts-exchange.com)
I will post a new version of the class.Database.inc in a moment.  I just want to make sure you understand the change I'm making and how to find out where the error has been hiding.
Ray Paseur

See if this makes sense.
<?php // class.Database.inc
/**
* mysqli database: only one connection is allowed
*/
class Database
{
    private $_connection;
    //store the single instance
    private static $_instance;
    /**
    * get an instance of the database
    * @return Database
    */
    public static function getInstance(){
        if (!self::$_instance){
            self::$_instance= new self();
        }
        return self::$_instance;
    }
    /**
    * constructor
    */
    public function __construct(){
        $this->_connection = new mysqli('localhost','username','pass','dbname');
        //error handling
        if ($this->_connection->_connect_error){
            trigger_error('Failed to connect to MySql: '.mysqli_connect_error(),E_USER_ERROR);
        }
    }
    
    
    /**
    * Empty clone magic method to prevent duplication.
    */
    private function __clone(){}
    /**
    * get the mysqli connection
    */
    public function getConnection(){
        return $this->_connection;
    }  
}

Open in new window

Ray Paseur

I have tested this version of it.  The only changes I made before posting here are the authentication credentials.

The problem with this Database class is that it is not a "real" Singleton, in that it does not enforce the policy that requires only one connection to the data base.  Because it can be instantiated, you can wind up with multiple data base connections.  

In the next post, I will show you a real Singleton.

<?php // RWY_temp_rgb192.php
error_reporting(E_ALL);
/**
* mysqli database: only one connection is allowed (BUT THIS IS NOT A TRUE SINGLETON)
*/
class Database
{
    private $_connection;
    //store the single instance
    private static $_instance;
    /**
    * get an instance of the database
    * @return Database
    */
    public static function getInstance(){
        if (!self::$_instance){
            self::$_instance= new self();
        }
        return self::$_instance;
    }
    /**
    * constructor
    */
    public function __construct(){
        $this->_connection = new mysqli('localhost','user','pass','name');
        //error handling
        if ($this->_connection->connect_error){
            trigger_error('Failed to connect to MySql: '.mysqli_connect_error(),E_USER_ERROR);
        }
    }


    /**
    * Empty clone magic method to prevent duplication.
    */
    private function __clone(){}
    /**
    * get the mysqli connection
    */
    public function getConnection(){
        return $this->_connection;
    }
}
// CREATE INSTANCES
$db1 = new Database;
$db2 = $db1->getConnection();
$db3 = new Database;
$db4 = $db3->getConnection();
$db5 = $db3->getConnection();

// THIS WILL PROVE THAT THERE ARE TWO CONNECTIONS (NO ECHO)
if ($db2 === $db4) echo 'EQUAL';

// THIS WILL SHOW THAT CONNECTIONS FROM THE SAME INSTANCE ARE EQUAL
if ($db4 === $db5) echo 'CONNECTION EQUAL';

Open in new window

Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Ray Paseur

This is a true Singleton class.  It cannot be instantiated, therefore you cannot wind up with any instance of the object, much less several instances of the object.  And since it will always return a private class property representing the MySQLi connection, you can be sure that any access to the Database will be using the same connection.

I believe that the only thing we want back from this is the connection, not the internal instance, so I changed the getInstance() to eliminate that additional step.

<?php // RAY_database_singleton.php
error_reporting(E_ALL);


// SINGLETON DATA BASE CONNECTION CLASS
class Database
{
    // CLASS PROPERTIES ARE ALL PRIVATE
    private static $_connection;
    private static $_instance;

    // CONNECTION VALUES
    const DB_HOST = 'localhost';
    const DB_USER = 'user';
    const DB_PASS = 'pass';
    const DB_NAME = 'name';

    // NULLIFY THE CLONE
    private function __clone() {}

    // OUR ONLY PUBLIC METHOD RETURNS THE CONNECTION
    public static function getConnection()
    {
        if (!self::$_instance) self::$_instance = new self();
        return self::$_connection;
    }

    // CONSTRUCTOR RETURNS THE CONNECTION
    private function __construct()
    {
        self::$_connection
        = new mysqli
        ( self::DB_HOST
        , self::DB_USER
        , self::DB_PASS
        , self::DB_NAME
        )
        ;
        if (self::$_connection->connect_error)
        {
            trigger_error(self::$_connection->connect_error, E_USER_ERROR);
        }
    }
}

$mysql1 = database::getConnection();
$mysql2 = database::getConnection();


// PROVE THAT THESE ARE THE SAME OBJECT http://php.net/manual/en/language.oop5.object-comparison.php
if ($mysql1 === $mysql2) echo 'EQUAL';

Open in new window

HTH, ~Ray
ASKER
rgb192

output of
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452593

EQUAL
Instantiating Address
Setting properties...
object(Address)#3 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377885590) ["_time_updated:protected"]=> NULL }
Notice: Undefined variable: db in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 15
NULL
Notice: Undefined variable: mysqli in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 16
NULL
Fatal error: Call to undefined method Database::getInstance() in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 129
ASKER
rgb192

output of
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452571

CONNECTION EQUAL
Instantiating Address
Setting properties...
object(Address)#5 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377885797) ["_time_updated:protected"]=> NULL }
Notice: Undefined variable: db in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 15
NULL
Notice: Undefined variable: mysqli in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 16
NULL object(Database)#6 (1) { ["_connection:private"]=> object(mysqli)#7 (0) { } } whatobject(mysqli)#7 (0) { }
Notice: Undefined variable: sql_query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Warning: mysqli::query() [mysqli.query]: Empty query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Fatal error: Call to a member function fetch_assoc() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 142
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
rgb192

output of
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452502

Instantiating Address
Setting properties...
object(Address)#1 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377885928) ["_time_updated:protected"]=> NULL }
Notice: Undefined variable: db in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 15
NULL
Notice: Undefined variable: mysqli in C:\wamp\www\Ex_Files_oophp-edit\04_05\demo.php on line 16
NULL
Notice: Undefined property: mysqli::$_connect_error in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Database.inc on line 26
object(Database)#2 (1) { ["_connection:private"]=> object(mysqli)#3 (0) { } } whatobject(mysqli)#3 (0) { }
Notice: Undefined variable: sql_query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Warning: mysqli::query() [mysqli.query]: Empty query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Fatal error: Call to a member function fetch_assoc() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 142
ASKER CERTIFIED SOLUTION
Ray Paseur

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
rgb192

QUERY: SELECT 1+1
FOUND 1 ROWS OF DATA USING MySQLi_Result::Fetch_Object(): stdClass Object ( [1+1] => 2 )
Instantiating Address
Setting properties...
object(Address)#4 (10) { ["street_address_1"]=> string(15) "555 Fake Street" ["street_address_2"]=> NULL ["city_name"]=> string(10) "Townsville" ["subdivision_name"]=> string(5) "State" ["_postal_code:protected"]=> NULL ["country_name"]=> string(24) "United States of America" ["_address_id:protected"]=> NULL ["_address_type_id:protected"]=> int(1) ["_time_created:protected"]=> int(1377895740) ["_time_updated:protected"]=> NULL } object(Database)#1 (1) { ["_connection:private"]=> object(mysqli)#2 (0) { } } object(mysqli)#2 (0) { } object(Database)#1 (1) { ["_connection:private"]=> object(mysqli)#2 (0) { } } whatobject(mysqli)#2 (0) { }
Notice: Undefined variable: sql_query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Warning: mysqli::query() [mysqli.query]: Empty query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Fatal error: Call to a member function fetch_assoc() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 142



output after commenting var_dump
QUERY: SELECT 1+1
FOUND 1 ROWS OF DATA USING MySQLi_Result::Fetch_Object(): stdClass Object ( [1+1] => 2 )
Instantiating Address
Setting properties...

Notice: Undefined variable: sql_query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Warning: mysqli::query() [mysqli.query]: Empty query in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 140

Fatal error: Call to a member function fetch_assoc() on a non-object in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 142



I noticed that I added echo and var_dump in class.Address.inc and demo.php, changing the values so I copy paste those files

current version of class.Address.inc
<?php

/**
 * Physical address. 
 */
class Address {
  
  const ADDRESS_TYPE_RESIDENCE = 1;
  const ADDRESS_TYPE_BUSINESS = 2;
  const ADDRESS_TYPE_PARK = 3;
  
  // Address types.
  static public $valid_address_types = array(
    Address::ADDRESS_TYPE_RESIDENCE => 'Residence',
    Address::ADDRESS_TYPE_BUSINESS => 'Business',
    Address::ADDRESS_TYPE_PARK => 'Park',
  );
  
  // Street address.
  public $street_address_1;
  public $street_address_2;
  
  // Name of the City.
  public $city_name;
  
  // Name of the subdivison.
  public $subdivision_name;
  
  // Postal code.
  protected $_postal_code;
  
  // Name of the Country.
  public $country_name;
  
  // Primary key of an Address.
  protected $_address_id;
  
  // Address type id.
  protected $_address_type_id;
  
  // When the record was created and last updated.
  protected $_time_created;
  protected $_time_updated;
  
  /**
   * Constructor.
   * @param array $data Optional array of property names and values.
   */
  function __construct($data = array()) {
    $this->_time_created = time();
    
    // Ensure that the Address can be populated.
    if (!is_array($data)) {
      trigger_error('Unable to construct address with a ' . get_class($name));
    }
    
    // If there is at least one value, populate the Address with it.
    if (count($data) > 0) {
      foreach ($data as $name => $value) {
        // Special case for protected properties.
        if (in_array($name, array(
          'time_created',
          'time_updated',
        ))) {
          $name = '_' . $name;
        }
        $this->$name = $value;
      }
    }
  }
  
  /**
   * Magic __get.
   * @param string $name 
   * @return mixed
   */
  function __get($name) {
    // Postal code lookup if unset.
    if (!$this->_postal_code) {
      $this->_postal_code = $this->_postal_code_guess();
    }
    
    // Attempt to return a protected property by name.
    $protected_property_name = '_' . $name;
    if (property_exists($this, $protected_property_name)) {
      return $this->$protected_property_name;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined property via __get: ' . $name);
    return NULL;
  }
  
  /**
   * Magic __set.
   * @param string $name
   * @param mixed $value 
   */
  function __set($name, $value) {
    // Only set valid address type id.
    if ('address_type_id' == $name) {
      $this->_setAddressTypeId($value);
      return;
    }
    // Allow anything to set the postal code.
    if ('postal_code' == $name) {
      $this->$name = $value;
      return;
    }
    
    // Unable to access property; trigger error.
    trigger_error('Undefined or unallowed property via __set(): ' . $name);
  }
  
  /**
   * Magic __toString.
   * @return string 
   */
  function __toString() {
    return $this->display();
  }
  
  /**
   * Guess the postal code given the subdivision and city name.
   * @todo Replace with a database lookup.
   * @return string 
   */
  protected function _postal_code_guess() {
    $db = Database::getInstance();
    //var_dump($db);
    $mysqli = $db->getConnection();
    //echo 'what';
    //var_dump($mysqli);    
    $city_name = /*$mysqli->real_escape_string(*/$this->city_name/*)*/;
    //$sql_query .= 'WHERE city_name = "' . $city_name . '" ';
    
    $subdivision_name = /*$mysqli->real_escape_string(*/$this->subdivision_name/*)*/;
    //$sql_query .= 'AND subdivision_name = "' .$subdivision_name . '"';
    
    $result = $mysqli->query($sql_query);
    
    if ($row = $result->fetch_assoc()){
      return $row['postal_code'];
    }
    //var_dump($db);
//var_dump($mysqli);
  }
  
  /**
   * Display an address in HTML.
   * @return string 
   */
  function display() {
    $output = '';
    
    // Street address.
    $output .= $this->street_address_1;
    if ($this->street_address_2) {
      $output .= '<br/>' . $this->street_address_2;
    }
    
    // City, Subdivision Postal.
    $output .= '<br/>';
    $output .= $this->city_name . ', ' . $this->subdivision_name;
    $output .= ' ' . $this->postal_code;
    
    // Country.
    $output .= '<br/>';
    $output .= $this->country_name;
    
    return $output;
  }
  
  /**
   * Determine if an address type is valid.
   * @param int $address_type_id
   * @return boolean
   */
  static public function isValidAddressTypeId($address_type_id) {
    return array_key_exists($address_type_id, self::$valid_address_types);
  }
  
  /**
   * If valid, set the address type id.
   * @param int $address_type_id 
   */
  protected function _setAddressTypeId($address_type_id) {
    if (self::isValidAddressTypeId($address_type_id)) {
      $this->_address_type_id = $address_type_id;
    }
  }
}

Open in new window


current version of demo.php
<?php
error_reporting(E_ALL);
require 'class.Address.inc';
require 'class.Database.inc';
echo '<h2>Instantiating Address</h2>';
$address = new Address;

echo '<h2>Setting properties...</h2>';
$address->street_address_1 = '555 Fake Street';
$address->city_name = 'Townsville';
$address->subdivision_name = 'State';
$address->country_name = 'United States of America';
$address->address_type_id = 1;
//var_dump($address);
//var_dump($db);
//var_dump($mysqli);
echo $address;

echo '<h2>Testing Address __construct with an array</h2>';
$address_2 = new Address(array(
  'street_address_1' => '123 Phony Ave',
  'city_name' => 'Villageland',
  'subdivision_name' => 'Region',
  'postal_code' => '67890',
  'country_name' => 'Canada',
));
//var_dump($address2);
echo $address_2;

Open in new window

Ray Paseur

Looks like the _postal_code_guess() function is damaged by comments.  What should be in that function? Suggest you restore it to its original state and try the tests again
Your help has saved me hundreds of hours of internet surfing.
fblack61
ASKER
rgb192

Using wamp on my desktop and linux server I get the same warnings and fatal error.
Ray Paseur

Then you're probably not running the original script.  Please revert to the original script for class.Address.inc, check to be sure it has the correct query in the _postal_code_guess() function and try again.

You might want to learn about GIT or SubVersion so you don't run the risk of losing a prior version of your software to an accidental overwrite.
ASKER
rgb192

with the original class.Address

all your examples worked except
https://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28226938.html#a39452593

Fatal error: Call to undefined method Database::getInstance() in C:\wamp\www\Ex_Files_oophp-edit\04_05\class.Address.inc on line 129
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.