Call methods from a model of another component

2,147 views
Skip to first unread message

dommod

unread,
Aug 16, 2012, 6:30:24 PM8/16/12
to joomla-de...@googlegroups.com
Hi,

If I have two MVC components A and B, is there a preferred way of calling methods in one of A's models from within B's code. I know I can simply use php's require function, but will that allow me to lever the full power of the A's MVC structure, for example will it work if I want to call a method from A which uses JTable to access the database?

Thanks

Dommod

TDZWeb

unread,
Aug 17, 2012, 10:05:48 AM8/17/12
to joomla-de...@googlegroups.com
I believe the intended method is for both components to use a common library. You can install code snippets, custom classes as libraries and use jimport() to make sure they are loaded.

How to make a library install package? Several good guides on the interwebs: Let me google that for you ;)

dommod

unread,
Aug 17, 2012, 10:43:18 AM8/17/12
to joomla-de...@googlegroups.com
Thanks for the response

I was already aware of the idea of libraries within Joomla!, but from a structural point of view they aren't appropriate to the problems I wanted to deal with.

One recent reason I've wanted to call functions from other component is the following. I have several components "A","B","C","D".... that manage and display various different types of information in different database tables. Recently I've wanted to add search functionality via a new component "S", that could search the data from within those components. The three solutions I can think of are:
  1. Have "S" know about the tables used by "A", "B", "C", "D", ... and perform direct queries on those tables, then organize and display the results. This solution has a high degree of coupling between "S" and each of the other components. This is actually the solution I implemented.
  2. Create a library that does most of the work of "A", "B", "C", "D" so that "S" can call on function from within that library to get search results. This solution is not very cohesive and would also be highly coupled as code from "A", "B", "C" and "D" would appear together in the library even though its not particularly related.
  3. Implement a search function with a common signature across each of the components "A", "B", "C" and "D" and then allow the search component "S" to call that function on each component and then combine them into a set of results. This is the solution I would prefer to implement.

There have also been other occasions where I would like to call function from the model of one component from within the code of another component.

Thanks for trying.

Dommod

TDZWeb

unread,
Aug 17, 2012, 11:58:57 AM8/17/12
to joomla-de...@googlegroups.com
Well I am only just learning to write components so I may not be the right guy to give advice. However, it occurs to me that you can include classes from anywhere on the webserver so if you need to have your search code "close" to its context, just make an 'assets' folder in each component with a search.php file where you define a public static method for each component that takes the search terms and returns a search result tailored to your S component. Your S component is then responsible for loading the search classes, calling the methods for each and present the result. You could even make a search plugin and expose your components to the built-in joomla search.

No matter what you do, you need to either explicitly load the necessary classes or make sure they are autloaded using a system plugin (JLoader::register($component, JPATH_BASE.'/components/'.$component.'/assets/search.php');). Otherwise I am pretty sure Joomla only loads and instantiates a model automatically when a view uses it and the naming conventions are respected. Therefore, normally, a model's methods are only available when its component is directly accessed with a task that directs the controller to a view that loads the model.

dommod

unread,
Aug 17, 2012, 2:01:27 PM8/17/12
to joomla-de...@googlegroups.com
Thanks again,

I know that it's possible to include files from anywhere on the server (I did mention that option in my original post). I was only using search to illustrate the problem I was trying to overcome, which was to find out if there was a prefered way in which the code in one component could call methods from a second component. I had hoped to find a way of including the code I needed within the MVC structure, but I'm beginning to think that its not possible.

You comment about extending core search with plugins is very intriguing and I've already taken a look at some examples. However the results I want to return are specialized (some contain images) and I don't think that the core search can be extended to take this into account. I was wondering if it would be possible for my search component to fire its own 'search' event that each of my other components could listen for.

Just taking that idea a little further, if I had component I wanted to respond to a search, then I could create a plugin for the component that would return the results, factor out the common code from the component and plugin into a library. This structure would avoid duplication of code between the component and plugin; different components I wanted to search would not be coupled together at all and each library for each component would be highly cohesive. I'm not sure if I'm overengineering a solution here and I don't know whether its worth alterting my existing code to fit this structure.

Thanks for the ideas.

Dommod

laoneo

unread,
Aug 17, 2012, 2:31:29 PM8/17/12
to joomla-de...@googlegroups.com
In my extension suite I'm using the model of the component (which holds the data logic) in a module the following way (don't get confused between model and module):

jimport('joomla.application.component.model');
JModel::addIncludePath(JPATH_SITE.DS.'components'.DS.'com_dpcalendar'.DS.'models', 'DPCalendarModel');

$model = JModel::getInstance('Events', 'DPCalendarModel');
$model->getState();
$model->setState('list.limit', $params->get('max_events', 5));
$model->setState('list.direction', $params->get('order', 'asc'));
$model->setState('filter.ongoing', $params->get('ongoing', 0));

$events = $model->getItems();

dommod

unread,
Aug 17, 2012, 4:48:46 PM8/17/12
to joomla-de...@googlegroups.com
Thank you laoneo, that is exactly what I was hoping for. I've just tested it and was able to call functions from one component from within another component.

Brilliant stuff, I can't thank you enough.

TDZWeb

unread,
Aug 18, 2012, 5:45:36 AM8/18/12
to joomla-de...@googlegroups.com
Ah sorry I guess I got sidetracked by the search thing because I am thinking along those lines for my own budding extension suite. I don't think there is a standard way to make components listen for events. It is rather the other way around, extensions trigger events with the dispatcher and plugins registers listeners there. You can control what arguments the extension sends to the plugin, and the plugins can return a result that get put in an array in the dispatcher's trigger method which in turn it returns to the event caller.

Franz

unread,
Aug 18, 2012, 7:43:06 AM8/18/12
to joomla-de...@googlegroups.com


On Friday, August 17, 2012 12:30:24 AM UTC+2, dommod wrote:
(...)

If I have two MVC components A and B, is there a preferred way of calling methods in one of A's models from within B's code. I know I can simply use php's require function, but will that allow me to lever the full power of the A's MVC structure, for example will it work if I want to call a method from A which uses JTable to access the database?


The reply given by laoneo is basically ok, it is a standard method which i often use.

But to improve on that, I can suggest to read something about HMVC. 
Basically this means developing your component in a way that a task of its controller can be invoked from anywhere, and especially from another component.
It is a sort of "API" where your B component just asks for something to A component; A component does what it has to do and returns the result.
Surely better than to meddle directly with the model, which usually should not be included from a different component (or from a different controller, for that matter).

allon moritz

unread,
Aug 18, 2012, 2:11:49 PM8/18/12
to joomla-de...@googlegroups.com
Basically this means developing your component in a way that a task of its controller can be invoked from anywhere, and especially from another component.
If joomla would provide something like that it would be event better. To go even a step further modern applications have a service oriented architecture (I'm not talking about web services) where the service is the public API of a component which should be invoked from it's own controller and from other components/modules/plugins. This is an approach which makes for example Eclipse so popular among Java developers.

--
You received this message because you are subscribed to the Google Groups "Joomla! General Development" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-general/-/WrqEthu8gEQJ.

To post to this group, send an email to joomla-de...@googlegroups.com.
To unsubscribe from this group, send email to joomla-dev-gene...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/joomla-dev-general?hl=en-GB.

dommod

unread,
Aug 18, 2012, 5:45:09 PM8/18/12
to joomla-de...@googlegroups.com
Hi Franz,

Is what you are suggesting possible (I'm guessing that from laoneo's response that it's not). From the experimenting I've been doing it seems that it's possible to use the getInstance method of the JModel class to instantiate a model from another controller (if you include that class first), but JContollers getInstance methode doesn't seem to allow this.

If you know a neat way to expose the methods of a controller in one component to a controller in another component, then I'd be really interested.

Thanks
To unsubscribe from this group, send email to joomla-dev-general+unsub...@googlegroups.com.

elin

unread,
Aug 18, 2012, 8:56:59 PM8/18/12
to joomla-de...@googlegroups.com
I think that's the direction the platform is headed but it's not close to being used in the CMS yet. Remember when you talk about what "Joomla" does or does not support there are two different things, what the Joomla Platform supports and what is implemented already into the Joomla CMS as an extensible application. You can use platform features in extensions to the cms it's just you'll be more of an early adopter at this point. Still you will be ahead of the game in the long run. Alternatively you can make a platform application.

Elin

Franz

unread,
Aug 20, 2012, 6:06:47 AM8/20/12
to joomla-de...@googlegroups.com
On Saturday, August 18, 2012 11:45:09 PM UTC+2, dommod wrote:
Is what you are suggesting possible (I'm guessing that from laoneo's response that it's not). From the experimenting I've been doing it seems that it's possible to use the getInstance method of the JModel class to instantiate a model from another controller (if you include that class first), but JContollers getInstance methode doesn't seem to allow this.

If you know a neat way to expose the methods of a controller in one component to a controller in another component, then I'd be really interested.

Hi dommod,
as Elin said, as of Joomla 2.5 this is not already implemented, you should code it yoursefl.
You can take a look at Akeeba Backup "Framework on Framework" architecture, which does (just download and use on of their extension).
Unfortunately I am not the right person to explain you more details, since I am myself a beginner of this new approach.
But as several people already agree that this could become a common practice, I was suggesting you that it is worth investigating.
Reply all
Reply to author
Forward
0 new messages