I am creating some classes, but I don't know if this approach is very solid. First some basic information. I use code igniter as framework. I use $CI =& get_instance() since I need to load some models.
I store products inside a Product class like this:
class Product {
private $id;
private $partNumber;
private $description;
private $stock;
/**
* Product constructor.
* @param $id
* @param $partNumber
* @param $description
*/
public function __construct($id, $partNumber, $description){
include_once(APPPATH.'controllers/Core_Stock_Controller_Test.php');
$this->id = $id;
$this->partNumber = $partNumber;
$this->description = $description;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getPartNumber()
{
return $this->partNumber;
}
/**
* @return mixed
*/
public function getDescription()
{
return $this->description;
}
/**
* @return Stock
*/
public function getStock(){
if($this->stock == null){
$stockController = new Core_Stock_Controller_Test();
$this->stock = $stockController->getStockFromProduct($this);
}
return $this->stock;
}
}
The controller:
class Core_Product_Beta{
public function __construct()
{
$CI =& get_instance();
$CI->load->model('Core_Product_Model');
include_once(APPPATH . 'models/Product.php');
}
private function getInstance()
{
return get_instance();
}
/**
* @var Int $partId
* @var Int $partNumber
* @return bool|Product
*/
public function getPart($partId = null, $partNumber = null)
{
if ($partId) {
return $this->mapProductToObject($this->getInstance()->Core_Product_Model->getPartnumberFromId($partId));
}
if (strlen($partNumber) == 12 && is_numeric($partNumber)) {
return $this->mapProductToObject($this->getInstance()->Core_Product_Model->getIdFromPartnumber($partNumber));
}
return false;
}
private function mapProductToObject($data)
{
if(isset($data[0])) {
return new Product($data[0]->id, $data[0]->Part_number, $data[0]->Description, $data[0]->Type, $data[0]->Housing, $data[0]->Gki, $data[0]->enabled);
} else {
throw new ProductException("Error with product", "The product does not exist", null);
}
}
}
And I load the stock when the method is called, because I don't need it every time (So I think it's faster this way, because sometimes I need more than 200 Products). Is it the right way to create another object in a class?
The Stock controller:
class Core_Stock_Controller_Test{
public function __construct() {
$CI =& get_instance();
$CI->load->model('Core_Stock_Model');
}
private function getInstance(){
return get_instance();
}
public function getStockFromProduct(Product $product){
$result = $this->getInstance()->Core_Stock_Model->getStockForAllLocationPerPartId($product->getId());
$locations = array();
$totalStock = 0;
foreach($result as $res){
$totalStock = $res["total"];
$location = new Location($res["location_id"], $res["cd_mag"], $res["cd_location"], $res["cd_loc_type"], $res["stock"]);
array_push($locations, $location);
}
return new Stock($locations, $totalStock);
}
}
The Stock class:
class Stock
{
private $locations = array();
private $totalStock = 0;
/**
* Stock constructor.
* @param array $location
*/
public function __construct(array $location)
{
$this->locations = $location;
}
/**
* @return array
*/
public function getLocations()
{
return $this->locations;
}
/**
* @return Location
*/
public function getLocation($index){
return $this->locations[$index];
}
/**
*
*/
public function getTotalStock(){
$stock = 0;
foreach($this->locations as $location){
$stock += $location->getStock();
}
return $stock;
}
}
This works, but bad because I don't use dependency injection. How can I solve this? I do it this way because I want to delegate everything.
So that I can simply say:
$controller = new Core_Product_Beta();
$product = $controller->getPart(1, null);
No issues till now. I want to get the stock from that product, and I want to simply call $product->getStock
, without instantiating and adding classes to each other at this level.
Another reason why I'm doing this this way is because I don't need to use the stock every time. So I thought it is better to load it when I need it. What is the best way to design this?
Edit: Some more information about the relations between the classes. I have a product class with presents a product. Each product can have a relation with the stock class.
But the stock class holds the locations (the location class contains the actual location and the amount of stock on that location). Each product can lay on different locations in the warehouse. That is way I save the locations as an array at the stock object.
In short: A product can have stock, and stock has 1 or more locations.
$CI
? It seems central to this review. Also can you provide some commentary as to relationships between these classes/models. I am strugglling with this given the odd class names. \$\endgroup\$