Jump to content

Why While Loop Is Not Working Inside A Class?


Sanjib Sinha

Recommended Posts

I have a simple category table in which 5 or 6 names are there. Now I want to retrieve them.

When I connect to mysql database in procedural way, the while loop is working great, giving nice output. But when I go through a class and trying to retrieve the data, it stops after giving the first table name.

My procedural code is here:

mysql_connect("localhost", "root", "");
mysql_selectdb("12reach");
$cat = mysql_query("SELECT *
FROM `category`
LIMIT 0 , 30");
    if (!$cat){
	    die ('Error');
    }
    while ($row = mysql_fetch_array($cat)) {
	    extract($row);
	    echo $row['name'].'<br>';
    }

It works fine. Giving six category name. But problem begins with the following code: I have two classes and a php file where I created an instance of category class and trying to get the category table names one by one.

class ConnectClass {
   private $_connection;

   public function getConnect()
   {
  $this->_connection = mysql_connect("localhost", "root", "");
  if (mysql_errno()) {
    throw new RuntimeException('Cannot access database: '.mysql_error());
  }
  else {
    mysql_selectdb("12reach", $this->_connection);
  }
   }

include 'ConnectClass.php';
class CatClass extends ConnectClass{

   public function getcat() {

    $cat = mysql_query("SELECT *
FROM `category`
LIMIT 0 , 30");
    if (!$cat){
	    die ('Error');
    }
    while ($row = mysql_fetch_array($cat)) {
	    extract($row);
	    return $row['name'].'<br>';
    }	   
   }
}

include 'CatClass.php';
$obj=new CatClass();
$obj->getConnect();
echo $obj->getcat();

 

Probably while loop is working inside the class. As I want to return the last name of the category table, I can get it placing it outside the loop. But if I want the full name list, it does not work in object oriented format.

 

Any idea, where is my fault?

Link to comment
Share on other sites

Many thanks for giving the clue. But I have a question.

 

If I want to return rows as an array, the same thing happens. It returns an output 'Array'. Like this,

include 'ConnectClass.php';
class CatClass extends ConnectClass{

   public function getcat() {

    $cat = mysql_query("SELECT *
FROM `category`
LIMIT 0 , 30");
    if (!$cat){
	    die ('Error');
    }
    while ($row = mysql_fetch_array($cat)) {
	    extract($row);
	    $result = array($row['name']);// or $result=array($row);
	    return $result;

    }

   }
}

 

in my php file connect.php, I tried to echo like this:

include 'CatClass.php';
$obj=new CatClass();
$obj->getConnect();
//print_r($obj->getcat());
echo $obj->getcat();

 

But the output is Array. Quite normal. If I use print_r function I can see that while loop stops after the first row.

 

But if I don't use return, and instaed use echo inside CatClass.php, it works fine. Like this:

include 'ConnectClass.php';
class CatClass extends ConnectClass{

   public function getcat() {

    $cat = mysql_query("SELECT *
FROM `category`
LIMIT 0 , 30");
    if (!$cat){
	    die ('Error');
    }
    while ($row = mysql_fetch_array($cat)) {
	    extract($row);
	    echo $row['name'].'<br>';
    }

   }
}

 

In this case in my connect.php file I only call the function like this:

include 'CatClass.php';
$obj=new CatClass();
$obj->getConnect();
$obj->getcat();

 

Now it gives nice output of all the rows of table names.

 

So, return is simply not working inside a class while loop. It exits and do not enter again into that loop. But if I echo it, it produces perfect output inside that function.

Now, my question is, could I not use return inside a class while trying to retrieve many values?

Link to comment
Share on other sites

Your return statement needs to go outside of your while loop. This has nothing to do with the fact that your code is within a class. As has already been said, return exits the current function.

 

The code within your while loop is all over the place anyway actually. Replace your while loop with this:

 

$results = array();
while ($row = mysql_fetch_array($cat)) {
    $results[] = $row['name'];
}
return $results;

 

I would also seriously consider removing your classes all together. They are not being used at all like they are designed to be used.

Link to comment
Share on other sites

Many thanks. It works and I understood the trick.

But if you kindly clarify the last line

I would also seriously consider removing your classes all together. They are not being used at all like they are designed to be used.

I will be grateful. Would you suggest to bring the whole thing under one class?

Link to comment
Share on other sites

Your hierarchy is complete nonsense. You've written, in English: "CatClass is a ConnectClass.". This is because you've extended the CatClass to the ConnectClass but in reality a cat has absolutely nothing to do with a database connection. Further more you've ploughed a shed load of logic into single methods; you've included data retrieval and processing all in one method which doesn't make sense especially considering the name of your method.

 

Consider separating your logic into parts e.g. a Database class can have methods such as __construct() (that creates the connection upon instantiation), getConnection(), selectDatabase() and so on. This can be instantiated and passed to the Cat class via a constructor.

 

Plus the points above regarding the return statement and finally, you don't need to put a "Class" suffix after every class. You can't instantiated anything other than concrete classes so its unnecessary effort.

Edited by CPD
Link to comment
Share on other sites

As you have suggested, I am trying to restructure my class codes in this way. First the ConnectClass.php

 

//this is a simple class to establish connection
//with the database
 class ConnectClass {
   private $_connection;
   private $_database;

   public function  __construct() {
    $this->_connection = $con;
    $this->_database = $db;
   }
   public function selectDatabase() {
    $con = mysql_connect("localhost", "root", "");
    if (mysql_errno ()){
	    throw new RuntimeException('Cannot access database: '.mysql_error());
    }
	 else {
	    $db = '12reach';
	    mysql_select_db($db, $con);
	 }
    }
}

 

Next the CategoryClass.php

 

/*
* CategoryClass basically extends ConnectClass
* to establish connection with the database
* and retrieve datas from category table
*/
include 'ConnectClass.php';
class CategoryClass extends ConnectClass{
   public function  __construct() {
    $this->selectDatabase();
   }
   public function categoryName() {
    $cat = mysql_query("SELECT *
FROM `category`
LIMIT 0 , 30");
    if (!$cat){
	    die ('Error');
    }
    //since we dont want to exit the loop without having
    //all the table names, so we get our results in an array
    $results = array();
    while ($row = mysql_fetch_array($cat)) {
	    $results[] = $row['name'];
    }
    //now it is time to go outside the loop and return all table names
    return $results;
   }
}

 

Please suggest, if it can be modified or be written in a better way? So that connection and other part be more secured.

Link to comment
Share on other sites

The category class uses a DB connection, but it's not a database connection.

Send the DB connection object as a parameter to the constructor, but don't extend the DB class with the category class.

 

Think of it in terms of chess: A knight is an extension of the piece, but the board uses the pieces. Thus you'll have to send the pieces (object instances) to the board, as it makes no sense to extend the board from a piece. Same way with categories and the DB connection. ;)

 

abstract class Piece {
   private $_colour;
   private $_move_rule;
   private $_name;

   public function move ($vector) {}
   public function set_colour () {
       $this->colour = $colour == 'white' ? 'white' : 'black';
   }
   public function get_colour () {return $this->colour;}
   public function get_name () {return $this->name;}
}

class Knight implements Piece {
   private $_name = "Knight";
   private $_move_rule = "1fx2s";
}

class ChessBoard implements GameBoard {
   private $_height = 16;
   private $_width = 16;
   private $_players = 2;
   private $_pieces = array ();

   public function add_piece (Piece $piece, $x_pos, $y_pos) {
   }
}

// Generate the chess board.
$game = new ChessBoard ();

// Generate the chess pieces.
$knight_white = new Knight ('white');

// Add the chess pieces to the game board.
$game->add_piece ($knight_white, 1, 3);

 

Just a quick example, to showcase the proper object inheritance and association.

Edited by Christian F.
Link to comment
Share on other sites

So many thanks for clearing the confusion.

Each time I want to fetch a category name(here a category object), database connection opens up and closes, so it is really unneccessary to extend CategoryClass from ConnectClass.

Connection object can be passed as an argument through Category constructor, so that with each instantiation of category, costructor will be called first and DB connection opens and closes.

I will give it a try.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.