2

I have a php script that gets user input (some text and a link), puts it in the database and then using the link the user provided, it searches for an image.

The problem is, sometimes it takes a while to search for the image, and this makes the website 'stuck', so the view that says 'Your post has been submitted!' sometimes takes between 4 to 6 seconds to finally load.

Is there a way to make PHP search for the image asynchronously?

You may be wondering why don't I just load the view and then do the image search, or just use AJAX. Well, I need the 'last insert ID' from the database to rename the image according to the item ID, and this can only be done once the post has been inserted in the database.

EDIT 1: I have already read this Asynchronous PHP calls? but I am not sure I understand.

EDIT 2: Here is an overview of the process as requested:

  • Step 1: User opens form and fills 2 fields (some text and a link)
  • Step 2: User submits form
  • Step 3: PHP inserts post in MySQL database
  • Step 4: PHP searchs for an image of that link (crawls the web, takes a few seconds) and saves the image with the name of the last ID from database insert. If last ID was 75 image will be saved as 'img_75'.
  • Step 5: PHP loads 'You have succesfully posted a link'

What I want is step 5 to happen just after step 3, while step 4 is running. I don't actually need the response from step 4. As long as it runs on the background I am happy :)


SOLUTION: I have done what @shadyyx suggests. A simple AJAX call. I really hoped for an alternative but apparently not php nor any other server side language can handle asynchronous calls.

Community
  • 1
  • 1
John Shepard
  • 937
  • 1
  • 9
  • 27
  • 4
    So why can't you use AJAX? Your PHP script will insert the post into the database, then you can get the last insert ID and use it in your AJAX call. You can use PHP to generate the Javascript that will make the AJAX call. – Travesty3 May 22 '12 at 13:23
  • @Travesty3 Its probably because his image-search (may be) needs to happen before the 'sumbit' create a DB record. – UltraInstinct May 22 '12 at 13:26
  • 1
    I'm still not sure why you can't use AJAX. Could you add some more detail about the renaming bit in your last main paragraph, so we can see how that fits into the search? – halfer May 22 '12 at 13:26
  • @Thrustmaster: Then how would making an asynchronous call help that? – Travesty3 May 22 '12 at 13:27
  • @John: Can you post an overview of what you want to do? May be there are better approaches.. – UltraInstinct May 22 '12 at 13:27
  • 2
    If something works by posting to the server, you can be pretty sure it'll work using ajax too as that is all ajax does... – Alex May 22 '12 at 13:27
  • Yup I will post right now an overview of the process – John Shepard May 22 '12 at 13:27
  • AJAX can help you save your visitors' valuable time while just checking an image by requesting with server asynchronously. – Vishal May 22 '12 at 13:30
  • you can pre-create the ID via a quick ajax, then on ajax's response you return this ID and trigger another async ajax, having your user moving freely while your server searches. isnt this possible? –  May 22 '12 at 13:30
  • @Travesty3 AJAX and normal user-triggered requests are identical when they reach the server side. AJAx or no AJAX, makes no difference to PHP, here. What I am thinking is there might be different ways without hitting the DB. – UltraInstinct May 22 '12 at 13:30
  • Without hitting DB? You mean storing previous ID in SESSION variable or in a cookie? – Vishal May 22 '12 at 13:32
  • @Vishal: May be, but that would depend on what OP wants to achieve. – UltraInstinct May 22 '12 at 13:35
  • ... _saves the image with the name of the last ID from database insert_ - no, don't do that. You need to obtain and store the ID from the INSERT in step 3 **for this user**, since by the time step 4 finishes, the 'last inserted ID' as seen by the database may belong to another user. Bear in mind that two users may use this feature simultaneously, but the order in which step 4 finishes for each is not guaranteed regardless of which one submitted first. – halfer May 22 '12 at 13:42

5 Answers5

4

I would do this in a two step AJAX call.

Here is what should it look like:

  1. User opens a form and fills in the data
  2. User clicks on submit button - an AJAX call is sent to the server
  3. A new entry is written into the database and last ID is returned as response back to JS
  4. You show user the message that the form was submitted
  5. and call new AJAX request that will crawl the desired URL, download and save the image with the ID You got from the first AJAX response...

Clear? Easy? I guess it is...

shadyyx
  • 15,825
  • 6
  • 60
  • 95
1

I used processes for this.

  1. the client requests
  2. the server answers and gives the client an answer ID
  3. the server starts a php process which does long running stuff in background and saves the result to a file
  4. the client requests the answer with the ID every few seconds
  5. when everything is in the file the server loads it and sends the result on an answer-request of the server.

used popen() for this...

also the server could tell the client a time-span which the client should wait till requesting the answer.

K..
  • 4,044
  • 6
  • 40
  • 85
  • 2
    Yes, I'd go one further, and set up a queue. Gearman is very good with PHP, but there are loads to choose from these days. – halfer May 22 '12 at 13:27
  • Yes, I made a jobmanager with queues and slots etc. but this is not necessary, I guess :) – K.. May 22 '12 at 13:30
  • Why would this be any better than having an AJAX request wait on for the response? Wouldn't make any difference to the user, just that there's little overhead to the browser. – UltraInstinct May 22 '12 at 13:34
  • In this special case an AJAX request would be sufficient, I guess. But requests can timeout and with my aproach I wanted to eliminate the timeout problems. – K.. May 22 '12 at 13:36
  • 1
    @Thrustmaster - 6 seconds is a long time to lock up a web process. But there is certainly a trade-off to be made between reducing all web operations to sub-second timings, the effort required to get there, and the value of doing so in each case. – halfer May 22 '12 at 13:38
  • @halfer: Only if it is 6 seconds, not if PHP is able to execute the script and respond much earlier. Besides, creating a new process (on the server), and polling for it repetitively is very expensive. Why have tens of request do what a single (asynchronous) request can? – UltraInstinct May 22 '12 at 13:49
  • if you can approximate the time to calculate the result, you could tell the client when he has to come back. this would minimize the polling. – K.. May 22 '12 at 13:52
1

Why not creating a new record, returning last id immediately, and running the new query for updating the record with information?

lukas.pukenis
  • 13,057
  • 12
  • 47
  • 81
1

Here is what I suggest for your case:

  • Send out a cookie to the browser when you have the form page being loaded.
  • The requests for the image should not (and must not) depend on the record that 'would be' inserted.
  • The image you are searching for is to be saved in some temporary path. Associate that path to the cookie. In PHP, you could use $_SESSION[...]. This would be an AJAX request as soon as the user fills out the required fields.
  • When form is submitted to the server:
  • Server gets the image from the $_SESSION variable.
  • PHP moves the file from the temporary location to the actual location.
  • Updates the DB.

Why you should not create a record prematurely

What would happen when AJAX request has struck the server(and the record is created) and then the user navigates away? In such cases you need to have additional constructs to remove that record, which is some sort of extra stuff you wouldn't want to get into.

UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
0

I have already read this Asynchronous PHP calls?

The quality of the answers there could be better.

but I am not sure I understand

err, then maybe you might not understand the answers here.

The short answer is that you can't write asynchronous PHP code.

A longer answer is that you can make parallel HTTP requests from PHP (but still blocking) using the curl_multi_ functions, however if you want to generate a page from PHP without blocking then you'll have to generate HTML containing AJAX calls and let the browser handle the concurrent requests and populate them into the page when completed. Using this approach you have the option of invoking mulitple search threads on your DBMS which (if done right) should run faster than a single request.

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • I really thought PHP would have a way. After all this years of development, one would have guessed they would have done something for the sake of simplicity, something like I guess I will have to go with AJAX then? – John Shepard May 22 '12 at 15:02
  • What you describe is not possible in **any** language - it's not a limit of PHP but of HTTP. – symcbean May 22 '12 at 23:15