17

I'm working on an OpenCart project, that requires a lot of customization. for my project I have to change something in the cart library (system/library/cart.php).

I would have to call a custom function that's defined inside the product model (catalog/model/catalog/product.php).

In a controller, loading a Model and using its functions is easy:

    $this->load->model("catalog/product");
    $this->model_catalog_product->customFunction();

But how do you load a model outside a controller? You can't create a new instance of the model, I already tried that:

    require_once("catalog/model/catalog/product.php");
    $a_model = new ModelCatalogProduct();

This obviously doesn't work cause models weren't intended to be used in such a way.

I also tried to use the scope resolution operator ( ModelCatalogProduct::customFunction()) It doesn't work either.

I could pass all the required info as arguments, but I would rather use the model inside the cart library class, cause the changes would be global.

Is it even possible to load a model outside a controller in OpenCart?

tereško
  • 58,060
  • 25
  • 98
  • 150
Ziga Petek
  • 3,953
  • 5
  • 33
  • 43
  • What reason do you have for needing to do this exactly? – Jay Gilford Nov 22 '12 at 12:47
  • I joined the project when it was about 70% complete. The price calculation is completely custom and it's implemented only for the front end (The site uses AJAX to get the info on how much it's gonna cost). The problem is, that these changes weren't implemented in backend. So the price is being calculated ok, but when the user adds a product to the cart, it uses the default openCart price calculation. I have to change the getProducts() function so the price will be ok. – Ziga Petek Nov 22 '12 at 12:59
  • The custom price is being calculated in the product model. So now I have the choice of going through all the files and finding where I have to change the code, or I add about 10 lines to the Cart library and it would be done. That's why I'm asking. – Ziga Petek Nov 22 '12 at 13:01

4 Answers4

22

If it's only one method that you need to copy, you would be best adding a method to the Cart class itself. The Cart class will work with the $this->db->query() calls as it already has $db assigned to it even though it's not a Controller/Model

Edit

Should you wish to do this, you could do something similar to the following

public function test() {
    global $loader, $registry;
    $loader->model('catalog/product');
    $model = $registry->get('model_catalog_product');
    $result = $model->getProduct(123);
}
Jay Gilford
  • 15,141
  • 5
  • 37
  • 56
  • 1
    Actually it's about 5 functions. I gave it a try and copied all the needed functions to the cart class (through vqmod) and it's working. Thank you for your answer. However, I'll keep this question open for a while to see if there will be other answers. I'm sure there will be other people with a simmilar problem and they deserve to have as much info as possible. – Ziga Petek Nov 22 '12 at 13:23
  • I've put a method that you could use above. It's a bit hackish, but will do what you need. Just use `$model` instead of `$this->model_catalog_product` – Jay Gilford Nov 22 '12 at 17:05
  • 1
    Thanks, this even worked in OC 4 system/cart – Hayden Thring Jul 19 '23 at 04:56
7

You are able to load a model outside a controlled.

If You need to load a model inside of another model, You could load it the very same way using $this->load->model('my_module/my_model');.

If You need to load a model inside of template file or other custom PHP script, look at the index.php file where the Registry is instanciated - You would need to instanciate it the same way. So Your custom code could look like:

$registry = new Registry();
$my_model = $registry->load->model('my_module/my_model');
$my_model->customFunction();

Anyway I highly recommend not to edit/change the core library files unless You are sure there is no other way how to implement/do what You need.

As Jay Gilford proposed I would implement that function or it's call to the catalog/checkout/cart.php, potentially confirm or success depending on the scope and functionality You would like to implement.

shadyyx
  • 15,825
  • 6
  • 60
  • 95
  • 1
    Does this apply to OC 1.5.6.4? I tried and it didn't work for me. – OC2PS Sep 02 '14 at 18:20
  • I tried this in OC 4 and get Error: Class "Opencart\System\Library\Cart\Registry" not found – Hayden Thring Jul 19 '23 at 04:57
  • Well, @HaydenThring, OC was at a different version back then in 2012 :rofl: I don't work with PHP nor OpenCart for ages now, sorry I can't help you more. – shadyyx Jul 19 '23 at 09:47
  • Its fine, im just leaving note for others, didnt expect you to do anything. the accepted answer worked for me luckily – Hayden Thring Jul 21 '23 at 04:21
0

In OpenCart parts of the model layer are dependent on the libraries. One example is that the ID of the current customer (frontend) or the current user (backend) is needed.

To keep the structure clear and clean and to reduce code duplication, you should not introduce a dependency in the other direction. If a model is dependent on the class user and the class user is dependent on the model, you created a vicious circle.

I would recommend to move the functions into the library layer and remove their implementations in the model layer. To minimize the impact, you can wrap the function call within the model.

library/myClass

function getValue($id){ 
 $sql = "select ..."; 
 $query = $this->db->query($sql); 
 return $query->rows;
}

admin/model/catalog/myModel

function getValue($id){
 return $this->myClass->getValue();
}
ckonig
  • 1,234
  • 2
  • 17
  • 29
-1

In the file "cart.php" in function add() calling function "getProduct" is used in this way:

$this->load->model('catalog/product');
$product_info = $this->model_catalog_product->getProduct($product_id);

So using same way in any other part the file for example in function index() is possible and works.

As an example to warn if entered quantity is more then stock. Accessing quantity using above.

Ghm y
  • 1
  • 1