Welcome Guest, Not a member yet? Register   Sign In
Create a custom object from DB result()?
#1

[eluser]Andy Ingham[/eluser]
Hi All,

An interesting question (hopefully!)...

If I process through query results using the following code:

Code:
foreach ($query->result() as $row) {
    ...
}

then each '$row' is an object (of type stdClass?).

However, if I want to create my own 'custom' object for each row, so that I can wrap methods around the data, then what's the best way of doing it?

I notice in the 'mysqli_result::fetch_object' php.net documentation that you have the option of specifying a class_name when retrieving a row as an object:

Quote:class_name

The name of the class to instantiate, set the properties of and return. If not specified, a stdClass object is returned.

...so maybe this gives a clue as to an approach (although the CI result() function doesn't seem to accept any arguments).

Another approach is presumably to retrieve the row into a stdClass object, as described earlier, but then to copy the attributes from the stdClass object to my own class. If so, anyone know how best way to do this?

Any help on this greatly appreciated.

Thanks,

Andy
#2

[eluser]Matt S.[/eluser]
Are you wanting a custom object for each actual row or for each fieldset returned? You can try to make a custom reference of each object, like so:

Code:
foreach($query->result() as $row)
{
     $row->someField    =& $custom1->someField;
     $row->anotherField =& $custom2->anotherField;
}

I'm still a little confused on what you are trying to accomplish.
#3

[eluser]Andy Ingham[/eluser]
Matt,

Thanks for getting back on this.

Well, to use a simplified example, I'm reading through a database of products in my model and passing back to the controller an array of objects, each object holding one row from the database, e.g. getProducts() function in Products_model something like this:

Code:
$this->db->select('*');
$this->db->from('products as prod');
$this->db->join('categories as cat', 'cat.id = prod.category_id');
$query = $this->db->get();
return $query->result();

The controller calls the model and loops through the result and it can display the ID of each product item:

Code:
$products = $this->Products_model->getProducts();
foreach ($products as $product) {
  echo 'Product ID: ' . $product->prod_id;
}

Now what if I have a method that I'd like to be available for each product item so that, for example, I could find out total value of stock (stock level * unit price), so I'd want to do something like this:

Code:
$products = $this->Products_model->getProducts();
foreach ($products as $product) {
  echo 'Product ID: ' . $product->prod_id;
  echo 'Stock Value: ' . $product->stockValue();
}

Obviously I'd need to create a productItem_model something like this:

Code:
class productItem_model extends CI_Model {

  function __construct() {
      parent::__construct();
  }
  
  function stockValue () {
    return $this->stockLevel * $this->unitPrice;
  }
}

So my question is can I get the CI result() function to return results as an array of productItem objects rather than just stdClass objects?

Assuming that I can't, then I presumably need to change the constructor function of my Product model so that it can receive a stdClass object as a parameter and then create attributes from that? This would mean something like the following:

Controller:

Code:
$products = $this->Products_model->getProducts();
foreach ($products as $stdClassObject) {
  $product = new productItem_model($stdClassObject);
  echo 'Product ID: ' . $product->prod_id;
  echo 'Stock Value: ' . $product->stockValue();
}

productItem_model:

Code:
class productItem_model extends CI_Model {

  function __construct($stdClassObject) {
    parent::__construct();
    foreach($stdClassObject as $attrib => $value) {
      $this->$attrib = $value
    }
  }
  
  function stockValue () {
    return $this->stockLevel * $this->unitPrice;
  }
}

I think that this will work (yet to test it out) but wondering whether it's the most elegant approach.

Andy
#4

[eluser]Matt S.[/eluser]
Why handle the calculations through PHP and not just do them in SQL? I think it would be a little easier just to create the stock value in your select string:

Code:
$this->db->select( '*, ( stockLevel * unitPrice ) AS stockValue ');
#5

[eluser]Andy Ingham[/eluser]
Hi Matt,

The MySQL solution would be fine in this simple example, but if things get more complicated then I think it would be better to wrap up each product in a custom object. For example, what if a product's cost reduces the more you buy, so for example unit price when buying up to 10 is £1.00 but between 10-24 is £0.90, 25-49 is £0.80, etc. I'd like to be able to call a method of the product object to tell me the unit price:

Code:
$unitPrice = $product->getUnitPrice($orderedAmt);

Andy
#6

[eluser]Matt S.[/eluser]
I see, I think the viable solution would be just to create private methods within the controller you are using and pass them arguments as needed. Alternatively, you can set up a library/helper containing the calculations if you are going to use them multiple times.

Code:
class Some_Controller extends Controller {

     function __construct()
     {
          parent::Controller();

          $this->load->model('products_model')
     }

    function index()
    {
        $products = $this->products_model->getProducts();

         foreach ($products as $product) {
              echo 'Product ID: ' . $product->prod_id;
              echo 'Stock Value: ' . $this->_stockValue( $product->stockLevel, $product->unitPrice );
         }
    }

    function _stockValue($stockLevel = 0, $unitPrice = 0)
    {
         return $stockLevel * $unitPrice
    }
    
}
#7

[eluser]Andy Ingham[/eluser]
Matt,

Thanks again for your input on this.

In the end I did go with the way that I mentioned in my last post. I think it's better having the methods in the model, so that you can use those methods whenever you're using the data. If you put these methods in the controller then you wouldn't have access to them when working with the data in another controller.

Andy




Theme © iAndrew 2016 - Forum software by © MyBB