-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
11-06-2015, 07:42 AM
(This post was last modified: 11-06-2015, 07:42 AM by sebastianvirlan.)
Is this method a good practice?
Controller:
PHP Code: $produse = $this->produse->entries_by_limit((($page-1) * $config_pagina['per_page']), $config_pagina['per_page'], $order_by, '270');
Model:
PHP Code: function entries_by_limit($start, $limit, $order_by = "order by id_produs asc", $rez) { $this->db->select('a.*'); $this->db->select('b.nume_imagine', false); $this->db->from("$this->_table a"); $this->db->join('imagini_produse b', "b.$this->_primary_key = a.id_produs", "left"); $this->db->limit($limit, $start); $this->db->order_by($order_by); $result = $this->db->get();
foreach($result->result() as $single) {
if($single->nume_imagine): $single->nume_imagine = base_url('assets/uploads/'.$single->id_produs.'/'.$this->parse_image($single->nume_imagine, $rez)); else: $single->nume_imagine = base_url('assets/images/no-product-image-available.png'); endif; }
return $result->result(); }
function parse_image($image_name, $rez){ $image = explode('.', $image_name); return $image[0].'_'.$rez.'.'.$image[1];
}
and view
PHP Code: <img class="primary-image" src="<?= $produs->nume_imagine ?>" alt="">
Should I use any helper or is ok like this?
-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
11-10-2015, 12:39 AM
(This post was last modified: 11-10-2015, 01:42 AM by sebastianvirlan.)
I think a good start would be OOP, so I started:
PHP Code: class Product {
private $_product; private $_resolution;
public function __construct($product, $resolution){
$this->_product = $product; $this->_resolution = $resolution; }
public function products() {
foreach($this->_product as $product){ $product->nume_imagine = $this->parse_image_name($product); }
return $this->_product;
}
public function product() {
$this->_product->nume_imagine = $this->parse_image_name($this->_product);
return $this->_product;
}
private function parse_image_name($product) { if($product->nume_imagine): return base_url('assets/uploads/'.$product->id_produs.'/'.$this->image_resolution($product->nume_imagine, $this->_resolution)); else: return base_url('assets/images/no-product-image-available.png'); endif; }
private function image_resolution($image_name, $resolution) {
$image = explode('.', $image_name); return $image[0].'_'.$resolution.'.'.$image[1]; } }
The problem is I dont't know where to call and how to call. In model? In controller?
-
Martin7483
Crossfire CMS
-
Posts: 373
Threads: 14
Joined: Sep 2015
Reputation:
20
In the world of MVC each request is routed to a Controller. You could ignore the M and V completely and do everything in your controller. But you will quickly see that this means duplicating a lot of code. So you start to use Models for Database communication. In your models you perform some logic to the DB results and return it to your controller. Again you will start to notice code duplication. So you start using helpers for common functions and libraries for more complex data handling. And thus you may start to use a business layer for your models.
I would say your Product class is a library and you pass a data package to this class. So how you call this could be
1. Controller --> request data from your model and return to Controller
2. Controller --> pass the data to the Product class and return to Controller
3. Controller --> pass the data to the view
Hopes this helps you out
-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
11-10-2015, 01:45 AM
(This post was last modified: 11-10-2015, 01:53 AM by sebastianvirlan.)
(11-10-2015, 01:16 AM)Martin7483 Wrote: In the world of MVC each request is routed to a Controller. You could ignore the M and V completely and do everything in your controller. But you will quickly see that this means duplicating a lot of code. So you start to use Models for Database communication. In your models you perform some logic to the DB results and return it to your controller. Again you will start to notice code duplication. So you start using helpers for common functions and libraries for more complex data handling. And thus you may start to use a business layer for your models.
I would say your Product class is a library and you pass a data package to this class. So how you call this could be
1. Controller --> request data from your model and return to Controller
2. Controller --> pass the data to the Product class and return to Controller
3. Controller --> pass the data to the view
Hopes this helps you out
Thank you. Helped a lot, see my last post with my class and tell me if I can refactor something.
Then in my controller I have:
PHP Code: $best_offer = new Product($this->products->best_offer(), 270); $produse_noi = new Product($this->produse->entries_by_limit(0, 10, null), 270); $data['best_offer'] = $best_offer->product(); $data['produse_noi']= $produse_noi->products();
Is this the best practice MVC and OOP?
-
sintakonte
Member
-
Posts: 89
Threads: 10
Joined: Nov 2014
Reputation:
4
i think your way of thinking is on the right way but needs to get organized
Your Problem is that you need sometimes methods or variables where it seems they don't belong to a model or a controller.
i try to explain it on your current example
First of all we need to adapt the MVC principle into a MVOC term.
make a folder in your application directory called objects
the next thing is you have to make sure that your objects get autoloaded
open your hooks.php in application/config/ and write the following down
PHP Code: $hook['pre_system'][] = array( 'class' => 'AppAutoLoadObjects', 'function' => 'initialize', 'filename' => 'AppAutoLoadObjects.php', 'filepath' => 'hooks' );
after that create a class named AppAutoLoadObjects.php in your applications/hooks/ directory
this class should look like
PHP Code: class AppAutoLoadObjects {
public function initialize() { spl_autoload_register(array($this,'autoloadCoreObjects')); }
public function autoloadCoreObjects($class) { $path = array( 'objects/', );
foreach($path as $dir) { if (file_exists(APPPATH.$dir.'/'.strtolower($class).'.php')) require_once(APPPATH.$dir.'/'.strtolower($class).'.php'); } } }
now to your object
create a Product_Object in the application/objects/ directory
(be aware in order to avoid name collision add always the _Object Suffix to your Objects)
PHP Code: class Product_Object { private $rez;
public function getImage() { if ($this->nume_imagine) { $strImage = base_url("assets/uploads/".$this->id_produs."/".$this->getParsedImage()); } else { $strImage = base_url('assets/images/no-product-image-available.png'); } return $strImage; } public function setRez($rez) { $this->rez = $rez; } private function getParsedImage(){ $image = explode('.', $this->nume_imagine); return $image[0].'_'.$this->rez.'.'.$image[1];
} }
your model should look like
PHP Code: public function entries_by_limit($start, $limit, $order_by = "order by id_produs asc", $rez) { $this->db->select('a.*'); $this->db->select('b.nume_imagine', false); $this->db->from("$this->_table a"); $this->db->join('imagini_produse b', "b.$this->_primary_key = a.id_produs", "left"); $this->db->limit($limit, $start); $this->db->order_by($order_by); $result = $this->db->get();
$arrData = array(); foreach($result->result("Product_Object") as $objProduct) { $objProduct->setRez($rez); $arrData[] = $objProduct; } return $arrData; }
your controller function could be
PHP Code: public function listProducts() { $arrProducts = $this->produse->entries_by_limit((($page-1) * $config_pagina['per_page']), $config_pagina['per_page'], $order_by, '270') $arrViewData = array("produse" => $arrProducts); if (count($arrProducts) > 0) { $this->load->view("your_view_name", $arrViewData); } else { $this->load->view("no_products"); } }
and finally your view
PHP Code: <?php foreach($produse AS $objProduct) { ?> <img class="primary-image" src="<?=$objProduct->getImage(); ?>" alt="" /> <?php } ?>
with this approach everything is on its own place
and if you want to manipulate product data you can do this in your own object and you could be sure - every time a product gets instantiated you have the right data and methods.
-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
I am not very convinced about this method because I must do a foreach in models. And let me tell you why:
in Products model I may have:
select_by_id
select_by_slug
select_by_category_id_by_limit
select_by_category_slug_by_limit
entries_by_limit
And think that I must make a foreach inside all this models. A lot of duplicate foreach ....
-
sintakonte
Member
-
Posts: 89
Threads: 10
Joined: Nov 2014
Reputation:
4
I don't understand what you mean
in your example you have a Model which uses exactly the foreach approach
Quote:foreach($result->result() as $single) {...
and if you have a function where you know exactly that you expect only one result
than you can write something like
PHP Code: $result = $this->db->get(); if ($result->num_rows() == 1) { $objProduct = $query->row(0, "Product_Object"); return $objProduct; } return false;
-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
Yes my Model used the foreach and because of this I posted ...
Yes, sometimes I have result and sometimes row with 1 result.
-
sebastianvirlan
Junior Member
-
Posts: 32
Threads: 11
Joined: May 2015
Reputation:
0
11-11-2015, 01:00 AM
(This post was last modified: 11-11-2015, 01:06 AM by sebastianvirlan.)
(11-10-2015, 02:07 PM)dubefx Wrote: @sintakonte very interesting aproach, i learned something new today, so thanks. But CI3 already have this functionality custom_result_object and custom_row_object and can be used in your example model like:
Code: public function entries_by_limit($start, $limit, $order_by = "order by id_produs asc", $rez)
{
$this->db->select('a.*');
$this->db->select('b.nume_imagine', false);
$this->db->from("$this->_table a");
$this->db->join('imagini_produse b', "b.$this->_primary_key = a.id_produs", "left");
$this->db->limit($limit, $start);
$this->db->order_by($order_by);
$query = $this->db->get_compiled_select()
$result = $this->db->query($query);
return $result->custom_result_object('Produse_Object');
}
Autoload for _Object is still required, but if you don't want to register new autoload simply add at the end of Produse model the Produse_Object class and is done. Also you can access all CI mega object by adding:
Code: public function __get($name)
{
return get_instance()->$name;
}
in Produse_Object class (in case you are not extending Produse class).[/code]
So is still need for hook? Please post your full final code. I don't see where you pass $rez.
|