EDIT: Previous title, because no one was reading the question: "If I'm making AJAX calls in an MVC framework, is it common to have 'getter' controller methods over the model?"
It's all in the title: If I want to make an AJAX call to delete a user, that DB code clearly lives in the model $this->userModel->delete($id).
If I'm making all of the CRUD calls via AJAX, do I just have passthrough controller methods to expose those model calls to a URL?
function delete($id) {
$this->userModel->delete($id);
}
etc? This seems silly, but it also makes sense... but it also makes me feel like I'm missing something. Is this the most common pattern?
Thanks!
When it comes down to Ajax under the MVC Framework I usually tend to have each function with a specified keyword such as fetch / set.
something like this
class Users extends Controller
{
public function Fetch($id){}
public function Create(){}
public function Update($id){}
public function Remove($id){}
}
To answer your question: yes
The task of the controller is the decision maker, so that you would perform authentication checks etc within the controller for security purposes.
Think of it this way, you would not use the same controller for changing records in your administration as you would within your users front-end, but you would use the same models.
the models should be used in more places than just the front end, so you would not place a session check, input validation in the model methods as you would perform different checks depending on the location the action is taking place.
Your frontend controller would have something along the lines of:
public function Fetch($id)
{
if($this->session->get_userdata("auth_level") & USER_AUTH_LEVEL_READ)
{
//Show data
}
}
where as your administration would have:
public function Fetch($id)
{
if($this->session->get_userdata("auth_level") & IS_ADMINISTRATOR)
{
//Show data
}
}
if you place the very same check in your models then you would have generate several models that would do return the same data regardless of the location.
Related
I want to develop a website and an App for Android and Apple. An App will fetch the data via API from our domain.
Let say on our website, it will show a list of products or create user account; In the controller, I could use internal API request which will then fetch the data via MySQL rather than using MySQL query method directly on it own. Is this common practice or bad practice?
This is example of dingo/api internal request (Laravel):
Route::api(['version' => 'v1', 'prefix' => 'api'], function () {
Route::get('users', function () {
// fetch from database
return User:all();
});
});
In the Controller
class UsersController
{
public function showUsers()
{
$users = API::get('users');
return View::make('users-list')->with('users', $users);
}
}
In this example they have an API route setup for get method at users and API::get('users'); will make an internal request to that end point and return you what ever that method returns
Yes I would consider this common practice. I personally even think it's good practice to consume your own API internally. It definitely helps keeping your code DRY (Dont Repeat Yourself).
Of course it causes a bit of an overhead compared to a direct method call, but I doubt it will be noticeable. Anyways, for your consideration, an alternative would be to keep the API controllers very very flat and have most of your logic somewhere else (in the Model, a Repository or a Service Layer). I recommend doing that anyways. This would mean that you could easily do the same thing in your in your "normal" controller as you do in the API controller because it's basically just a (few) call(s) to another class.
Here's an example to illustrate what I mean
Let's say your users endpoint is a bit more complicated (This includes some eager loading and filtering)
public function index(){
return User::has('profile')
->with('profile', 'city')
->active()
->get();
}
Now of course it still isn't a lot of code and you could easily do the same in the other controller as well. But imagine you wanted to add a new relationship to eager load. You would need to change your code in two places. (If you would forget one you probably wouldn't even notice it...)
One solution to this problem is creating a repository. I won't go into the details on how to implement this pattern (there are a lot resources about this on the internet) but basically in the end you'd have a class like this:
class UserRepository {
public function getAll(){
return User::has('profile')
->with('profile', 'city')
->active()
->get();
}
}
(Ideally you would also have an interface defining your repository...)
Then use dependency injection to make an instance of the class available in your controller: (Again this is not complete you'd need a few more things to set up DI)
public function __construct(UserRepository $repo){
$this->user = $repo;
}
public function index(){
return $this->user->getAll();
}
And in your other controller(s) you could use the exact same call getAll().
I have a problem with PHP/MVC.
This is my index controller.
<?php
class Index extends Controller {
function __construct() {
parent::__construct();
}
function index() {
$this->view->render('header');
$this->view->render('index/index');
$this->view->render('footer');
}
public function test(){
$this->model->test();
}
?>
And this, index model.
<?php
class Index_Model extends Model{
public function __construct() {
parent::__construct();
}
public function test() {
return $this->db->select('SELECT text FROM test');
}
}
}
How can I use this in "index view"?
Of course you can call controller and model methods from your views (if it wasn't possible then you'd need to put EVERYTHING in your view). The idea of MVC isn't complete separation (as some people wrongly think) but separation of the logic. This means that it is fine to pass data between the different parts of the MVC arch; the idea is that you want to try to make sure that the logic in each part is logic that is appropriate for that part.
Many people will over complicate this in search of some ideal which is just silly. I would get rid of the controller method all together and reference the model method directly in the view if all you are doing is grabbing some data to be displayed in the view. There is no reason to waste time and effort passing these results to the controller just to be passed back to the view. You will thank me for this advice once you make a truly large site and look at all of the effort you would have spent doing that (and then later maintaining all of it).
My philosophy is that a controller should be used for just that (controlling the application logic). If you want to display a sidebar with a list of the most recent post that has NOTHING to do with the controller so it shouldn't add any code to it. Save yourself some headache and call the model from the view. In the end your code is going to make more sense if you do.
In response to your question: You cannot use your controller method in the view because it doesn't return anything.
I'm writing a fairly simple "fact database" in PHP (with Codeigniter .. but I am trying to get away from the framework internals for learning purposes), and trying to better my MVC/OOP practices.
Previously I would have done this: a fact model, a user model, a source model .. and inside each of those models I would place the CRUD logic for each. So it would look like this..
$this->fact_model->save($fact);
$this->user_model->deactivate($uid);
$this->source_model->get_id($sid);
But after reading more, it seems to make sense to have a separate persistence model (ie 'database_model'). But then it seems it would have to contain a full range of CRUD for each type of object, which seems wasteful to me. I guess I'm looking for how to go to this...
$this->db_m->save(Fact $fact);
$this->db_m->update(User $user);
// .. etc .. but also ..
$this->db_m->get_user_id($uid);
// .. and ..
$htis->db_m->get_all_facts();
Is this heading in the right direction? Do I just end up testing for type inside the database model and switching when I need to? Or do I extend the database model for each type of object?
$this->fact_db_m->save(Fact $fact);
$this->fact_db_m->get_all();
$this->source_db_m->get_id($sid);
Or something like this, which I guess is the closest to CIs AR implementation.
$this->db_m->save('facts', Fact $fact);
$this->db_m->get('user', array('id'=>$uid));
I guess this is a case of "active record vs repository". I understand that repository is easier to test, and the CRUD logic is separate from the object data, and that separation makes sense to me. But still.. it means you have to write a separate repository model for each entity. Is this right?
BTW - I know Codeigniter has a Database class and uses active record, and in a way I am just kind of re-creating it with some of those approaches. I'm just trying to understand things without relying on the framework internals. Any comments? Is it just a matter of choice?
Trying to do a little research on my own, thanks to your question, I came across this article: http://msdn.microsoft.com/en-us/magazine/dd569757.aspx , which explains the differences between different data access patterns.
I hope i understood the question correctly, but here goes.
My approach would be to use the separation of models, however the one twist i usually do. i will try to be clear.
Lets say my application is going to require 3 unique features. One for users, facts, sources, All of these models might need to use some common functions like SAVE or LOAD, or UPDATE, or DELETE. Instead of duplicating the common functions into each model, i would simply make a base class with all the common functions, a nd have the base class extend the CI_Model, then all my new model files ( users,facts,sources ) i would have extend my common class.
To better illustrate this, i will throw some basic code up
db_common_model Common Class (db_common_model.php)
class db_common_model extends CI_Model
{
public function __construct()
{
parent::__construct();
}
/**
* All Common Functions Here */
public function save()
{
// Do stuff
}
public function update()
{
// Do stuff
}
public function etc()
{
// Do stuff
}
}
users_model Class (db_common_model.php)
class users_model extends db_common_model
{
public function __construct()
{
parent::__construct();
}
/**
* user specific functions */
public function get_one()
{
// Do stuff
}
public function get_all()
{
// Do stuff
}
public function get_latest()
{
// Do stuff
}
public function etc()
{
// Do stuff
}
}
/**
* When using it in CI Controller
*/
$this->user_model->get_one(); // loads user specific function
$this->user_model->save(); // Calls all inherited methods from parent db_common_model
// Etc
This way of setting up your models allows you expand common features in the db_common_model, that are automatically available to all children classes.
This allows for clean organization, and allows you to not have to re-invent your common functions in every model.
Hope this helps.
Good Morning everyone. Recently i've read an article about mvc pattern saying that most of the php frameworks out there implemented the mvc pattern wrong.
php master mvc pattern part 1
php master mvc pattern part 2
Well after reading this and looking over that implementation a question appeared.
How on earth would call in the view the method called in model? What i'm trying to say is this.
This is a piece of code from the article.
<?php
$model = $_GET['model'];
$view = $_GET['view'];
$controller = $_GET['controller'];
$action = $_GET['action'];
if (!(empty($model) || empty($view) || empty($controller) || empty($action))) {
$m = new $model();
$c = new $controller($m, $action);
$v = new $view($m);
echo $v->output();
}
let's say we've written a small implementation of this design pattern after reading the article and we have the following code:
<?php
class Index extends Controller
{
public function __construct(IndexModel $model, $action)
{
$this->model = $model;
}
public function someAction($id)
{
$this->model->getData($id);
}
}
class Index extends View
{
public function __construct(IndexModel $model, $action)
{
$this->model = $model;
}
public function someAction()
{
$this->model->getData();
}
}
class Index extends Model
{
public function __construct()
{
//Some Code Here
}
public function someAction()
{
// Inserting Data into database.
}
}
As you can see we are calling the same method both in controller and in view to get the data from the database. But if i know correctly the view should take care of the controller's job so the $id wouldn't be right to parse it again in the view or something like that. Then how this can be solved?
There's no 1:1 correlation between controllers and parts of the model (note: not "models" but parts of _the model_). Just because you have an "index controller" doesn't mean you need an "index model" and "index view".
The M, V and C are not constructed together. The controller is constructed, and then it decides which model method to load/construct/invoke and which view should respond to the request.
There's discussion about whether the controller should invoke the view, or whether the model should "update" the view. Since web requests are ephemeral and there's no "constant" view, the latter makes little sense in PHP; it's more appropriate for the original SmallTalk or Obj-C or similar environments.
The first code snippet has terrible use of empty (see here) and, again, should not construct all parts together.
MVC should be approached like this:
The model is the app. It's not just a "data handler" or "data store", it is the core app. Everything the app does, business logic wise, is "the model". This includes sending email notifications, database maintenance work and such auxiliary things, they're all in the model.
The view is responsible for producing output of various forms. The view should be able to interact with the model to get the data it needs to do its job. Data should not be "pushed into" the view, the view should be able to "pull" the data it needs; otherwise something external to the view needs to know what data the view needs, which means the view logic is not self contained in the view anymore.
The controller is just the little bit of glue that's left to invoke the correct model method and view in response to the incoming request.
I typically structure these parts like this:
The model consists of various parts, including data storage handlers, "primitives" (classes that model individual business objects) and "services". The "services" contain all the "actions" your app can do and form the model API. Whenever you want to "do" something in the app like "register a user" or "fetch all records for date range X through Y", there's one specialized method for it in the service API. Just looking at this service API you should be able to enumerate all the things your app "does".
There's one object which is either a "dispatcher" or a "service locator" or simply a dependency injection container that simplifies instantiation of these service classes and allows someone to call them. The controller gets one of these and so does the view.
There's a router which does some "rough routing" based on the URL, invoking a controller method. The controller further looks at the details of the request and decides to call a model method and/or to respond with a view.
The view may decide the best way to present some data based on the specifics of the request, e.g. whether to respond with an HTML page or a JSON data blob. Yay for RESTful services.
In rough pseudo code:
$r = new Router;
$r->route($_GET, $_POST, $_SERVER); // or something like that
This dispatches to something like:
class FooController {
public function __construct(ServiceLocator $services) { ... }
public function bar(Request $request) {
$request->assertIsPost();
$this->services->locate('Baz')->froogleTheWibbles($request->getPostParams());
(new BarView($this->services))->displayWibbles($request);
}
}
class BarView {
public function __construct(ServiceLocator $services) { ... }
public function displayWibbles(Request $request) {
switch ($request->accepts()) {
case 'html' :
$this->loadTemplate(...);
...
case 'json' :
echo json_encode($this->services->locate('Baz')->getWibbles());
}
}
}
And the model does whatever it needs to do...
class Baz {
public function froogleTheWibbles(array $data) {
foreach ($data as $wibbleData) {
$wibble = new Wibble($wibbleData);
$this->wibbleStore->save($wibble);
}
...
}
}
There is no "one answer" for MVC, the important part is that the model contains everything your app "does" independent of input and output, the view can produce the right output as requested as independently as possible and the controller is just the little bit of glue that handles input conditions. There are various ways in which this can be realized. The important design principle should be the realization that the view and controller are interchangeable to fit different conditions (web page, JSON API, XML API, SOAP API, CLI invocation, ZeroMQ node etc.), but "the model" is not.
I'm using the MVC pattern in my application.
Now I need the view object in a model.
I don't want to add the view as a parameter for my function in the model (since I need it in other functions as well). And I don't want to keep on passing it.
Should a add the view as an attribute for the constructor of the model?
Is there another way? Shouldn't I be needing the view object in the model in the first place?
What would be the preferred way of doing it?
Example:
Controller
function someAction()
{
$somemodel->add();
}
Model
class SomeModel()
{
function add()
{
if ($view->user) {
// do stuff
$this->mail();
} else {
// do other stuff
}
}
function mail()
{
Mailer::send($view->user->email, $this->getitems(), $view->layout);
}
function getitems()
{
return Items::getitems($view->user);
}
}
If you're really doing MVC, then you won't need the view in the model, because only the controller should have access to the view.
Looking at the code you've provided, I can tell one thing: the add() method should not reference $view in any way (even for accessing its properties). Instead, the model should be provided with the $view->user value from the controller. The same goes for the mail() method.
Consider fixing those issues. Otherwise, you'll get into something worse later on.
The model should be separate from the view. So, as mkArtak said, the controller should be the only thing that communicates with the view. Which then passes only the necessary information to the model.
As for the model, it should really only deal with the information that it understands.
i.e. if you had a Car model... you don't want to build it dependent on it's factory. If you did, you would have to change your code if you wanted to build it in different factory.
The controller is where you 'bake' everything prepare for render. By bake I mean you consider any passed in $_REQUEST params, make model API calls to get the data you need, and set template variables to be rendered. Your action, at the end of this process should make a call to a template (view) you choose in order to render the 'baked' template variables.