Difference between controller and router? - php

I'm currently putting together a little mvc framework for practice, I have a bit of laravel experience so it is loosely based on that. I've made a router that simply returns a specified view for the url that you set.
Now I've also made controller that splits the url and uses the first part after the base url as controller and second part as action. This loads a file corresponding with the controller and a method within that file corresponding with the action.
So if the url is something like: url.com/users/index it will load a UsersController.php file and look for the index() method within that file.
Now I'm wondering with is the exact difference between a controller and a router? It it like a specified? Wherein a router is just a little bit simpler and just reacts to an exact given url and a router chops it up and has a little more depth?
What I currently have seems to overlap quite a bit.

(Presuming that router does not refer to network hardware or wood working tool!)
The router takes the request and decides which controller/controller methods will handle the request.
The controller accepts the requests and handles it!
Now I've also made controller that splits the url and uses the first part after the base url as controller and second part as action. This loads a file corresponding with the controller and a method within that file corresponding with the action.
This isn't really a controller (as far as MVC is concerned) it is part of the routing.
For example take the [GET] uri: example.com/article/view/123
The MVC router will parse the uri and find the following segments
article
view
123
By default most routers would now instantiate the articleController and call its view method passing in 123 as a parameter. (You could alternatively have some getUriSegment(segmentIdx) method, that's a design choice for your framework.)
The ArticleController would have a view method with an $articleId parameter. This method would probably do something like: get the specified article (from a db via a model for example) and then display it (probably by returning a view which has been given the article returned by the model)

The controller sits between the model and the view. It communicates with both to make a response to a request.
The router chooses which controller (and which method on that controller) handles the request. For example it might decide the request 'product/view/123' should call the ProductController's View methods passing 123 as a parameter.
A router might also convert urls. Instead of using, like you said, method and action in the url. You could also have www.example.com/members. And the router would convert it to UsersController's Index method. This allows the user of 'pretty' urls to map to nice logically named controllers.

The router points a request to a controller.

Related

How to knowing that view is linked with controller in PHP Laravel

I beginner in PHP and I sill struggling to understand about controller, view and rout. I do so many thing to showing my code in view.
I write this to connect the function index in file ChargeController
Route::get('/', 'app\http\controllers\ChargeController#index');
So, how can I knowing that code was integration as MVC in PHP?
thank's
Laravel follows MVC design pattern (Model-View-Controller).
Model interacts with database (Laravel's ORM is Eloquent)
View is responsible for rendering.
Controller handles the user input (form inputs, data, validation etc.)
In the web, we have web sites and their urls. You visit a site and move inside a site with urls. Laravel has own Router which maps urls to a controller's action (in your case / maps to ChargeController's index method)
Your request goes into controller's method then you validate user's request if needed. After that you have validated user inputs (string, array, file etc.) with these inputs you may some database queries that handles by Laravel Models.
Controller give/get all information via Models. Then pass these information/data to view.
Laravel has Blade templating engine. It has directives to help you to use PHP inside HTML. Blade view names ends with blade.php (for your example it is resources/views/charge/index.blade.php) from there your controller returns view with givin data from laravel model to your controller.
In some cases, you don't use Laravel's Blade, and directly returns JSON response from your controller to be consumed by your frontend (VueJS, React, Flutter etc.)
So basically how it works is when you navigate to http or https://yourhost.com (with no path, the default path will be /), your application will try to check if the path / is registered. By defining the code on your question, it is registered and Laravel will run whatever method that linked to that path. In this case, it will run your index method on ChargeController class. Inside that index method, you may be needing some data, which you can access using Models class that Laravel provides. After getting those data, you also need to register which view to show with the data inside that index method. If you registered your view and design it correctly, the path / will show the view along with your provided data.
Inside MVC, all of the view's logic, animation, etc. is also coded inside the view file, which makes it different from other design patterns. For ex. there's a MVVM design pattern (Model-View-ViewModel), this pattern separates the view's logic and put it inside the ViewModel file. (see MVVM for more information)

What are these routing styles called in a web application?

What do you call routing that maps one URL directly to a file?
Example:
http://localhost/directory/file.php => /var/www/apache/htdocs/directory/file.php
What do you call routing like one on https://github.com/nikic/FastRoute?
Example:
http://localhost/directory/file => request actually goes to a single index.php file, which then loads routing files or tables and loads appropriate class as defined in the routing table.
What do you call routing that maps one URL directly to a file?
I would call that no routing. Or maybe direct routing? I've never heard anybody use a term specifically for it.
What do you call routing like one on https://github.com/nikic/FastRoute?
That's (typically) the front controller pattern.

What is the right way to pass parameters to a Kohana 3.3 controller called through HMVC?

I am trying to use Kohana 3.3 HMVC approach. I have created a view and a controller for generating a segment of a page (meant to be integrated into the actual web page by another controller and to be never accessed through HTTP from outside a controller) filled with data records retrieved through ORM. What I need is to pass some data (records selection criteria) from the top controller through the middle controller to the ORM model. Altering GET/POST data as suggested here seems wacky (as it is going to alter the whole application state rather than of the target controller as far as I understand) (but perhaps it is considered okay in the PHP world, I don't know (I am coming from the strict C++/C#/Java/Scala world), let me know if so). Is there a better way?
The HMVC approach works just like a normal request except that it has its own instance of the request class. From the HMVC sub request you can access the parent request object by loading the initial request.
$parent_request_query = $this->request->initial()->query();
You can also access the current request.
$current_request_query = $this->request->current()->query();
You could also just pass parameters.
$params = array(
'passing' => 'data'
);
echo Request::factory('controller/action')->query($params)->execute()->body()

Nesting controllers with the Front Controller Pattern and MVC

I'm developing a web application in PHP using an MVC-approach (not using any framework, pure PHP). As is often the case with MVC, every request arrives at a front controller which routes it to the corresponding controller, and executes the requested action. The URL structure looks like this:
www.site.com/controller/action
Let's say I'm building an e-commerce site which has products in different categories. Possible URLs could be:
www.site.com/sofas/overview
www.site.com/video-games/overview
For the first URL, the "sofas" controller is loaded, and the overview() method of it is executed. This all works well until we have to nest these products within parent catagories. I'll take the two previous URLs to demonstrate what I mean:
www.site.com/furniture/sofas/overview
www.site.com/electronics/video-games/overview
Now, the "video-games" controller is nested within the "electronics" controller. However, with the current 'load controller -> execute action' structure this won't work.
A possible solution would be to create a method within the parent controller ("electronics") which gets executed in case an unexisting action is requested ("video-games"). This method checks whether the requested action exists as a controller. If so, the controller gets loaded and the action ("overview") of it gets executed.
I fruitlessly searched for solutions to this limitation of the standard front controller pattern, including here on SO. I think my implementation of MVC is now correct, but the front controller still brings limitations.
I think the thought that you have to have a different "controller" for each different product type may where you are running into problems.
Unless you are going to have drastically different views for each product type, I would think the controller would be linked to a concept such as "catalog" (or "product" or whatever you want to call it). So for example your URL structure might look like
www.site.com/catalog/furniture/sofas/overview
www.site.com/catalog/electronics/video-games/overview
With the catalog portion of the URI determining the controller and the additional URI segments in essence being parameters passed to the controller indicating the specifics of the request.
This would work nicely with an OOP inheritance structure in that you could have a root 'product' class, and then extend that class with subclasses for furniture, electronics, etc. which would each have their own properties specific to the category. You would the further sub-class for sofas, video games, etc.
All your controller would have to do is evaluate the request URI to determine which class to load for the request. So something like:
// assume URI has been parsed to get value such as "sofas", "video-games", etc. into a variable called $class_to_load
$product = new $class_to_load;
$product->overview();
You are confusing MVC structure with routing issues.
The controller should be probably something like a product controller, or a category controller. Group controllers by functionality.
Now routing deals with the structure of the request and where this gets sent in the application.
You should have a routing layer that knows (for example) to send /<category>/<subcategory>/<action> to the appropriate controller (say products controller) with appropriate arguments (i.e category and subcategory) so it can construct a response.
Only directly mapping the url to controller and action (i.e enforcing /<controller>/<action>) is a very limited way of constructing the architecture of your application.

Way to bypass the controller in CodeIgniter?

I've been using the CodeIgniter framework for PHP and am enjoying it, but I notice that it seems to require a controller for every view. I'm wondering if there is a way to call a specific model from the view itself, rather than route through a controller. I understand that use of a controller is best practice in most cases, especially where the data from the model needs to be modified in some way, but I have cases where I just need to do a strict data pull to the view (which is loaded via ajax), and setting up a controller for that seems superfluous.
Any thoughts? Thanks in advance!
You're fundamentally misunderstanding MVC, at least as implemented in CI.
All URLs on your site (at least those that utilize the CI framework) are mapped to functions (methods) within controllers.
http://myCIsite.com/controller/method[/var1][/var2]...
It doesn't matter whether the URL is accessed via regular HTTP or via AJAX. This is always a one to one mapping. Because of this, you should think of the controller/method combination as the "web page". Do not think of the view as the web page.
Models and views are subordinate to controllers. The controller delegates specific responsibilities to them - database interaction for models, and page output to views.
Because models and views only serve to perform delegated responsibilities, their use is not required in any given controller/method. Help pages, for example, generally have no need to interact with a database, so there is no model utilized by the controller/method combination that serves a given help page. Likewise, form handlers frequently redirect to another page upon completion of processing. As such, there is no view corresponding to the form handler (but there is (likely) a view called from the controller/method in the redirected to page).
Furthermore, models and views do not necessarily correspond on a one to one basis with individual controllers/methods. Any given model can be loaded and used from within several controllers. Similarly, a controller could have a single monolithic view that is used by all methods, or each method could be assigned its own view. (Or, as I just said, a given controller/method could utilize no view at all.)
Finally, CI does not enforce strict MVC separation. You can interact with the database and echo HTML all from within the controller and CI will not complain. Nevertheless, this separation and delegation of responsibility is followed because logically separating the responsibilities makes the code easier to read and helps you follow the DRY principle in your coding.
The fundamental Understanding is that the "web page" corresponds to the controller/method. The view and model, when used, handle delegated responsibilities for the controller/method.
I'm wondering if there is a way to
call a specific model from the view
itself, rather than route through a
controller.
That's not possible as of what I know, the main abstract class of the CI controller imposes restriction to use a controller otherwise you will get a fatal error.
And actually what you say will break the best practice of MVC design pattern. You got to go to model through a controller not view.
I'm a bit confused as to exactly what you're trying to achieve. The controller's value, aside from just being a clean way to handle incoming requests, is to manage the interaction between the models and the views and to determine which views to load. It's also entirely reasonable to load model data directly from your views, but how did you get to your view in the first place?
I guess I'm just having a hard time seeing the context here..
To run a query via Ajax you still need to provide a URL / path in the javascript call. You can not get around the fact that a controller function has to "catch" this call; you can not map a url directly to a model. All you need is 3-4 lines of code in your controller.
Via URI routing you can map a URL to a different controller, so you don't "require a controller for every view". I always create a controller called "ajax" to handle those requests.
A basic ajax call with jquery can be something like this
$('#prod_img').load( "http://domain.com/ajax/get_img", {'color': 'blue', 'url_title': 'bla' } )
You can echo stuff in your controller, so rather than trying to bypass the controller you should be looking into how to do away with the views. This will actually be easy, you can load the db class in the controller just as you can in a model.
But if you really don't want to use MVC perhaps Codeigniter is not the framework for you.
You should read more into the principles of MVC.
Views are strictly for presentation of data, the model shouldn't communicate with views directly.
But still if that's what you want then just pass $this->db from the controller to the view and use it in the view.
Then again, this is NOT a good practice.

Categories