Hi all,

I've literally JUST dived into OOP and it's a totally different world. I've written some pretty awful code just to grasp OOP basics. The following code is all in the same file and runes fine, there are no warnings, errors, notices and so forth yet it doesn't work correctly... I think it's something dead simple and if it is I promise to facepalm as hard as I can.

Thanks for any help in advance.

Code:
<?php

error_reporting(E_ALL);

    class database{

        protected $_link, $_result, $_numRows;

        public function __construct(){
            $this->_link = mysqli_connect('localhost', 'root', '', 'studybubble') or die(mysqli_error());
        }

        public function disconnect(){
            mysqli_close($this->_link);
        }

        public function query($string){
            $this->_result = mysqli_query($this->_link, $string);
            $this->_numRows = mysqli_num_rows($this->_result);
        }

        public function numRows(){
            return $this->numRows();
        }

    }

    class user{

        private $firstname;
        private $lastname;
        private $avatar;

        function __construct(){

            $db = new database;
            $stm = $db->query("SELECT fn, ln, avatar FROM `users` WHERE `authuser` = 'mmcdonald'");

            $this->firstname = $stm['fn'];
            $this->lastname = $stm['ln'];
            $this->avatar = $stm['avatar'];

        }

        public function firstname(){
            return $this->firstname;
        }

        public function lastname(){
            return $this->lastname;
        }

        public function avatar(){
            return $this->avatar;  
        }
    }

    $user = new user;    
    echo 'Firstname: '.$user->firstname().'<br />
          Lastname: '.$user->lastname().'<br />
          Avatar: '.$user->avatar();

?>
The current output:

Firstname:
Lastname:
Avatar:

Again PLEASE ignore the security aspects and optimisation aspetcs and such, they're not my focus in this exercise :) Thanks!

Looks like you're missing a mysqli_fetch_assoc(). The query method should return $this->_result and on line 38 the fetch should be used.

commented: Cheers! +3

Thanks for the response Pritaeas, it looks like it's basic PHP training I need not OOP!

I totally understand the requirement for return $this->_result but where would I add the mysqli_fetch_assoc()? In the query method or in the user class construct?

Also, for the fetch, how would I write this? To be totally honest I'm still struggling to appreiciate what properties I'm calling on and from where, also for what reason.

Thanks again,
Michael

At this point, the position of the fetch would be a design decision. IMO I'd execute it after the query, and return the array instead of the statement. You are executing this query because you want a specific row (in this case). The database class should handle all database functions.

It depends on what you are going to use query for in the future, because depending on the query you pass, you'll want a single result, a list of results, or just true/false (in case of an insert/update query).

Your numRows method is missing an underscore BTW. Note that for insert/update statements, the use of mysqli_affected_rows may be needed.

Finally, you can use mysqli_fetch_object instead, to return a standard object (you ARE using OOP) instead of an array.

Okay thank you for the information, I'll be looking into all of the above and will post back here with my progress.

Michael

It's all working well now so thank you. May I ask, what's the most appropriate way of constructing classes and methods in regards to utilising user information? Should I have a class that would be used to loop user information on a user database and a class to construct their profiles?

Any advice would be appreciated. In the mean time I am going to abuse Google - ta!

The way I'd do it is visible in this thread. The database class uses PDO to construct a users class directly from the SQL result. I think MySQLi can do the same.

Am sure you have an idea in your head, but to me it's not clear from the last post. What you should remember, especially at the start, is that a single class should have a single clear purpose.

That's great Pritaeas thank you very much. The way I'm currently approaching my classes is to have a class for each area of the web application. For example:

  1. User Management (Creating, updating and retreiving user data)
  2. Support Management (Creating, updating and retreiving ticket data)
  3. Forum Management (Creating, updating and retreiving thread/topic data)

...and you get the drift. Is that what you mean by a single clear purpose - or are you implying that I should have a class for creating, a class for updating and a class for retreiving?

As for your comments regarding your existing class in your ORM experiment (Which looks great by the way), would you recommend PDO over mysqli? I have read the opinion of many thanks to Google but there are too many conflicting arguments to truly clarify. Would you do the honour and share your opinion? Believe me when I say it'll hold more weight in my judgement!

You have no idea how much your advice is appreciated,
Michael

As you type your points 1-3 the first thing you should notice is that all three are doing the same database actions. One of the strengths of OOP is reuse. How are you going to reuse the database actions between those three classes? IMO a database class is a single entity responsible for updating information to/from objects. Where that information is stored doesn't matter. The idea is that you can create multiple database classes (storing information differently), but they should be easily swapped with little effort (loose coupling). If you embed the database functionality into your class, then switching to another type of storage later on requires you to rewrite your classes.

The only advantage of PDO over MySQLi which you should take into consideration is, will you use/support multiple types of databases (just MySQL or also SQLite, SQL server, Postgres, etc.). Other than that they're pretty much equals, each with their own quirks. If you decide to stick with MySQLi then do switch to the OO version, since OOP is what you want to learn. My other preference for PDO is the fact of it's exception handling, which I'm more comfortable with.

Cheers Prit, I have a much clearer understanding.

That happens to be the most unbiased response I've ever had to that question - thanks!

Guess who!

I've made very little progress due to work but I've spent an hour looking into where I left off. Below is what I wrote from scratch over the past hour. Now if half works because if I use the user ubject once it works fine, yet if I enter it more than once it fails (Sorry if I haven't worded that correctly).

The classes
class database{

    protected $_link;

    public function __construct(){
        $this->_link = mysqli_connect('.', '.', '.', '.');
    }

    public function disconnect(){
        mysqli_close($this->_link);
    }

    public function query($string){
        if ((isset($string)) && ($string != null)){
            $result = mysqli_query($this->_link, $string);
            return $result;
        }else{
            return false;
        }
    }

}


class user{

    public $string;
    protected $db;

    public function __construct(){
        $this->db = new database;
    }

    public function getData($values){
        $string = "SELECT `".$values."` FROM `users` WHERE `id` = '77'";
        $result = $this->db->query($string);

        /* create associative array */
        $data = $result->fetch_array(MYSQLI_ASSOC);
        //printf ("%s (%s)\n", $data["fn"], $data["ln"]);
        $result->free(); 
        $this->db->disconnect();

        return $data[''.$values.''];

    }

    public function getFirstname(){
        return $this->getData("fn");
    }

    public function getLastname(){
        return $this->getData("ln");
    }
}
The code THAT WORKS
$db = new database;
$user = new user;

echo $user->getFirstname();
The code DOESNT WORK
$db = new database;
$user = new user;

echo $user->getFirstname()." ".echo $user->getLastname();
Output of code that doesn't work
Michael
Warning: mysqli_query(): Couldn't fetch mysqli in C:\xampp\htdocs\sb\classes.php on line 17

Fatal error: Call to a member function fetch_array() on a non-object in C:\xampp\htdocs\sb\classes.php on line 42

As you can see the first call on the object for the first name works, then it starts crying after I call on another. I think the answer is quite obvious, it's that I'm requesting an array without my query method being prepared to return arrays, but I don't know how to restructure the query method so that it can operate as many times as I'd like to call on it.

Any advice would be great,
Michael

Don't worry peeps it was me being a drip - I grabbed a coffee, munched a lot of biscuits and noticed I was closing the database in my method:

$this->db->disconnect();

Deleting that line (User class line 42) solved the issue. Ta!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.