Where to operate on data? - laravel

My controller calls a repository which gets data from a model, this is then returned up the chain to the controller, which outputs the data in a view.
Where should I operate on this data? For example, perhaps I wish to add a random object to the data:
//Controller
$data = $this->repository->getAllRows();
Where should this go? in the controller? in the eloquent repository?
$data->splice(0, 5, [$myNewObject]);

Depends on what you are doing it for. If its directly related to data, you can place it in model, or its directly related to logic, keep it on controller.
Like you can keep it on model if you need like:
//on model
function getRecentRows()
{
$data = .....
return $data->splice(0, 5, [$myNewObject]);
}
You will keep this on controller if
//on controller
$data = $this->repository->getAllRows();
$data->splice(0, 5, [$myNewObject]);
$datas->each(function($item){
$item->is_featured = true;
});
//return view with data
This might not be the exact answer. You have to provide exact case here.

It depends, but generally I like to keep my models clean without any logic.
Now if that is a single action, just do it in the controller.
If it's a common task and you want to share it along other controllers, you have two options:
Creating a class so you can use that functionality sometimes inside
your controllers
Creating a controller with your operating data functions and extending all of your controllers from it.
I usually adopt this last one, specially when creating API's where I want to create filters to hide some data.
EDIT
This is a screenshot with a structure that I used for my last project named Paka:

Related

Is there any way to call multiple methods with one route in laravel?

I am trying to send some data to my admin dashboard page. The data is for two charts: the first displays the number of articles posted by users in the past week and the other displays the last five articles. However, each of these datas are returned from separate methods of my controller.
So far, I have fetched all the data I need from the database in one method and returned a view with all the data, In this way:
return view('admin', compact('lastUserPosts'))->with('week', json_encode($week))
->with('postNo', json_encode($postNo));
and a normal route like:
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard');
clearly I'm not following the single responsibility principle, so I'm wondering How can I write my code to fetch each set of data from its own method in controller and then call both of these methods in one route.
I would highly recommend that you watch Laracon EU conference there was a talk titled becoming a better developer by using the SOLID principles, aside from that what you can do is separate the logic of the contoller from formatting and fetching the data by creating a middle layer between it and the model something like a PostsRepository now this class should contain the fetching and ajax formating of the Model, import it in your contoller use App\Repository\PostsRepository and instead of the normal model that you enject to your controller method use the Repository instead
Public function getAllPosts( PostsRepository $post) {
.....
}
Now you have access to all the method of the Post model from a different class and you can also test it easily

How do I pass arguments / parameters to model

Following the tutorial how to create a joomla 2.5 component I'm stucked to pass arguments from view.html.php to my model.
$items = $this->get('TableData');
and my TableData model would expect to get the following arguments
public function getTableData($table, $index_column, $columns) {}
You can not do this using the view's get method. Instead you would have to grab the model into the view and call the function directly in the view:
$model = $this->getModel();
$items = $model->getTableData($table, $index_column, $columns);
Alternately, you could create different entry points in the model that would be able to figure these input options either from state information or preset. Many would argue that this would lead to a better application design, since using my code above is putting what should be model logic in the view.
This is just an addon to David's answer.
Because most of the data usually comes from POST / GET methods, depending on your application, you may want to look at how loadFormData() from loadFormData JModelForm or populateState gets overridden in specific Joomla components.
Basically the state of model is set directly from POST data, using JInput.
Also, although it's not a rule or something, 3 parameters is a maximum I would pass to a method. For flexibility I would rather pass an array with can be later extended without changing the method signature.

Access controller method from inside a model

How do I access a controller method from inside a model?
You don't.
Although it is technically possible, if you think that you need to, it suggests a flaw in your application's design.
The Controller layer is the backbone of you application and meant to handle requests from the user, talk to the Model layer, and stitch together the output in the View. Your Model layer should be blind to the Controller and View, but deal with data manipulation only. This is an over-simplified explanation of the MVC pattern (you can find resources for that elsewhere).
Your Codeigniter models should be reusable from any controller, and not dependent on them. There are many solutions to solve whatever problem it is that you have: You can pass data into a model in a number of ways, or you can use the result of a call to a model's method to perform an action in your Controller.
You can use like this:
class some_model extends Model
{
function getController()
{
$controllerInstance = & get_instance();
$controllerData = $controllerInstance->getData();
}
}

Where does Zend_Form fit in the Model View Controller paradigma

The Zend Framework is mainly meant for MVC use. One of the very usefull components is Zend_Form.
I have a bit trouble finding the place of Zend_Form. Is it part of the view, model, or controller and which responsibilities should I give it.
The thing is, Zend_Form does two things: decorate and render the form and validate it. The first is a real view task, the second a real model task.
Now the most common use seems to be to have the forms interact with the controller only, effectively putting both tasks (rendering and validating) to the view/controller.
Another option given by Matthew Weier O'Phinney is to attach the form to your model, and adding the later view options in the controller.
So, I'm doubting. Where in the MVC pattern should I place Zend_Form and how should I use it?
Edit Good answers so far, thanks! I will be awarding the bounty an hour or two before it expires, so please give an answer if you have some more thoughts!
Zend_Form can be viewed at different points. It can't be considered at all as part of just one layer of MVC pattern.
First of all Zend_Form use decorators and view helpers to render the form, at this point it is part of view layer.
Then, Zend_Form does part of the model job filtering and validating the content.
We know that Controller layer render input from the view and pass it to the model. Actually, the controller layer decide which resource to load from model layer and then perform the corrects calls.
When you call Zend_Form from controller layer, you can consider that you are calling one model resource to perform valitations and filtering actions and decide whether or not this is a valid input. For example:
public function newAction()
{
$form = $this->getForm();
if($this->getRequest()->isPost())
{
$formData = $this->_request->getPost();
if($form->isValid($formData))
{
$Model = $this->getModel();
$id = $Model->insert($form->getValues());
}
}
$this->view->form = $form;
}
Tie Forms to the model can be considered a good pratice because when you are performing filtering and validation actions you are on model layer. So, as Matthew proposed:
class Model_DbTable_Users extends Zend_Db_Table
{
protected $_name = 'users';
protected $_form;
public function getForm()
{
if(!$this->_form)
$this->_form = new Form_User();
return $this->_form;
}
public function add($data)
{
$form = $this->getForm();
if(!$form->isValid($data)) return false;
if($form->getValue('id'))
{
$id = (int) $form->getValue('id');
$this->update($form->getValues(), 'id =' . $id);
}
else
{
$id = $this->insert($form->getValues());
}
return $id;
}
}
From the standard directory structure we can see that Forms aren't in the model folder nor in the view folder because Zend_Form is a specific class that tie many resources and layers together. If you check the Matthews post you will realize that this is exactly what is being said when the action url is set on the view script and the form is tied to the model.
Finally, you can analyze your context and pick up one of these two approachs.
Currently, my choice is to tie forms to models. Looks nice! And make a lot of sense to me.
IMO, Zend_Form is designed to wear multiple hats. It is, in fact, a bridge between the view and model with a giant support beam from the controller.
Instead of assigning a Form to a Model, consider assigning Model(s) to a form.
In the Model layer, you can have a a getFormInputs method that could return the Elements needed to input data. The model doesn't care what form is going to use it, it just makes it available to any from that wants them.
Now in your form layer, make a setupInputs method that will loop thru an array of models to grab all the inputs. If there was only one model, add the inputs to the form. If there was more then one model, make sub forms.
Your controller will initiate the form and pass the values back to model (see Keyne's newAction method)
Zend_Form does often feel like the odd man out. I think everyone's mileage varies.
Lately, most of my administrative interfaces have been very drag + drop AJAX-y, and they require a good deal of html and javascript - actual form elements are sparse. So I chose to eschew a lot of the features of Zend_Form and use it as a fancy view helper with filtering. All my validation is done on a separate layer in the model.
I think O'Phinney's idea makes a lot of sense as well. Here, he's choosing to think of the form almost as a component of the domain object - where he can add business logic. This sounds just fine, as long as you're careful to keep all the view logic for the form separated. As he notes, it's about making semantic sense. There isn't necessarily a hard and fast rule.

MVC: pass model / model data to a view from a controller?

If a view needs to acces data from a model, do you think the controller should:
a) pass the model to the view
b) pass the data of the model to the view
c) neither; it shouldn't be the controllers concern. Let the view access the model directly to retrieve the data. Only let the controller give some parameters the view needs to filter the data from the model.
d) it depends on the situation.
e) none of the above, but [...]
Thanks
After some debate in the comments to an answer that was deleted by the user, maybe this needs clarification. My view of the MVC architecture is biased towards that of the Zend Framework (php) in which an action in a controller by default has a default view assigned to it. So it's not so much the model that dictates which view is approporiate, but rather the controller. Do you feel the model should dictate what view is appropriate? The only way I see fit to let the view be build based on a model, is by letting the controller pass the model to the view. Are there other techniques to let a view access a model without the controller being involved? Or is it perfectly fine to let a controller pass the model to a view, so that the view can be build based on the models attributes?
e) None of the above; pass in a view-optimised "ViewModel".
Example in ASP.NET MVC:-
public ActionResult Details(int id)
{
Product p = ProductService.GetProductById(id);
if(p == null) { return RedirectToAction("Index"); }
ProductViewModel model = new ProductViewModel(p);
return View(model);
}
both a) and b) "will do" subject to d). Never ever c).
Typically, the ViewModel just encapsulates the Model (if nothing complicated is going on, your view could access the model directly via ProductViewModel.Product). If the view needs to do anything complicated with the Model however, it's the ViewModel's responsibility to do that, rather than the responsibility of the Controller, or the View.
This keeps your concerns nice and segregated. Your Controller doesn't care exactly what specific data your View needs (beyond the fact that it's rendering some Details of a Product), or especially what format your View needs that data in. Your View doesn't depend on the implementation details of your Model. Your Model doesn't have to concern itself with how it's being Viewed. If you have two Views rendering Products (e.g. Create, Edit, Summary, MoreDetails etc), those Views can have different ViewModels to expose only the data that each specific View needs, so your Views aren't depending on eachother. Lovely :)
Some further reading from various viewpoints:-
http://www.thoughtclusters.com/2007/12/datamodel-and-viewmodel/
http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx
I think ViewModels are a particularly .NET thing, but I see no reason at all why the pattern can't be used in PHP.
Hope this helps.
Ideally, it should "pass the data of the model to the view" so the view doesn't need to know any explicit structure of the model and thus be more reusable and designer-friendly.
But practically, "pass the model to the view" works as just fine. Most of the time you will need a new view anyway because clients never share favorite colors (if you know what I mean :-) so views re-usability doesn't justify having a lot of tedious code required to copy data from the model to the view.
What you should concern more about is the modularity of the controller itself, since many websites do share common functionalities (controllers) such as web forums or a news listing but not looks (views)
This is late I know, but I'm having this issue on a project I am working on. I started with a) - for simplicity - and now running into road blocks.
I am coming around to this method:
e) None of the above; pass in a view-optimised "ViewModel".
because it avoid bloating both your model classes (instances of which are "transaction objects") and your views. For example, you may need to render a number with a specific number of decimal places (this is the problem I am having now).
With an intermediate "ViewModel" this is easy - you just write the relevant ViewModel "getXXX" method to return the number formatted how you wish.
If you just pass the model directly into the view, you will need to specify it in the view every time you use this figure (going against DRY - don't repeat yourself), or alternately, add a rendering method to your model classes (which goes against a class being for one purpose only).
Cheers
a) pass the model to the view
Otherwise the controller is manipulating the view via screening the model. This is what would happen in "b) pass the data of the model to the view". The b) option doesn't really even make sense in the pure MVC pattern. After all, the model IS the data. If the model is changed for consumption, a view has been applied, whether you choose to do it in the controller and pass it off as a controller function. What happens when you have a different view? Does the controller screen its data differently? You soon have two views for model, the controller sub-view and the view itself.
For me that's e).
As already mentioned here, ideally the view and the model are decoupled. The way I prefer to implement this is to have a viewHelper for a model. This has the API the view can use to get the data. Now views are not affected by changes in the model and the view doesn't need to 'get' the internals of the model. These are hidden away by the viewHelper.
example:
class Post {
public function export(ViewHelper $helper) {} // I try to avoid getters when I can
}
class PostViewHelper {
public function getTitle($parameters) {} // title of current post in the loop
}
class PostView {
private $helpers = array();
public function loadTemplate($path) {}
public function addHelper(ViewHelper $helper, $name) {}
public function __get($key) {} // if exists $this->helper[$key] etc
}
in a template
<h1><?php $this->post->getTitle(); ?></h1>
You may want to implement this differently. But my point is in how the view and the model are decoupled, introducing an intermediate viewHelper wich creates the view/template API.
I don't think it's that complicated. a or b.
The controller's job is to manage the relationship. It finds the model and view and provides the view all the model data it needs to do its job. That's it. MVC doesn't dictate the exact form the data takes.
(a) Start simple. It's pretty natural to pass the model objects directly to the view. If you have a page about a Foo, just pass the Foo.
(b) But at times-- and only at times-- you create a value object / DTO to get the data to the view (called a ViewModel above). Do this when there's a mismatch between the view and the native model, such as summary views. If the view is presenting a summary of 1,000,000 objects, you don't want to hand the view the model objects; you want to hand the view a summary of the 1,000,000 objects.
And the exact implementation really depends on the language and framework you are using. But I think these guidelines are a good start.
uhh b.
i dont really see the difference between a and b other then some technicallity of how you will be passing data.
usually you pass a map of data to the view with some data from the model

Resources