Caching and session variables (PHP, MySQL...) - php

Apologies in advance for the lengthy post, just trying to explain the situation clearly.
I've created a PHP-driven website for searching a big (millions of records) MySQL database of people. On the search page you have your usual form for search criteria. Due to the way the people often use the site, the search criteria are saved into session variables so that if the search page is reloaded the previous criteria remain in the form fields (there's a button to manually reset the criteria, of course). This in itself works fine.
I also have two language selection links that store the language selection in a session variable (making the page header load an appropriate localization file), and as above, this in itself also works fine.
What's problematic is that when a user gets the search result, a list of people, and wants to open up detailed info on a person (thus going from search.php to info.php) and then wants to go back to the people listing via the back button, it takes too long to reload the previous page as the page re-sends the MySQL query etc, instead of going back to a cached page. It can take even 5 seconds or more sometimes as the queries produce up to 5000 results - but even say, 200-500 results takes long to reload because the database itself is big and not the fastest in the world. And limiting the number of results isn't really practical.
The obvious solution at first glance would SEEM to be enabling the browser cache. Which is exactly what I did via PHP header and pragma controls. And all seemed well, as going back to the list was basically instantaneous. However, I realized that enabling the cache means the updated session variables don't work. New search criteria doesn't properly replace the old ones when reloading the search page after having been to a different page, and even though you select another language, pages open up in the language you previously were using, because that's the way they were cached! You can force the language to update via F5, but that doesn't seem to help the search criteria much. But even if it did, F5-spam isn't really an answer, it needs to work automatically.
So long story short, how do I make the search result list open quickly without making session variables useless? Or will I simply have to make do with sluggish page loads when using back button, thus annoying users? I really don't want to open the info.php in a new page, either.

Have you considered caching the database results on the file system? I have found the Zend Framework caching class to be very easy to use. You can use any information you want, to differentiate cached results from other cached results. So the caching can be as fine grained as required.
http://framework.zend.com/manual/1.12/en/zend.cache.introduction.html
You don't need to use the whole of Zend Framework to use the class. You can use it on its own.

Related

PHP in same file as form or seperate? Speed

I've just started learning PHP and just done with $_POST/$_GET.
Now I want to know, what is the pro's and con's of having the PHP to process the data from a form inside the same file, or send the data to another file (action="anotherfile")?
Logically I will think that sending it to another file would increase the time process it, but is that true?
When I have the PHP script inside the same file, the page doesnt seem to reload when I hit the submit button (but the content changes). Or does it? If it does, wouldn't the only difference would be that I would have to type the script for the menu (lets say you have the same menu on all pages) in both files? Which would lead to more coding/less space?
what is the pro's and con's of having the PHP to process the data from a form inside the same file, or send the data to another file (action="anotherfile")?
You are conflating files and urls.
By having the logic split between different files (and then included where appropriate) you seperate concerns and make your code easier to manage.
By having a single URL be responsible for both displaying the form and processing the form data you don't end up in the awkward situation where the result of processing the form data requires that you redisplay the form with error messages in it. If you used two different URLs there you would need to either display the form on the processing URL (so you have two different URLs which display the form) or perform an HTTP redirect back to the original URL while somehow passing details of the errors to it.
Logically I will think that sending it to another file would increase the time process it, but is that true?
No. It makes no difference on the time scales being dealt with.
When I have the PHP script inside the same file, the page doesnt seem to reload when I hit the submit button (but the content changes).
It does reload.
If it does, wouldn't the only difference would be that I would have to type the script for the menu (lets say you have the same menu on all pages) in both files?
That's what includes are for.
In any language we always try to write clean code. That's why we follow MVC.
Logically I will think that sending it to another file would increase the time process it, but is that true? I think NO.
Because when we send data to another page and on another page at the top we echo that post data and exit. you will see it will not take time. it take time when we redirect/load some html page after that.
It does not matter where we sending data (same page or another page). matter is what is loading after that.
There is no difference about speed.
Whetever you post the content of your form in standard submit, this data will be sent to the server and a response (after processing ) will be downloaded.
The only difference is about organization of your code. The logic that draws themplate of page (menu or other fixed parts) should be stored in some file that you can include separately or call by a function.
Is also true that when you post your data you do for some reason, register a user for example. Is a good pratice that the php file that handles user registration will do that and output the messages and not other functions.
If your file has some logic switches that make it output either an empty form or a a registration message based on the presence of post or get variables, you will notice that when you scale to more complex tasks this will add complexity and make code mantainment harder.
I'll try to make sure I understand your question by restating it.
If you have a form (/form.php), and the "action" of that submit button leads you to a separate php page (/form_action.php), there is absolutely no difference in speed. Each HTTP request (form.php and form_action.php) is independent - "form_action.php" doesn't remember anything about "form.php" unless you pass that information through (as parameters). This is what people mean when they say that HTTP is stateless. It's worth learning about how HTTP works in general alongside the details of PHP.
If you have a PHP script which in turn includes other PHP scripts, there is a tiny performance impact - too small to measure in pretty much any case I've ever come across.
However, using includes allows you to separate your markup (the HTML) from the logic (the PHP). This is a really good thing if you are doing anything other than tinkering. It allows you to re-use functionality, it makes it much easier to change and maintain the code over time, and it helps you think through what you're trying to achieve.
There are many different ways people have solved the "how do I keep my code clean" puzzle; the current orthodoxy is "Model-View-Controller" (as #monty says). There are also PHP frameworks which make this a little easier to implement - once you've got the basics of the language, you might want to look at Zend or TinyMVC (there are several others, each with their benefits and drawbacks).

large select slowing down page load - caching php

I'm building a web app, the way I started off the app for testing purposes is to load lots of data in to session arrays from my database so I can use the values easily throughout the pages. I have one page the has numerous selects on it, and each time the php page loops through all the variables, chooses the selected one, and outputs the dropdown. One of my arrays though has just under 3000 values and loading this dropdown slows the page down from about 300ms to 1-1.2s. Not terrible but easy to tell that it is less responsive. So I'd like to know if there is anyway for me to improve the load speed, or any thoughts on a substitute for the dropdown.
What I have tried so far:
Session arrays hold all the values, when the page is loaded through jquery ajax method the php page loops through these values and echos the dropdowns.
Php include - create php or html pages of all the values pre written as selects, this creates a ~100kb page for the problem dropdown and this is then included with include. Takes roughly the same amount plus I'd have to then use javascript to set the value, but I'd do this if it could be improved. I thought perhaps some caching could provide improvements here. There seemed to be no significant difference between html and php pages for include but I'd assume html would be better. I'm also assuming that I cannot use regular caching because I am using a php function to include these pages.
I have tried just loading in the html page and it takes about 1 sec on first load, after browser caching it is back down to 100-350ms so I imagine caching could provide a huge boost in performance.
I have considered:
Creating a cached version of the whole page but this will be quite the pain to implement so I'd only do it if people thought it is the right way to go with this. I would have to use ajax to retrieve some data for the inputs which I was originally doing with php echos.
Just removing the problem dropdown.
Just to clarify something I've never had clarified, am I correct in thinking php pages can never be cached by the browser, and so by extension any php included files can't be either. But then how come a javascript file linked to in a php file can be cached, because it is using an html method?
The data being returned and parsed into a dropdown is probably your bottleneck. However, if the bottleneck is actually the PHP code you could try installing an optcode cache like APC at http://php.net/manual/en/book.apc.php. It will speed up your PHP. (Zend Optimizer is also available at: http://www.zend.com/en/products/guard/runtime-decoders)
If your bottleneck is the database where the items in the dropdown is coming from, you may want to try setting MySQL to cache the results.
You may also want to try an alternative dropdown that uses AJAX to populate the dropdown as the user scrolls down, a few records at a time. You could also create it as a text field that prompts the user for possible matches as they type. These things may be faster.
I suspect the problem is the raw size of the data you're transmitting, based on the results of number 2 in "What I have tried so far." I don't think you can rely on browser caching, and server-side caching won't change the size of the data transmitted.
Here are a couple of ideas to reduce the amount of data transmitted during page load:
Load the select box separately, after the main page has been
delivered, using an asynchronous javascript call.
Break the choice into a hierarchical series of choices. User
chooses the top-level category, then another select box is populated
with matching sub-categories. When they choose a sub-category, the
third box fills with the actual options in that sub-category. Something like
this.
Of course, this only works if those 2nd and 3rd controls are filled-in using an async
javascript call.
Either way, make sure gzip compression is enabled on your server.
Edit: More on browser caching
The browser caches individual files, and you typically don't ask it to cache PHP pages because they may be different next time. (Individual php includes are invisible to the browser, because PHP combines their contents into the HTML stream.) If you use a browser's developer console (hit f12 on Chrome and go to Network, for example), you can see that most pages cause multiple requests from the browser to the server, and you may even see that some of those files (js, css, images) are coming from the cache.
What the browser caches and for how long is controlled by various HTTP response headers, like Cache-Control and Expires. If you don't override these in php by calling the header function, they are controlled by the web server (Apache) configuration.

How to pass javascript based capability tests to server, and have server send markup based on test results

I'm considering doing capability/feature tests with JS and sending the results back to the server so it knows what it can/cannot send to client.
It's the same idea as modernizr server - https://github.com/jamesgpearce/modernizr-server
The problem I'm running into is communicating the JavaScript results back to the server on initial page load. I'm not sure what options are available but I know there are not a lot. I've tested setting a cookie and instantly reloading the page so PHP can read the results yet I'm concerned from an SEO standpoint. It just seems like instantly reloading a page will have some adverse affects, also I'm particularly worried if the refresh is on a page that has a form. Once the cookie is set and the user goes to another page, it works fine, it's just figuring out how to serve the content on the initial page load based on the capability tests. I've had a few different thoughts like just using JS to serve the markup on the initial page load and let PHP read the cookie on subsequent page loads, but I'm just not sure what might be the best solution.
I'm just at a loss as to what other options there are. I don't know which direction I should be looking in or if there is any direction at all. I don't know if AJAX would be able to help with this or not. I feel like I'm close, but figured maybe if I asked the community someone might have a good solution.
Thanks!
modernizr-server uses the method you described, it sets a cookie and then reloads the page. (Actually, it doesn't do any content output, the only thing on the initial page load is the JavaScript itself. Has an exit; statement if the cookie it's looking for isn't found.) Anyone who has JavaScript off could probably expect a blank page with it.
It looks like you have a couple of options (this is non-exclusive, there are more.):
Set a cookie and then reload.
Set a cookie, and then use AJAX to fetch the initial page's content. (As you mentioned)
Set an expected baseline of support (perhaps, expect no JavaScript support whatsoever), and serve that on your initial page load. If they have JavaScript on, you can either reload, or use AJAX to tell your server what things it supports and then reload chunks (or all) of the initial page.
Serve no-javascript content to just search engines, use option 1 or 2 for everyone else.
Option three here is the most work intensive, but probably the most inclusive option. (Edit: 3 and 4 will make sure search engines see your content)

Making a menu of tables in php

Ok what I am trying to make is a system that supports tickets. Tickets have all kinds of info on a specific job. How can I make a ticket menu with like links to tickets which contain all the info I need. For instance I click on ticket number 777 so it I have the php?id=777 in the url.
I need this page to constantly look for new tickets.
what you need to do is add a the correct ticket to an anchor
Ticket 777
Ticket 778
on the page.php you can access the ticket number using the $_GET variable
<?php
$ticket = $_GET['id'];
/// now you have the ticket number in the variable
?>
I need this page to constantly look for new tickets.
I'm not 100% sure what you're exactly looking for here, but there are two basic solutions here:
AJAX to update the content without reloading the page
Reload the page every few minutes and have PHP handle it
The first is better for things that are constantly updated, like Twitter posts, news, stock-tickers, etc, but it's a little overkill for something that updates relatively rarely (takes longer than 6 minutes or so).
The tickets should be stored in some kind of database and then read out and looped over to create the table. This would probably make more sense in a list format (stacked divs) instead of a table, but then again, I don't know the specifics.
For the simple PHP generation of links, #Ibu has a good example.
EDIT:
For more information about implementing AJAX, this page has a good example. I would recommend using a framework like jQuery or MooTools to handle the AJAX because there are some inconsistencies between browsers.
EDIT:
From the comments you made, it sounds like you are not very familiar with how PHP works.
PHP is just a templating language with some programming language features. It is best used to generate pages on the fly with dynamic content from a database.
When you try to request a .php page, you are actually telling the server to execute the code in that file. When all the code is finished, the resulting document is given to the requesting browser. The result should be valid HTML if done correctly.

Is there a common name for this "session locking" method?

On one of my pages I have users queue up search terms to be to queried from a 3rd party API. As they're building the queue, my site is making the queries in the background (through ajax) so I can cache the responses, saving them time when they submit. I store a session variable $_SESSION['isloading'] as true during the time that the background queries are running, and its false when they're done.
When they submit, the results page waits for $_SESSION['isloading'] to be false before querying the cache for result. Meanwhile they're shown a progress wheel.
Is there a name for this technique of using a session to locally "lock" a user before proceeding to the next step in the code? I came up with this approach on my own and was wondering if it is a common (or good) solution to this problem, and is used elsewhere.
Putting it in $_SESSION will be a wasted effort. Been there, done that and it didn't work out.
You will be much better off if you provide your "search query string" in as a $_GET variable for your XHR ( marketing people call it - Ajax ).
Off the top of my head, this sounds a little similar to the way some older forum software performs forum searches in the background, and the visible page does a repeated refresh until the background search is complete.
I don't think there's a name for it; I'm also note entirely convinced that it's a great solution. As stevecomrie pointed out, you're going to run into difficulties with concurrency (unless the session variable's name is unique per search query).
I'd instead recommend an XmlHttpRequest (as teresko points out, it's not really called "AJAX", ugh!) and you can handle the "waiting" quite simply with Javascript.
I asked about this on IRC (Hat-Tip to ##php on freenode), and they suggested I just make the search form and search results one page. Then, when they're done entering their searches the view would change rather than submitting to the next page. This would remove the necessity of keeping track of an 'isloading' state. This seems like a better approach to me, are there any problems with it?

Categories