Asynchronous PHP - php

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.

I would do this in a two step AJAX call.
Here is what should it look like:
User opens a form and fills in the data
User clicks on submit button - an AJAX call is sent to the server
A new entry is written into the database and last ID is returned as response back to JS
You show user the message that the form was submitted
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...

I used processes for this.
the client requests
the server answers and gives the client an answer ID
the server starts a php process which does long running stuff in background and saves the result to a file
the client requests the answer with the ID every few seconds
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.

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

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.

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.

Related

calculation take time to complete, but i want to make it processing in background and user can visit another page?

I have php page where calculation take time to complete, but i want to make it processing in background and user can visit another page and when the calculation get competed show popup and user click on that link and show that calculation?
please check this screen recorder of issue
https://youtu.be/nqedwjOj-SQ
database is very big
thanks in advance
The approach explained here uses Javascript and PHP in combination to solve the problem.
First Step,
Make an AJAX request from the browser(with Javascript) to the backend PHP calculation logic. You can seperate the calculation script which will not render the HTML to show full web page. It will send a JSON response with message log to the AJAX request.
Second Step,
Save the AJAX request state(running|completed) on browser local storage. It is necessary to make the call persistant across multiple page visits.
Third Step,
In your PHP calcualation script you have to save the state(running|completed) of the calculation script. It is necessary to track the progress of the calculation.
Fourth Step,
If the user is in the same page for the duration of the calculation script to run then the AJAX request can handle the calculation complete notification. Otherwise check if a request has already been made(from local storage data that you have saved in the Second Step). If yes then retrive the data from the data base(that you have saved with PHP on Step Three).
Hope that explains the process.

What's the best approach for deleting the record: Laravel 5.2.15

I am using Laravel 5.2.15.
There are list of records in a webpage with Edit and Delete button with each record. I have two approaches for deleting the record
Use JQuery and send Ajax Request to server.
Place a form tag for delete button in each row.
I have following question
In case I use Approach 1, can it cause any issue when the site will be viewed from Android or iPhone? I have another option to do Server side validation using Request class.
In case of Approach 2, Will it make the page heavy? I am using Pagination, so 10 records will be displaced per page.
Please guide me if I should go with which approach or please suggest if both approaches are incorrect.
The questions you have don't really focus on the main reasons to choose one above the other. They differ mostly in how the request is sent to the server and how the page is refreshed to show the results.
Using Ajax is a very common approach and relies on using Javascript, a technology that has been available in all browsers for a very long time. Compatibility will not be a problem as most of the internet wouldn't function without it anyways (and you can even make it work using your second approach as a fallback mechanism). The request you sent is typically a HTTP DELETE request to a REST endpoint so that the server then knows to delete the record1. Upon receiving the success response from the server the page is responsible for updating itself by removing the row corresponding with the just deleted record, and possibly fetching new records to still have 10 rows on that page. No page refreshes required, but some Javascript required.
Your second approach is kind of old school in that the form you submit contains some kind of identifier such that the server knows what to do. This is a full page load and should be a HTTP POST request if you want to do it properly2. Following the Post/Redirect/Get idiom the server then sends a Redirect response so that the browser will then trigger yet another normal page load as GET request to show the user the updated list of records. You do not have to update the page manually by yourself, at the cost of having annoying page reloads (this isn't really expected anymore in the current day and age).
My advise would be to go with the first approach. It is the modern way of doing things and allows for having non-reloading pages. It does however require some additional work on the client side (in Javascript) to update the page accordingly.
As a side note, CSRF must be taken care of in both instances really. Always include a CSRF token with every 'update' action you perform on the server.
1 You have to program this yourself, of course :)
2 Browsers don't generally support anything other than GET and POST, although the HTTP specification allows for much more request methods.
It depends upon your requirements. But you should go with the 1st approch. If you will use 2nd approch the you will have to refresh the page since you can not handle the response. So basically if you delete 5 items the page needs to be refreshed 5 times and you may not send more than 1 delete request at a time. Now If you use 1st approch since It's ajax and javascript you can display appropriate message depending upon the result and no need of unnecessary page refresh.Plus as you mentioned you can do validaton using Request class. So you can handle bad or malicious request. And I am sure CSRF won't be that much of a problem since you can check whether the request is ajax or not using Request::ajax(). So 1st approch is better mostly because of that no page refresh.
Both approaches are fine ;)
But 2nd approach would be better than first one; Using this approach you can prevent CSRF attacks too;
I would suggest you to use method 1 with certain modifications.
Use get request to delete the record.
Send a CSRF token and dont forget to encrypt your id for the record
add your delete URL to href
Then when you do ajax request, use the url from href and you could send some additional parameter like is_ajax=1, but laravel already checks for the jquery header so Request::isAjax() method will let you know if the request was an ajax request or normal request.
Now all you need to do is send different response for ajax and normal request.
HOPE THIS HELPS :D
Another drawback of your second approach which haven't been mentioned is displaying validation errors. Specifically from your edit and even your delete actions.
If you have multiple forms for each set of data showing errors from validation would be a pain. But if you follow approach number 2 just by getting the reference of the row element submitted, you could easily append an alert div if ever an error from validation has occurred.
as for the delete action, somebody else might have already delete some shared data so you might also want to tell the user somebody already threw this out.

How to keep track of multiple request data from the same user in PHP sessions?

So the question is a little complicated, let me explain. My page code is running like this:
User enters query in the search field and clicks submit.
1.1 jQuery loads a new body to display progress data.
1.2 jQuery calls process.php via AJAX and supplies query as the argument.
1.3 jQuery starts setInterval periodic update to grab progress data, stored inside $_SESSION['prog'], and displays it.
When process.php finishes, jQuery stops periodic update, displays final information and calls AJAX to clear the $_SESSION['prog'] variable.
At the moment progress data is stored inside one variable, which is fine as far as different users are concerned (because of the different sessions), but if the same user were to make multiple requests at the same time, the $_SESSION['prog'] variable would be cross-overwritten.
So far I have thought of two possiblities to distinguish data for each request from the same user (same session)
Have jQuery generate some random string and send it together with query (and hope to avoid colission, although that would be unlikely)
Make 2 AJAX calls, first one requesting new_request_id, the second one sending query and new_request_id as parameters.
Have AJAX return something from PHP before is finishes(completes).
I need to connect each browser window (each request) with each running process, so I cannot send back new request ID after the request has been submitted, because I wont know which data to pick up with jQuery in the browser window. Btw, I will change $_SESSION['prog'] to $_SESSION[request_id] -> request_id is what I'm looking for.
It (request_id) could be last_insert_id(), because im creating new DB entries for each valid query, but I don't know how to get it back to each different user window.
I need advice here. Only just begun to code in PHP, AJAX and jQuery, don't really know much about sessions. How should I solve this problem?
Sorry for the lack of code, I will paste is at request.
You could add a unique ID to each request in addition to the session ID. eg. uniqid() in javascript/jquery?
You need to differentiate them somehow. For example use a unique ID autonumber field. MySQL has last_insert_id() which is very useful and handles concurrent requests correctly.
Avoid using Session variables in Ajax requests. Send them with GET (or POST) instead. Even if calling Session_start(); in the Ajax request and getting $_SESSION['prog'] from there, results can be unexpected.

On PHP Server, how to get final search page content after a long wait?

I searched a lot of places, but couldn't find solution.
What I want to do is:
submit a form on PHP server to another server, the request is to search some results back;
The search will take several minutes, so the other server will first return a progress html page, the will page will call back to ping the other server when the final result will be returned;
Get the final result page
The function is easy if form is submitted from browser. After viewing progress page, the final search result page will be returned and shown in browser.
But I don't want to show those on my client. I want to process that on my server, process data and show something else on my client.
Thanks a lot!!
You'll need some way of tracking whether a form has been processed or not - I recommend using a database entry. So here are the basics of your algorithm:
When the user submits the form to your client, you add a new record to the DB.
The required data from this form is sent to the other server.
Any client who accesses your page will be shown the 'Waiting' layout (because the complete DB column is set to '0')
When the processing is complete, the other server hits a listener script on your server, providing it the form ID. You then update the complete column in the DB to '1'
When the user visits the page now, they see its been completed.
I'm not going to write the code for you, but this functional overview should set you on your way.

Is there a way to return ajax POST results in pieces / increments?

Is there a way to pass results generated within a PHP page (called into action by an ajax post request) back to the document in bits / intervals?
Here is an example...
I am making an ajax POST to a PHP document with keywords passed by the user which scans a few sites to determine if they have resources for the search. If they do the PHP file returns a link to the site, and continues to the next one, if not I will just continue on to the next one..
with an ajax (I use jQuery) I can make this request and wait for the page to load, and then show all the links together easilly, but am wondering if I can display the links one by one as they load from the PHP file so that I don't have to wait for every page to be checked.
Thank you for your input.
You can implement this by having the client send a request for the first X (5 or whatever) results, display those, and then immediately send the request for the next X records. Your client will simply continue making requests and displaying records until it gets an empty response, at which point retrieval is complete.
To make this work you either need to maintain state on the server so that you know "where" in the search to pick up searching, or the client needs to include sufficient information in each AJAX request for the server to know how to continue processing.
By the way, this seems more like a GET operation than a POST.

Categories