Creating task or a view for search results - joomla

I'm making a search for joomla, after clicking search button I am getting this url:
index.php?searchword=aa&task=search
How can I create a view or task for it?

If you use the basic joomla search component you will find the views in
/components/com_search/views/search/tmpl
If you edit the view then its advisable to use template overrides, to ensure you will not lose your views on upgrade : http://docs.joomla.org/How_to_override_the_output_from_the_Joomla!_core
addition :
If you are building a component and you want a task to execute like that, then use this in your YourComponentName.php.
$controller = JController::getInstance('FrontendSuite');
$controller->execute(JRequest::getVar('task'));
$controller->redirect();
And add the task as a function in your controller.php. You will get something like this :
function search(){
$searchword = JRequest::getVar('searchword');
//Do your magic
}
As Valentin pointed out just below, you will need to add option=com_yoursearchcomponent to your URL for Joomla to call your component.
Adding Views to your component is explained quite well in the link Valentin posted below, http://docs.joomla.org/Developing_a_Model-View-Controller_Component/2.5/Adding_a_view_to_the_site_part
Hope this helps,
Good luck

Your URL will be like:
index.php?option=com_yoursearchcomponent&task=search&keyword=xxx
So you need to create a component. Have a look at the Developing a Model-View-Controller Component.
Then you will have in your controller or subcontroller the task search which will call the view search, where you will have the appropiate template for the view.

Related

Joomla Terminology: view, layout, task and component development

I'm a developer and I am very confident with MVC pattern and have already developed a lot of webapp from scratch using php framework like symfony or yii.
I'm a little bit confused about joomla mvc and terminology and after googling a lot, read joomla book extensions guide, read on joomla website my doubt are still there.
What is confusing for me is the component mvc structure and how I have to set up "my way of think" about joomla mvc, for doing the things in the joomla way.
In particular I am used to reasoning in terms of controller/action (like in symfony and yii framework)
So the final list of all my webapp url will be
controller1/action1
controller1/action2
controller1/action3
controller2/action1
controller2/action2
Each controller's action will decide what view to render and what layout to use for showing the view.
In particular in these frameworks, the definition of a layout is exactly the mean of a layout. And the view is the "core part" of the page.
So I can have a view with a list of users and I can put this view inside a mobile layout or a desktop layout, or to build a view for mobile and put it only in the mobile layout and so on.
The final result about directory structure in my webapp is something similar to the following:
controllers/
controller1
controller2
controller3
models/
modelForTableA
modelForTableB
views/
controller1/
viewForAction1
viewForAction2
layouts/
mobileLayout.php
desktopLayout.php
and for me is very clear to understand.
So finally my questions are:
how would be the directory structure in joomla?
what are in joomla the definition of view, layout and task?
I need to clarify that I do not need an explaination about MVC works in general, but if I would achieve the same result as before, how I have to organize my code and my work?
Suppose that I want to build a component with the following "url"
userController/addUser
userController/editUser
userController/listUsers
userController/viewUserDetail
anotherController/addOperation
anotherController/editOperation
anotherController/myNonCrudOperation
Thank you very much
Routing in Joomla is slightly different. The SEF URLs are built from menu items, which in turn point to a View/Layout combination.
This turns things around: a controller is not bound to a specific View/Layout.
Let's make an example of the flow with the addUser functionality you mentioned as an example; I'll be referring to these files (but you'll have plenty more):
/controllers/user.php
/models/user.php
/views/useradd/view.html.php
/views/useradd/tmpl/default.php
/views/useradd/tmpl/default.xml
/controller.php
/router.php
As you can see the layouts are inside each view's tmpl folder.
router.php
Let's start from this last file: router.php defines our custom SEF rules so, after Joomla passes the call to our component (usually with the params
?option=com_componentname) we can takeover and interpret the URL as we wish. It is a bit hard to get started with but does provide the most flexibility and power. We don't really need to implement it at all for this simple example: so back to our registration now.
First step: show the "new user" form.
You would typically bind this to a menu item, pointing to the /views/useradd/tmpl/default.php; the /views/useradd/tmpl/default.xml contains the definition of the layout so it's available in the menu manager. Very often there is only one layout per view.
Control is passed to the view /views/useradd/view.html.php , and the view will then load an instance of its own model (automatically chosen based on the view name, you can load other models of course) to gather any initialization data.
The view then renders the layout, and presents it to the user.
The layout's responsibility includes generating a form with an appropriate action (endpoint) and security tokens if appropriate:
<form action="index.php?option=com_mycomponent">
<input type="hidden" task="user.save">
<?php echo JHtml::_('form.token');?>
as you see it doesn't really matter if you want to use <input or params on the url, and you can most often mix them.
Form interaction
For autocompletion the form may need to invoke some backend controller methods, i.e. the method emailAvailable() in the /controllers/user.php
It does not make sense to have such functionality indexed, so we'll invoke the method directly with a non-SEF url:
index.php?option=com_ourcomponent&task=user.emailAvailable
followed by any other parameter. This will work in both get and post.
The controller /controllers/user.php's emailAvailable() method will return a json structure and then invoke exit() as we don't want the CMS to kick in at all. An alternative solution is to add the param &format=json in the call.
{"email":"johndoe#example.com", "available":true}
Saving the data
When the user submits the form, processing is first handled by the controller since a task is specified. (see above task=user.save). Joomla will invoke the method save() in the controller /controllers/user.php.
This time, however, our controller is responsible for returning information to the user. After processing the data, it may choose to re-render the registration form showing an error, or a thank you page. In either case the controller simply sets the redirect, letting Joomla handle the rendering when appropriate.
$this->setRedirect(JRoute::_('index.php?option=com_yourcomponent&view=useradd', false));
More control
Each time a controller task is not specified, the display() method of the main controller is invoked. You can add custom logic there.
Joomla fires several events during a view rendering; these can be intercepted by a system plugin or - if you add in the calls - other kinds of plugins as well. You may even create your own types of plugins. Do not try to instantiate a view manually from a controller, as this may inhibit plugin firing.
Small insight,
1) Directory Structure
controllers/
controller1
controller2
controller3
models/
modelForTableA
modelForTableB
views/
layout1
2) View and layout and task
check this answer
3) More routing techniques with SEF.
Hope it helps.
solved with this. I cannot delete this question because there already exists other answer.
Could any moderator close or delete this? Thank you
https://joomla.stackexchange.com/questions/18774/joomla-terminology-view-layout-task-and-component-development/18799#18799

Vote for comments in posts function with Codeigniter and routing

I am trying to create posts with comments with CodeIgniter and I am trying to add voting for the comments with + and -.
But my problem is not actually this functionallity but more exactly creating the link and the method in controller/model for this.
I understand that there is some kind of link to methods.
If I have something like this:
public function like() {
echo 'Test Function';
}
and when I create link like this one sitename.com/posts/first-post/like theoritecally I will see blank page with "Test Function" text (and of course if I write proper routing rule but I cannor for now).
I can see a blank page with this working echo 'Test Function', but does this mean I have to load every methods and views for the entire page if I want to display the entire webpage with all the elements? I think that I mistake something very serious here but I don't know what.
The example with the "Create news" tutorial in ellislab.com didnt help me. They show something similar I think with /create/ section in the URL and create() methods.
If I have many links with functionallities do I have to add new routing rules for all of them? I really tried to search in Google and everywhere but I didnt find anything related.
Sorry for this lame question.
You need to use Ajax call and on callback you have to increase or decrease the count. For creating a link , once page is loading render the data and provided the default link like
for + http://<site.com>/<controller>/like?totalLike=<36>
for - http://<site.com>/<controller>/unlike?totalunLike=<3>
Once user will click + link then by using Ajax, call the controller method link/unlike and increase or decrease the count and repopulate the link again with fresh counter.
Hope it will resolve your problem.

Joomla: How to change template on a specific article

Is there a way to change the template on a specific article only?
Note that it should work without linking the article to any menu.
If you want the template override not to depend on the menu position than the standard joomla way of assigning a different template to a menu will not work. You will need to get your hands dirty and write some custom code. You will need to use the article_id as a trigger for template switch.
I did something like that at work but don't remember now how exactly this is achieved. I will post my code here as soon as I locate it.
EDIT: Found the code :)
You need to edit the file /includes/application.php, specifically the getTemplate() method. At the end of this method, just before:
// Fallback template
if (!file_exists(JPATH_THEMES.DS.$template.DS.'index.php')) {
$template = 'rhuk_milkyway';
}
you can add your condition for applying a custom template, like so:
//CUSTOM TEMPLATE FOR THE ARTICLE 13
if (JRequest::getVar('id')=='13' && JRequest::getVar('option')=='com_content') {
$template = $custom_template_name;
}
This will apply the custom template which name is inside the $custom_template_name to article with id=13. You can also use it to apply a different template to components, like I did with simplecaddy:
//TEMPLATE FOR SIMPLECADDY
if (JRequest::getVar('option')=='com_caddy'){
$template = 'shop';
}
You should really try to stay away from hard coding anything in to the template if it can be avoided. Not sure why you would specify that the article not be linked from a menu. The easiest way to accomplish this without having to write and code is to create a new menu, then add a menu item that links to the article you want to specify the template for. You don't have to put the menu in a module anywhere so it will never show up on the site, but it will show up in the menu assignment in the template manager.
You can do this with single articles, categories, sections, or even components. As long as you have a menu link to associate the template to. I always create an Admin only menu to put links that are needed to run the site, but do not need to be accessed by users.
As Brent said, avoid the temptation to modify core Joomla code! Doing this will likely stop you from doing Joomla upgrades 'cos you know it's going to break the core changes that you made.
Apart from the "hidden menu item" technique (which is useful but can break SEF URLs in some situations), a useful tool is Chameleon. This allows you to select specific articles/categories/sections (plus things like browser type, user group, component, whatever) and use these to trigger a certain template.
Though this is an old post, I thought I'd share my thoughts: You can easily change template on a single article, by implementing the onAfterInitialize() - function in a system plugin. No need to modify the Joomla core.
This works for Joomla 1.5, but should also work in 2.5:
function onAfterInitialise(){
if(true){ // f.ex. test for article ID or whatever
JRequest::setVar('template', 'beez'); // change template
}
}
In joomla 3.x versions, url-parameters are handled differently. The following was tested in joomla 3.4.8:
public function onAfterInitialise()
{
$app=JFactory::getApplication();
if(true){ // f.ex. test for article ID or whatever
$app->input->set('template', 'beez3');
}
}
More on writing plugins for Joomla here

Dynamic layouts in CakePHP

Sorry about the question title, but I couldn't find a more appropriate way to phrase this.
I am currently building a CakePHP powered website and I'm not quite sure how to approach the following issue. The website looks something like the follwing mockup:
.
The greyed out areas are part of the layout, because their content does not change between views. In the sidebar, I have a collection of ads who are linked to several models. I need controller logic to determine the picture associated with an ad. Also, the ad list needs to be dynamic. Where should I put the logic for building the sidebar?
I've thought about:
putting the logic into the AppController (beforeFilter / afterFilter) - the problem is I can't use the controller logic I need (the other controllers inherit from AppController, I'm not sure how to use them there).
making a component - is it okay to build components that rely on controllers?
replicating the sidebar code in all controllers that render views - this seems kind of stupid to me.
What is the Cake way for this?
Update
After some reading and experimenting, I've gotten to refactoring most of it.
I obtained the best performance by moving the logic for building my ads in the model (eliminating the component that retrieved the pictures) and not using requestAction. It's almost three times faster and the code looks much better.
I've done something similar for data-driven navigation. I put my logic in AppController::beforeRender and haven't had any problems. I'm not sure I understand your concern related to controller inheritance. I retrieve my menus via:
$menus = $this->NavMenuItem->groupByMenu();
$this->set( compact( 'menus' ) );
I then created an element that renders the menu. It's executed by the layout via:
<?php echo $this->element( 'navigation', array( 'id' => 'secondary', 'menu' => $menus['SECONDARY'] ) ) ?>
If that doesn't help, maybe you can further explain your issue with controller inheritance in a comment.
I guess the answer is requestAction in case the results are cachable:
http://book.cakephp.org/view/434/requestAction
It can be done in this way:
Create an element that will help in layout of the Ad Block
Create one or more controller that will generate the data required for rendering of the block
Use requestAction for getting the data out of the models and into the element.
Check the cake book, there is an example of an element where data from Post Model is used to display top/latest 5 posts. Your requirement, I feel, is very similar to it.
Alex,
you're getting a SQL error because the build() function has to be in the Sidebar model, not controller. Also, you don't necessarily need to use $user = array('Sidebar'); you could calling Sidebar in all of your models with this:
$Sidebar = ClassRegistry::init('Sidebar'); and then $Sidebar->find();, $Sidebar->build(); etc.
Or, if you only need to call the build() function from the Sidebar model, you could do this:
$sidebar = ClassRegistry::init('Sidebar')->build();
$this->set('sidebar', $sidebar);
Cheers.

HMVC and dynamic widgets

Background
I use the word widget as a partial view that have its own controller (so its own actions) and it is placed in almost all pages. I implement the rendering of this via HMVC, that is just great.
Problem
Now, the problem is that the widget itself execute actions. Think about a shopping cart widget. That widget is placed in all pages so the user can see his/her stuff all along. And the widget have actions that are related to it, for instance: RemoveItem, RefreshCart, ApplyDiscountCoupon, etc. Such actions should trigger by a button or link and the link should be something like (in HMVC):
<a href='<?site_url()?>/cart/cart/removeitem/the_item_id'>Remove this item</a>
Ok. Now the user clicks that link, the cart module and cart controller are loaded and the action is executed, the action should look something like:
function removeitem($itemid)
{
// remove the item from db
...
// "load the view" ???
}
As you can see, my question is how to load the view in a HMVC module. The thing is that if I only load the cart view, it will only show my cart, and I can’t just redirect or load the main page because it can be any main page, that is: the cart could be in any main page (select product, keep buying, see product details, billing info, checkout, etc). :/
Another thing: a requirement is that I can’t use AJAX in this project.
Do you know how HMVC handle this?
Thanks in advance.
Ok. No luck with the community. Nevertheless I found a workaround. Hope would be helpful to someone.
HMVC doesn't have a natural solution to this. So I decided to use this workaround:
Into each main controller (that is, no widget, no partial view) I grab the current url in session this way (/controllers/keep_buying.php):
class Keep_buying extends Controller
{
function Keep_buying()
{
parent::Controller();
$this->session->set_userdata('main_uri', uri_string());
}
...
}
Then in my partial view widget (HMVC module view) I have a normal link to my widget controller (/modules/cart/views/cart_show.php):
<a class="button" href="cart/cart/additem">Add Item</a>
At the controller action (HMVC module controller action) I retrieve the current main page, do stuff and then redirect to that page, that implicitly will get into my widget flow (due to HMVC).
class Cart extends Controller
{
...
function additem()
{
$to_redirect = $this->session->userdata('main_uri');
// add-item work stuff...
redirect($to_redirect);
}
}
That is. Is not the ideal approach IMHO, but works.
I know that this topic is over a year old, however I have been Googling to gain some more insight into the structure an HMVC program should take, and how it can be implemented in CI, and have not found very many answers.
I'm pretty sure that for HMVC to work properly, with several widgets incorporated on all pages of a site, they need to be orchestrated by one main controller. This will be the top level of the heirarchy. Let me try to give an example:
You have a site with a shopping cart widget on every page. When you wish to use the cart functionality, you will need to link to methods in the cart module, e.g.:
add
The problem using this link is that you do not want to reload the rest of the site from that module. Instead, you can route the link through your main controller and have it reload the module, calling the desired method. e.g.
add
Then in the site controller, it will simply pass the method call to the main view
<?php
function cart_add($item){
$data['cart'] = 'cart/add/'.$item;
$this->load->view('main', $data);
}
?>
The view will call the cart widget with the following:
<?php echo modules::run($cart); ?>
Obviously this is a simplified explanation, and the main site controller will be handling several widgets in one main view, so passing the correct data will need to be managed better than just calling the main view from within a method. But hopefully this gives an idea of the structure I am referring to.
If anyone reads this and thinks I'm wrong, I would love to hear other solutions people have found to this issue.

Resources