16
votes

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?

3
What reason do you have for needing to do this exactly?Jay Gilford
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.itd
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.itd

3 Answers

21
votes

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);
}
7
votes

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.

0
votes

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();
}