Codeigniter - Pass array from controller, to view, and then to another controller - php

I have a controller which handles the adding of records to a database. Sometimes these records require a couple of passwords to be entered, to "sign the record". Therefore, when the form is submitted, it is passed to a function in the controller called "getSignatures." This will load a view with inputs for the passwords needed. The users will then enter their passwords to "sign the document". This will then be passed to a function in the controller called "checkSignatures," which will call a function in the model to check the passwords.
However, I still need to pass through or save all the data from when the form is submitted.
I have tried using a global variable to save the form data, but when the checkSignatures function is called, it's called through a new controller. I also tried passing through the form data to the view, saving it in a hidden input and then passing it back through post but you can't save an array in a hidden input.
Any ideas would be great, and sorry for the long-winded question.

Try using sessions as described here. In particular you should look at CodeIgniter's flashdata.
Sessions will be stored on the server for the entirety of the user's browsing session. This will let you access the data again. Flashdata is deleted after the next page load so they don't stick around for long.

Related

is it okay to overwrite the php superglobal arrays?

Here's essentially what I'm trying to accomplish. I have an HTML form which is processed by PHP. A user is required to be authenticated to be able to submit this form. However, I do not want the user to loose their work if the session times out while they are working on filling it out.
My thought process is, when I perform my authentication check, if it fails, the authentication module can store the $_POST data in the $_SESSION array, and redirect the user to the login page. Once the user logs in, the login page can redirect the user back to the submission page, and the authentication module would then see that there is saved $_POST data in the $_SESSION array, and set the $_POST array back to the values that were stored in $_SESSION. Then the submission page can process the form data as normal.
I have done testing and verified that it is, in fact (at least in the version of PHP I'm using), possible to overwrite the value of the $_POST superglobal in PHP. And, in this particular situation, it seems to make a lot of sense to do so. Using this method, no other site code anywhere, other than in the authentication module, would have to be modified for every form on the whole site to take advantage of the "saved post data" feature.
So, I've asked myself if I could do this, and the answer is yes. But should I? Or are there potential problems with using this method? Part of me says it make a lot of sense, but another part of me worries it might be bad code design. If I shouldn't do this, what would be the proper way?
Thanks to all the comments. I ended up using the following code placed in a common library file used by all pages. The only downside is you do have to remember to use global $post in any function or method using the special POST data. But it has the advantage of not being hackish like my previous idea.
if (isset($_SESSION['authSavedPost'])){
$post = $_SESSION['authSavedPost'];
unset($_SESSION['authSavedPost']); // So we don't try to re-post the same data twice
}
else{
$post = $_POST;
}
The authentication check function used on this and other forms, if it fails, will save the current POST data as $_SESSION['authSavedPost'] = $_POST so it can later be restored by the above code.

Using a class on a multi-page form

I would like to use Classes in my next website. Part of the site involves a multi-page profile form. The visitor fills in their name, submits this and then fills in their date of birth, submits this and then adds some text.
When the first form is submitted I will instantiate the class and update the database etc but when the visitor submits the next form do I need to declare another "new" class or does it stay instantiated?
What is the recommended way of achieving this kind of behaviour (ie not using classes for this / using sessions to hold the data / instantiating all classes on each page refresh / etc)
Thanks for some direction with this.
As PHP is stateless any classes you initiate only exist for that one page. If you create an instance with data in, it will only exist on that page. If you want it to exist on multiple pages then you will need to reload it on every page.
For what you're describing it would seem that you would first gather all the data, storing the users answers in session between each page, and then once you have all the answers initiate your class to do whatever it is you want to with your data.
Php data is unset after next request exept for persistant data like session and etc... .
To answer your question:
If this case is on one request and the scope of the variable is ok you could use the same variable(and instance) of the object.
If not, you should make a new instance.

Pass form data as parameter to Symfony2 controller function via AJAX

I think this is one of the more complex tricks to get right and therefore I have decided to elicit the help of the very knowledgeable people on StackOverflow. My scenario is as follows: I have two entities, a user and an account. A user is always linked to an account upon registration (and depending on the type of user, might be linked to more than one account. Upon registration the function saveUser() is called (via ajax from frontend) and the submitted form data is retrieved from the Request Object. This data is then passed to the function saveAccount($data) (which is called in the saveUser() function) in the form of a parameter and the account is created (sometimes called more than once with different data sets to create various accounts), which is linked to the user.
Now I want to create an account from my admin panel without creating a user, so I want to call saveAccount($data) directly via ajax (from frontend) and pass the form data to it as a PARAMETER (instead of retrieving it in the function via the Request Object), so that I can use the same saveAccount($data) function and that I do not have to create a saveAccount() which works the the Request variable. Does this make sense? Is this possible? If so, how would I go about doing this?
I did not post any code, as I did not see the need for it, this is more a conceptional problem, but if you require the code that I have thus far or if anything is unclear I will be happy to elaborate.
There should not be any saveAccount method, you just rely on relationships between entities, i.e. on a setAccount method, or to a addAccount one in case you need to add an entity to a Collection.
Then Doctrine will take care of saving and persisting everything.
For saving data, I would always rely on a RESTful interface [which you can create easily via FOSRestBundle], and send everything via ajax no matter what; you'll end up with a smoother interface and more maintainable code.
For instances where a controller function can be called either via AJAX with form data or internally by a another controller function the following solution works:
public function saveAccount($data = null)
{
if (empty($data)) $data = $this->getRequest()->request->all();
...
}
Then you can pass an array to the controller function in the same format as your form data array and it will use that data if passed to the function, otherwise it will retrieve the REQUEST (form) data.

Does this protect me against page reload and the back button?

Further to my previous question, here's what I decided to implement; it may not be pure P-R-G, but it seems ok. Care to comment?
The form.php has an action; let's call it validate.php.
validate.php is never seen by the user; if validates all $_GET and, if valid writes it to database and generates the HTML of a confirmation page / if not valid, it generates the HTML of an error page explaining what is wrong.
Whichever HTML is generated get stored in a $_SESSION variable and then validate.php does a header('Location: <as appropriate>);
Finally a page called submitted.php of invalid_input.php (in case the user reads the URL) consists only of echo $_SESSION['form_html'];
That seems to me like is proff against both page reload and back button problems.
Or did I goof by trying to reinvent the wheel?
Firstly, you're better off storing the form data, which means you can perform the validation again. It will also be less html. The problem with the method you're employing now is that it doesn't protect against multiple tabs, since $_SESSION is universal to a browser session.
One way I've used to prevent against duplicate submission (without PRG) is to generate a unique id for every page load (where a form is involved). When I generate that unique id, I add it to a $_SESSION['form_unique_ids'] array, and I include it as a hidden field in every form I generate. Then before I take action on a form submission, I check to see if that unique id is in the session. If it is, this is the first time that form has been submitted, and I remove it from the session. That way if I try to resubmit that page, I will know because that id is not in the session not to process the results.
This could be extended so that instead of storing a single id, you use the id as the key in the array, and let the value be the result of the transaction. Then:
If there are errors, you store the $_POST data as well. Then, redirect to original_form.php?id=unique_id and display the validation results. You can either store them or recalculate them there.
If there is success, store the success message and redirect to success_page.php?id=unique_id. Display the success message prominently there. If you like, you can remove it from the page.
You have the option of removing the session data when you display it, but that would mean if they refreshed the edit page they'd lose the validation messages and saved form data. I'd rather find a way to get rid of data that is old enough that they're not likely to need it anymore.
Anyway, some of those ideas might be useful. Then again, maybe it's way too much effort for the problem. Your call :)
As long as you use a php redirect at the end of your validate you cannot reload or back button into the validate.php

Contact page MVC workflow

All my previous projects have had this workflow on Contact pages
User submits form
Controller gets $_POST details
Controller validates details (and sets error messages if necessary)
Controller sends email
Controller redirects to thanks page
Is this the standard workflow?
I used to validate everything in controllers, and then did some more reading and they recommended against it. Therefore, should I send the $_POST details to a helper type object and let it do all the work (validation/sending)?
In controller we should only check validation. The main validation should be on model before operations with DB.
The controller file need to check & validate the user input data.
After getting & accumulating all the data, it needs to transfer the data to the Model file for checking with the database (if needed) & then need to do some other works from here (like setting sessions / cookies, or sending mails, or firing hooks, ...). However, the control must come back to the same controller method, as all the previous model functionalities must be fired by a method call, from the same controller method.
The proper view method must be called now, and then the output must be rendered to the console.
Hope it helps.
Validation is typically performed in the Model, not in the Controller.
This is because data structures are usually defined in the Model and it is best to compare the acquired data immediately before manipulation (i.e. inserting into a database, etc.).

Categories