PHP scripts that upload files, import data, or synchronize two databases often die halfway through for one reason: the default php.ini limits are tuned for serving page requests, not for batch work. When a script outlives a limit, PHP simply terminates it — your import stops at row 4,000 with no bug in your code to find.
The limits that matter
In php.ini, the resource section looks like this. Note that the CLI and web server usually read different ini files — check with php --ini on the command line versus phpinfo() through the web server.
;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;
max_execution_time = 240 ; per script, in seconds (0 = no limit)
max_input_time = 240 ; seconds spent parsing request data
memory_limit = 256M ; per-script memory ceiling
For forms that post large payloads and uploads, two more directives control the ceiling. Modern PHP still ships with surprisingly small defaults (post_max_size = 8M, upload_max_filesize = 2M), and post_max_size must always be larger than upload_max_filesize:
; Maximum size of POST data PHP will accept.
post_max_size = 30M
; Maximum allowed size for uploaded files.
upload_max_filesize = 25M
Raising limits without touching php.ini
On shared hosting you often cannot edit the main ini file, but you rarely need to. Most of these settings can be raised per-directory with a .user.ini file (CGI/FastCGI setups) or per-script at runtime:
<?php
ini_set('memory_limit', '512M');
ini_set('max_execution_time', 300);
set_time_limit(300); // alias for max_execution_time
Two caveats from running long jobs in production: