I am using a Front Controller to send the user through a series of pages with questions. Pretty much everything must be dynamic as the pages, the questions, and everything else is set in the admin interface and stored in the database.
I am tracking the user's progress through the database by storing a unique identifier in the session and storing the current page the user is on in the database so I can figure out the next page to send them to.
The thing is, there are a lot of special cases to check for. Right now the controller is over 300 lines long and the code is poorly written and I'm the one who wrote it. Plus, I am going to need to add a lot more to this system in the upcoming weeks such as user-generated content and different pages to show depending on where the user is coming from.
I can see that this controller is going to become a big mess fast if I don't organize it well.
What are some good ways or ideas to refactor this?
Generally it's easier to use URLs to determine what you should send to the client. If your questions are submitted via a <form> you can return a redirect to the next question once you have saved the answer. For example if this was one of your questions:
<form action="/questions/14" method="post">...
This would submit to /questions/14 and once you have saved the answer you can redirect to question 15:
header('Location: /questions/15');
exit;
Once you have URLs in place you can split up your front controller into parts that relate to each question. Then all you need is some routing:
if(preg_match('/\/questions\/([0-9]+)/',$_SERVER['REQUEST_URI'],$matches) > 0)
{
$question_num = (int)$matches[1];
if(!in_array($question_num, $valid_questions)) {
// return 404
}
$controller_name = 'Question_' . $question_num;
return new $controller_name;
}
else // check for urls that aren't questions ...
Related
I have an original php page and a popup window written in php, I wonder how to import the variables in the original page into the popup window. One possible problem is the variable in the original page is not defined in itself but in other php pages connected to it, and it will change based on user's choice. Sincerely looking forward to suggestions, thanks!
It is like:
Two files "business.php" and "school.php" share a header file called "info.php", in "business.php" $theme = "business"; and in "school.php" $theme = "school".
In header file, I can use
if($theme=="business"){
echo "<a href='#' onclick='popitup();'>Popup</a>";
}
to have a button in the business header part.
The function for the popup window is like:
function popitup() {
var newWindow = window.open('/../popitup.php', 'name');
if (window.focus) {
newwindow.focus()
}
return false;
}
What I hope to have is using the $theme variable in "popitup.php", such as when user click the "Popup" link from business page, the popup page can show a list of options related to business information.
I would suggest something like the following:
first, start a session and maintain that for all of your pages.
The page that calls the main page sounds like the best place to centralize these things. Let's call that your controller although it may be a misnomer depending on your setup. However, if it is where the variables you are talking about are defined, it is likely close enough.
Have it call your popup, being practically persistent now. Problem solved.
You may want to look into Model-View-Controller (MVC) as well as Object Oriented Programming (OOP) concepts. Make no mistake, this is not that, but a good architecture with planning can make things much easier.
TLDR: sessions
here is a link
here is a user friendly link
edit: just incase you do not want to refactor something you have already in place, you can call your popup with a query string at the end of your url and access them with $_GET[] on the php side. Here is a link for that. Then it would be something like, page.php?option1=abcd&option2=efgh I think of that as messy and a bit antiquated, but it is valid and works fine.
another edit: another option is using cookies that you store in the user's client. It is not as fool-proof though because people may not have them on, but it may accomplish what you are looking for. Here is a link for those.
third edit: you can store your user's choices in a database and pull them with code in the popup as it is rendered.
I'm working with MVC (php) for a tiny website.
For the moment, each view is included from the controller, but just one HTML file per controller.
To begin to optimize (I think), I want to cut some files in two/three parts :
header.php (just html headers).
Headband : this part is my problem, because if a user is connected, I want to display user informations, if he's not connected, I want to display "Register/Login" links. Am I forced to create two different files for this headband ? Is it really a good practice ? it seems not to be a proper way...
If you know some best practices or exemples, thank you.
Footer.php, not important.
I'm certainly no expert when it comes to MVC architecture, but I believe that you should have some logic in your controller to determine whether you need to display the register link or whether you need to display account info. You'd save this in a variable. Then, in your view, depending on the value of the variable you've set, you display one or the other, which can be included as other views themselves.
A bit of pseudocode:
Controller:
if (user is logged in) {
display = 'register link'
}
else {
display = 'account info'
}
View:
print display
Users will enter information on 4 separate pages and click a 'continue' button that takes them to the next page.
I know I shouldn't prevent users from going back and entering information again, but I also need to set up something that doesn't allow users to do something like this:
www.page.com/setup1 -> www.page.com/setup3 -> www.page.com/setup4 -> www.page.com/setup2
Right now they could possibly go in any order they want if they just enter the URL.
$URL = $_SERVER["HTTP_REFERER"];
if($URL == "http://page.com/setup1") { blah blah }
I have a variable that handles the page that they came from, displaying certain information based on that. Is there a way to use that variable to handle my issue? If not, what is the best way to tackle this issue that might arise?
Instead of using four pages, write one and work with JQuery which enables you to show and hide successive fields etc. Use Ajax calls to provide any dynamic information such as selectors based on previous answers. Those can populate DIVs or SPANs which carry hidden default responses . There is at least one excellent Validate plugin that works with JQuery so you ensure all fields are correctly completed.
The advantages are an enhanced user experience, faster responses with reduced server load. It also means that if they want to change earlier data you can handle it all via Ajax and a good plan.
Before adopting the above approach, I used to use one framework page to post back to itself using hidden fields to control the flow, passing data with increasing numbers of post variables and nested if's. I made it managable with lots of include files to do the updates and new fields
My issue was solved through session variables. Each page has a session variable called 'steps'. Each step has a number associated with the page that they are on. If they previous session 'step' was not the correct one, it redirects them to the appropriate 'step' page.
$steps = $_SESSION['steps'];
$_SESSION['steps'] = 3
For example, this must be the 3rd page, or 'step' in the sign up process.
If $steps isn't == 3, I have code that redirects them to the start of the sign up process, destroys the session and they must sign up properly.
IS there a way to post a $var to $PHP_SELF so that I can use it further down the script?
After 2 hours reading dozens of questions which helpfully appear in the sidebar to the right,
it became apparent that they pretty much all assume an HTML Form has been / will be
activated.
But psuedo~code of what I need looks more like this:
< php
$someVariable=y;
$otherVar=X;
// and the usual setup for accessing the `$_POST` of php:
$HokeyDino=`$_POST`["SendOFF"];
$SendOFF=101;
// etc. and then come to a point where I need the script to just automatically post a value
[ the lack of knowledge ]
// which if I had tha codez!
// would permit the use of that $var, $HokeyDino ...
if($HokeyDino==100){
// do stuff
}
I don't like looking foolish, but gotta ask away, because I figure I have missed learning some elementary aspect of programming, being self-taught so far, but not knowing what might be lacking makes it hard to go look productively.
Thanks very much!
EDIT // Clarification.
Wow, this is amazing. half an hour, 24 people reading the question. Blows my mind.
Right. What I have gotten done so far to give more background:
A php script which uses fopen to create on the fly another php / html page, and all the
code on the Authouring originating script, to write (a+) to the newly created temp page, the whole thing.
From a loop on the authouring page, I have code for retrieving POSTS I send TO that temp page, and that code gets written to a very temp page... then I cause the first part of the page to be written, to get placed on the Temp page, by put_contents etc.,
Next, from another loop on the Authouring page, I write code which item by item matches the things which were included in the < head > of the Temp page.
Anyhow, without graphics, it's a bit tough to explain. What I have at the point I have gotten to so far, is the newly created/assemble Temporary page, can be accessed as a WebPage,, and a button click on it, will successfully POST a value back to the originating/Authouring script.
Here's the tricky part: There isn't any way I was able to devise, to dynamically create code ON THE AUTHOURING page, to recieve POSTS from the Temp Page.
But I realized that if, in the Loops on the Authoring Page, I was able to $PHP SELF post a
string which would be the code for creating a * $Var = $ POST; to catch the values from button clicks on the TEMP page, it would work.
Critical, is that the Authoring Page, doesn't know how many buttons will be made over on the Temp Page ~ that depends on the number of items in the database, which the loops are reading and translating into code which builds the Temp Page.
So, there is no way to hard~code, on the Authouring Page, all possible code for recieving posts, but I could use one Universal $Var= $ POST[ X ] if I could generate it on the fly in the loop, on the Authoring Page.
Hence the need to write code which will $SELF POST, and have it triggered just by normal programme flow, and not the click of a button in a form.
Hmm.... clear as mud yet? :) the question still is pretty straight foreward.
Cheers!
//// Loop
Create CViewerTemp
read DB and manipulate data
Loop B
create, and write to VeryTempHead page
code which creates the top of CViewer, HEAD items
create, and write to VeryTempBody page
code which will work there, items one by one matching head items
end Loop B
Write code which is 1ne time only stuff, to begin CViewer.
then transfer the stuff from VeryTempHead page, into CViewer, kill
VeryTempHead
then transfer the stuff from VeryTempBody to CViewer, kill Very Temp Body.
Open CTempViwer, click on a Button, a value gets posted to Authouring Page.
Authouring Page doesn't recieve anything, no code to do so exists [YET! :)]
If you want to create data on the fly, but not from $_POST, you can just populate $_POST from any other source like this:
<?php
// some calculations
$_POST['my_var'] = $some_calculated_stuff;
// later in your code
if(isset($_POST['my_var'])) {
// works as if it had been posted
}
?>
Is this what you're looking to do?
It's a bit hard to follow, so I'll suggest another potential:
Have you taken a look at cURL?
I think you mean hidden input fields. You can print them with php and they will be posted to your next php script.
Please note, that the user can change the values and you shouldn't trust them.
Also, you can consider using $_SESSION. That would be the better way to solve the task.
Please note that you shouldn't use PHP_SELF because it's insecure.
I'm working on modifying a copy of social engine so that the sign up process includes an initial survey. I've already got a view, drawn my form however I'm not sure where the logic is processed. I know there are methods inside the corresponding controller but I'd like to save the data once the entire of the sign up process has finished.
Can anyone give me an overview of how the sign up process works in terms of MVC structure and communication?
Just for future reference I've added a blog post that I've created about this subject. It essentially boils down to creating new plugins/views/forms and editing the database in the engine4_user_signup table.
See the full post below for a more in depth discussion
http://garbtech.co.uk/socialengine-modify-sign-up-process/
Each plugin saves the data to the session on submit. Once the user finishes going thru the steps, the session should now contain all valid data. A transaction is then created, and all data is saved to the database. Thats basically how it works.
Of course the plugins can get a bit complicated if you are creating one. I created one myself and it took me a few days. Even then I didnt 100% understand the process, but I believe Ive got it down pretty good now.
You might want to add an extra step in the signup process. For this you need to create a new signup plugin. Take a look at this table- engine4_user_signup, you can see the plugin classes listed here. The classes are located in this folder- \application\modules\User\Plugin\Signup, you have to create a new one here. If you go through these classes you'll probably have an idea how to do what you are looking to do.