joomla 1.5 multiple models, problem with default view - model-view-controller

I'm developing a view that need to reuse a model, I'm following this documentation http://docs.joomla.org/Using_multiple_models_in_an_MVC_component. But that reference do the trick just (at least as far as I understand) when I use the parameter get task. if I use the view, joomla get me null data.
more clearly
controller.php - the task I named as the view I need
function viewdowhatIneed(){
$view = & $this->getView('viewdowhatIneed',html);
$view->setModel( $this->getModel( 'thenotdefaultmodelthatIneed' ), true );
$view->display();
}
model - thenotdefaultmodelthatIneed.php
class BLAModelthenotdefaultmodelthatIneed extends Jmodel{
function getReusableData0(){...}
function getReusableData1(){...}
}
view - view.html.php
class BLAViewviewdowhatIneed extends JView{
function display($tpl=null){
$dataneedit0 = $this->get('ReusableData0');
$dataneedit1 = $this->get('ReusableData1');
$this->assignRef('dataneedit0',$dataneedit0);
$this->assignRef('dataneedit1',$dataneedit1);
parent::display($tpl);
}
}
SO, what happen to me is:
example.com/index.php?option=com_BLA&view=viewdowhatIneed -> variables(datadataneedit0,dataneedit1) == NULL
example.com/index.php?option=com_BLA&task=viewdowhatIneed -> variables(datadataneedit0,dataneedit1) == Get me right data
then, my question is, is there a way to do the same thing, by using view parameter without task parameter (btw, I know this could be not a important problem, but I'm not an expert and on this reference http://docs.joomla.org/How_Joomla_pieces_work_together, it says:
The task part may or may not exist. Remember that if you omit it you are defaulting to task=display
so I really want to know that. In other words, can my view force to check the controller or vice versa.
Thanks in advance, excuse my english

Related

How to access table data without model in view

I want to know is there any way to access table data without passing it from controller to view in laravel 5 ?
I have an Options table in my database that stores all my project options. it has three column:
id
name
value
Now I want to access each option value in my master.blade.php file.
what is the best way to do it.
If you understand what MVC is all about then you should know that passing a variable from controller to your view is the best practice. View is simply used for presentation and should only be used for presentation purpose for the sake of separation of concern.
With that been said the best approach is:
Create a model for options then pass it through your controller to the view.
For example:
use App\Option;
PageController extends Controller{
public function __construct(Option $option){
$this->option = $option;
}
public function about(){
$options = $this->option->list('id','value');
return view('about', $options);
}
}
To make variable global in all view see my answer here:
Laravel 5 - global Blade view variable available in all templates
Well there can be multiple ways available, but passing your Table data directly into views is not a recommended way, It would be much better if you follow the proper way, means from Controller to Model. Well its upto you. here is my suggested possible ways.
Method 1 (about which you are asking)
in your master.blade.php file, you can also do this,
<?php
$v = new \App\Message(); // your model object
echo $v ->testmeee(); // its method
?>
Method 2
If you are trying to use your Table data globally(means you want options data should be available on all pages/views), then this one is highly suggested way.
Goto your App/Http/Providers/AppServiceProvider.php file
view()->composer('*', function ($view)
{
$user = new \App\User();
$view->with('friend_new_req_count', count($user->getLoggedinUserNewFriends()));
});
now this variablefriend_new_req_count with data would be available in all views (only in views) means you can access in view {{$friend_new_req_count}}

Multiple models for a view without controllers

As I've just started with Joomla component development, this might sound stupid, or might be trivial.
I would like to know if its possible to have different models attached to a view, without using separate controllers?
My intention is actually to use same model for different views.
Thanx in advance...
Yes, you can load any model in the view with
$model = JModel::getInstance('ModelName', 'ComponentNameModel');
OK, got it working.
Basically you just need to check for the 'view' variable in the JRequest class:
if(JRequest::getVar('view') == 'yourtargetview') {
$modelMain = $this->getModel ( 'yourtargetmodel' );
$viewCallback = $this->getView ( 'yourtargetview', 'html');
$viewCallback->setModel( $modelMain, true ); // true is for the default model;
}
And then in your target view class, reference the model functions as follows(notice the second parameter to get call):
$this->targetFieldValue = $this->get('targetMethod', 'targetModel');
Hope it helps...

Getting view to use correct region automatically

As mentioned in an earlier question of mine, I'm new to ATK4 and I'm currently learning, so there might come a few more question. Now to my issue.
I've created a region "Sidebar" in my template shared.html and adding the view to it like this:
class Frontend extends ApiFrontend {
function init(){
parent::init();
/*
Other stuff here
*/
$this->addLayout('Sidebar');
}
function layout_Sidebar() {
$this->add('View_Menu', null, 'Sidebar');
}
}
Then I'm creating the view like this:
class View_Menu extends AbstractView {
function init(){
parent::init();
$this->add('HtmlElement')
->setElement('a')
->setAttr('href', 'testurl')
->set('Link');
}
}
This gives me the following error:
Spot is not found in owner's template
Additional information:
spot: Content
Supplying the add function with $this->template->top_tag as third argument solves this problem:
$this->add('HtmlElement', null, $this->template->top_tag)
->setElement('a')
->setAttr('href', 'testurl')
->set('Link');
...but do I really have to add that to every add() call in the view? It doesn't seem right and I'm quite sure it's not!
When you are creating AbstractView, you need to specify a default template. By default your AbstractView will use the region of from your shared.html. In other words AbstractObject assumes the template of the region it replaces.
when you create defaultTemplate() or pass 4th argument to the add() you can specify a different file to be used for template of your sidebar menu.
In either way - the template should contain a where output of any sub-elements will be displayed.
You may inherit from "View" class which already relies on the custom template containing just a . Your idea of using HtmlElement is just like this, because HtmlElement extends View.

Codeigniter models loaded in controller overwritten by models loaded in models

I'm having Codeigniter object scope confusion.
Say I load a model in a controller:
$this->load->model('A');
$this->A->loadUser(123); // loads user with ID 123
// output of $this->A now shows user 123
$this->load->model('B');
$this->B->examineUser ();
// output of $this->A now shows user 345
class B extends Model
{
public function examineUser ()
{
$this->load->model('A');
$this->A->loadUser(345); // loads user with ID 345
}
}
I would have thought that $this->A would be different from $this->B->A but they are not. What is the best solution to this issue? It appears the ->load->model('A') in the examineUser () method does nothing because it was loaded in the controller. Then the call to loadUser () inside that method overwrites the stored properties of $this->A. This seems like a bugfest waiting to happen. If I needed global models, I would have use static classes. What I wanted was something scoped pretty much locally to the model object I was in.
Is there a way I can accomplish this but not go way outside of CI's normal way of operating?
Followup/related:
Where do most people put there "->load->model" calls? All at the beginning of a controller action? I figured it would be easier -- though perhaps not excellent programming from a dependency injection perspective -- to load them in the model itself (construct or each method).
Whenever you use the Loader Class ($this->load->), it will load the object into the main CI object. The CI object is the one you keep referring to as $this->. What you've done is load model A twice into the CI object.
Essentially, all object loaded using the Loader class goes into a single global scope. If you need two of the same type, give them different names, as per $this->load->model('A','C'). I don't know of any way around it unless you revert to using bog-standard PHP.
In my team's code, we generally load the models in the controller's constructor, then load the data to send to the view in the function, often _remap().
This is not how the loader works sadly. CodeIgniter implements a singleton pattern, which will check to see if the class is included, instantiated and set to $this->A then will be ignored if loaded again. Even if you are inside a model, $this->A will be referenced to the super-instance via the __get() in class Model. Alis it, or just do:
class B extends Model
{
public function examineUser ()
{
$user = new A;
$user->loadUser(345); // loads user with ID 345
}
}
Here's what I've decided to do, please comment if you have advice:
I've extended the CI Loader class:
<?php
class SSR_Loader extends CI_Loader
{
function __construct()
{
parent::__construct ();
}
/**
* Model Retriever
*
* Written by handerson#executiveboard.com to create and return a model instead of putting it into global $this
*
* Based on original 2.0.2 CI_Loader::model ()
*
*/
function get_model($model)
{
if (empty ($model))
{
return;
}
$name = basename ($model);
if (!in_array($name, $this->_ci_models, TRUE))
{
$this->model ($model);
}
$name = ucfirst($name);
return new $name ();
}
}
Do any CI guru's see a problem with that before I invest time in changing my code a bit to accept the return obj, ala:
// in a controller:
public function test ($user_id=null)
{
$this->_logged_in_user = $this->load->get_model ('/db/users');
$this->_viewed_user = $this->load->get_model ('/db/users');
$this->_logged_in_user->load($this->session->userdata ('user.id'));
$this->_viewed_user->load($user_id);
}
I could also do private $_logged_in_user to make it available in the controller but positively force it to be limited to just the current controller and not spill anywhere else, or I could just do $_logged_in_user = $this->load->get_model ('/db/users'); and limit it to just the current method, which is probably what I'll do more often.
This seems like a pretty straightforward way to "fix" this issue (I say "fix" b/c it's not really a bug, just a way of doing things that I think is a bad idea). Anyone see any flaws?

Should I call redirect() from within my Controller or Model in an MVC framework?

I'm using the MVC PHP framework Codeigniter and I have a straight forward question about where to call redirect() from: Controller or Model?
Scenario:
A user navigates to www.example.com/item/555. In my Model I search the item database for an item with the ID of 555. If I find the item, I'll return the result to my controller. However, if an item is not found, I want to redirect the user somewhere. Should this call to redirect() come from inside the model or the controller? Why?
No your model should return false and you should check in your controller like so:
class SampleModel extends Model
{
//Construct
public function FetchItem($id)
{
$result = $this->db->select("*")->from("table")->where("item_id",$id)->get();
if($result->num_rows() == 0)
{
return false;
}
//return result
}
}
and within your controller do:
function item($id)
{
$Item = $this->SampleModel->FetchItem($id);
if(!$Item)
{
redirect("class/error/no_item");
}
}
Models are for data only either return a standard result such as an key/value object or a boolean.
all logic should be handled / controlled by the Controller.
Models are not page specific, and are used globally throughout the whole application, so if another class / method uses the model, it might get redirect to the incorrect location as its a different part of your site.
It seems like the controller would be the best place to invoke your redirect because the controller typically delegates calls to the model, view, or in your case, another controller.
However, you should use whatever makes the most sense for your application and for what will be easier to maintain in the future, but also consider that rules do exist for a reason.
In short, if a coworker were to try to fix a bug in your code, what would the "reasonable person" standard say? Where would most of them be most likely to look for your redirect?
Plus, you said you're returning the result to your controller already... perhaps that's where you should make your redirect...

Resources