im designing a way the form posts its data.
e.g if we have a login.php, if the user submit we normally post it back to login.php and process it. which means if we have other pages like register.php, editprofile.php, we have to redo the process again. so normally we would do something like this in each page:
if($_POST["btnsubmit"]) {
//do smth
}
Im thinking of doing a common postForm.php which accepts all post requests, pass the data to the respective library and process it.
is this a good idea??
It is definitely a good idea! What you're describing is called a controller, from the Model View Controller pattern. I recommend checking out Symfony, which is a great MVC web framework for PHP.
A single Symfony controller (with a name like actions.class.php) can handle all of the posts and gets, plus the routing to get you there. By Symfony convention, a call to http://mywebsite.mydomain.com/home will run the executeHome function in the main controller. A form on that page could, for instance, post to /attemptLogin, and (again, by convention) Symfony would run the executeAttemptLogin function in this same controller file.
Related
Okay, I'm learning all about MVC, Bootstrap, Ajax and Smarty and I understand the basic principles of MVC. I am having one major issue however and I just cannot wrap my head around it, no matter how much I try and no matter how much reading I do.
At it's very core the thing I cannot seem to get my head around is how to pass variables from view to controller from controller to view.
If I want to assign a variable, I can simply $view->assign('variableName', 'variableValue') No issues there, then in the view if I want to call it, it's as simple as $variableName and it's in the view.
My issue is, I want to be able to minipulate data, for example let's say I want to have a list of items, numbers for the example, a list of 1-10, the user chooses 6, I want a way to be able to "POST" that back to the controller without actually having use POST/GET, I want to be able to essentially let it call an Ajax to send the users selection but I do not know the best way to do so.
If I was doing this without MVC, or Smarty it would be as simple as form, action post, I know that but unfortunately that isnt something I can use in this instance.
Any help you can offer would be appreciated.
I will begin with the normal workflow, e.g. without the MVC approach.
Let's say, in a certain moment you are seeing a web page in the browser and let's call it MAIN PAGE.
When you are submitting a form from main page without using ajax,
the whole page refreshes, no matter if the form action points to the
main page or to another one.
When you are submitting values using an ajax call (as part of the
main page code), then the main page will not be reloaded. E.g. an
ajax call targets ANOTHER PAGE to fetch some data in some format
(html, json, etc) and prints the data on screen, in a specified
container inside the main page.
Now, let's see what happens in a web MVC architecture.
You must understand, that an MVC application consists of only one page: index.php. This page serves as the MAIN PAGE, but ALSO as the ANOTHER PAGE, targeted when using ajax calls. The index.php page is therefore processed each time when you are sending a request to the web server - be it through manually changing the url in the address bar of the browser, through posting a html form, or through starting an ajax script.
All other components of the MVC structure (classes, template files, etc) are serving only one purpose: to build the structure of the index.php page - as main page or as ajax response page.
So, in principle, in the index.php page you'll have something like this:
Read the URL, e.g the url components: controller name, action name, action parameters (HTTP GET query string). For this you can use an instance of a Router class.
Create an object of type Request, passing and saving the url components into it. Here are read and saved the other server request variables too, e.g. HTTP POST, HTTP cookies, etc.
Create an instance of the View class.
Based on the url's controller name instantiate the corresponding Controller class, passing the Request object and the View instance to it. Here you'd give the model layer constructs (like a model factory object) as constructor parameter(s) too.
Based on the url's action name call the corresponding controller method, e.g. the controller "action". Exactly here, inside the controller action, are taking place the processing of the server request variables (saved in the Request object), the loading of the template files and their rendering, including transferring the processed server request variables into them.
In the last step, the rendered template files will be directly printed or further passed to an object of type Response, which in turn prints them.
In the end, you'll have a fully "constructed" index.php page, which will be either printed on screen by the browser (if index.php has the role of a main page) or processed by the browser as the result of an ajax request.
Note that I used the description of the steps found in the classical MVC approach. There are also other... types of this concept, best presented in Architecture more suitable for web apps than MVC?
Other very good resources:
MVC for advanced PHP developers (contains a list of great resources)
How should a model be structured in MVC?
Understanding MVC Views in PHP
Understanding MVC
MVC (Model-View-Controller) in PHP tutorial (Part I...IV)
Model-View-Confusion (Part I+II)
James Mallison - Dependency Injection and Dependency Inversion in PHP
Good luck.
I have a question related to form submission done in PHP application that's built in MVC architecture (self-written framework).
All examples that I've seen so far (including existing back-end frameworks) work this way that once form for adding record to database is submitted then certain method of controller is executed [say i.e. addRecord()], which triggers method of appropriate model. If everything goes OK then record is added and controller's method [addRecord() in this example] renders view of "index" page that displays table with records from database.
What I would like to achieve is to render view with form used to add records (the same that I used to add first record) instead of "index". Obviously I can do it easily by just rendering appropriate view from addRecord() (view with the form).
But the tricky point is when you check url you'll see the following:
The first time you enter it will be i.e.
http://project_name/my_controller/create
Once first form was submietted and you return to the view from addRecord() method then url will be:
http://project_name/my_controller/addRecord
What I would like to see is return to the original url, that is http://project_name/my_controller/create
Not sure if this is clear?
PS. Of course I could use AJAX call for form submission (that way I will stay at the same page) but perhaps it's possible to achieve the same without AJAX.
Thanks in advance,
On the controller you will want to submit to the addRecord route and do the processing. Have a check to make sure it was successful and on successful submission you can redirect back to the create route.
It is hard to give an example since you are using a custom made framework. I use slim which has a redirect method for a route. If what you have made does not have something like that then using should do the trick.
header('Location: '.$createUrl);
die(); //or exit
it may seem like a dumb question because I feel like it is when asking it but I can't find anything about it in the doc.
I need to put a form in the header of my website that appears in all pages.
I need that form to be able to be submitted in every page (no surprise here).
I can display my form via the layout function of Zend Framework, but I can't find the equivalent for the back-end of the website to be able to treat it at only one place, site-wide.
I thought it would be possible to put the form validation in the bootstrap but it doesn't seem like it.
Did I miss something or do I have to, at least, put the form validation in all init() function of all my controllers ?
take a look at the plugin documentation
You can write a plugin that handles your request. If you need to have your form processed before any other actions take place, I suggest you use the dispatchLoopStartup() hook.
You should avoid predispatch and postdispatch in this case, because those hooks are called multiple times if you proces multiple actions (by using _forward for instance)
I'm fairly new to the MVC architecture but I'm picking it up nicely, having my own framework almost done.
Nonetheless, I'm having a 'design issue', how to call the controller?
The controller, as in the function that checks if the user hit the submit button.
Example of controller:
$class->login($_POST['username'], $_POST['password']).
I know a lot of MVC frameworks and apps call it by the URL with $_GET params, but I think it's stupid to have one method or one class for each page that needs a function like logging in.
How do you guys do it? What's your method for this?
Any help is appreciated!
You might want to look up the Front Controller concept (and inversion of control), which you are probably already using in some form, but may not know it. The Front Controller analyzes the URL and current state of things, and determines what controller to load.
In my framework I have "routes" that have attributes, one being "require login". The Front Controller determines what "route"/controller needs to be run and checks for pre-requisites for that route, like login requirement. If the user isn't logged in, then the login "route"/controller is loaded instead of the requested "route"/controller. If login is successful, then control is passed to the appropriate "route" controller.
It shouldn't be the job of each controller to manage logins, only one controller should do that, usually the front controller. Any controller should be able to be loaded under any URL since it's the front controller that determines what controller to load. The sub-controllers don't know "why" they are loading, only that they are loading to do their 1 job.
You could have a base controller which contains a function, requireAccess($access_level). Other controllers would extend this controller. requireAccess() would redirect to the login page if the correct access level is not present.
As for redirection using GET variables for clean urls in MVC, I would not recommend this. It could cause problems down the line with wanting variables that contain slashes in them. Instead we would typically want to get the original request uri, and parse it ourselves.
Typically MVC urls follow the pattern /Controller/Action/Id/etc
Ive run into a little problem with an application im trying to write with CodeIgniter, basically i want to have a login form on each page up the very top of the site, but im finding it difficult to figure out the logic with the validation function.
From my understanding, the validation rules ( set_rules ) have to be set from the controller, now if i want a login form on each page, does this mean i have to set the rules on each and every controller i write? this seems a little odd. can i set the validation rules from inside the view?
What i have at the moment is one view for the login box, which i call from my view with the
<?php $this->load->view('includes/members_login'); ?>
command.
Any help or guidance on this would be great .... im quite stuck.
Cheers,
No, you only have to set the rules in the controller function that recieves/processes the login form. I generally keep a dedicated "Auth" controller to execute related operations like login/logout/reset password/etc...
for layout, you can just include it in the consistant header, but just point the form at your controller/function that processes the login.
For login forms though, I'm not sure why you'd want to "validate" them. Either the user/pass matches up or it doesn't.
One idea that comes on my mind is to create basic layout for all of your pages which will load lets say 5,6 other files and build view for each page.
Some of these parts will be called on every page, like header, navigation... so you can use your login form in these parts and it will be loaded on every request.
I think you should try something like AJAX via javascript to authenticate any user login. Basically the login button would be handled by an onclick event which would get the details of the button and pass it to your "Auth" (or Login or maybe UserAuth - up to you to decide) controller which would do the validation..
If you really want the login form on every page, you could create your own My_Controller and do the form validation in the constructor. Alternatively, as you said, you can do it in the view also. CI doesn't force adherence to MVC. If putting the code into your view would make for quicker development and easier maintenance, there is no reason not to do so.