I want to do a read-modify-write to a file whilst I have an exclusive lock. Clearly I can use flock() and do the sequence fopen, flock, fread, fwrite, flock, fclose, but I my code would look neater if it I could use file_get_contents and file_put_contents. However, I need to lock both processes and I was wondering if was possible to do that using flock "somehow". The danger is, of course, that I'll write something that seems to work but doesnt actually lock anything :-)
Asked
Active
Viewed 497 times
1
-
1Have you tried it? Seems like a simple enough test. – Jonathan Aug 10 '18 at 16:18
-
The neatest code in the world is probably not very functional :) Neither my experience or a few Google searches tell me of anything else which can accomplish what `flock` does. – Scoots Aug 10 '18 at 16:19
-
3`file_put_contents` (and get) is just a wrapper around fopen/fwrite/fclose functions. Also, [file_put_contents](https://php.net/file_put_contents) does have a `LOCK_EX` flag that you can pass which will acquire an exclusive lock on the file before writing. – Jonathan Aug 10 '18 at 16:23
1 Answers
0
as @jonathan said you can use the flag LOCK_EX with file_put_contents but for file_get_contents you can build your own custom function and then use it in your code . the code below can be a starting point for you:
function fget_contents($path,$operation=LOCK_EX|LOCK_NB,&$wouldblock=0,$use_include_path = false ,$context=NULL ,$offset = 0 ,$maxlen=null){
if(!file_exists($path)||!is_readable($path)){
trigger_error("fget_contents($path): failed to open stream: No such file or directory in",E_USER_WARNING);
return false;
}
if($maxlen<0){
trigger_error("fget_contents(): length must be greater than or equal to zero",E_USER_WARNING);
return false;
}
$maxlen=is_null($maxlen)?filesize($path):$maxlen;
$context=!is_resource($context)?NULL:$context;
$use_include_path=($use_include_path!==false&&$use_include_path!==FILE_USE_INCLUDE_PATH)?false:$use_include_path;
if(is_resource($context))
$resource=fopen($path,'r',(bool)$use_include_path,$context);
else
$resource=fopen($path,'r',(bool)$use_include_path);
$operation=($operation!==LOCK_EX|LOCK_NB&&$operation!==LOCK_SH|LOCK_NB&&$operation!==LOCK_EX&&$operation!==LOCK_SH)?LOCK_EX|LOCK_NB:$operation;
if(!flock($resource,$operation,$wouldblock)){
trigger_error("fget_contents(): the file can't be locked",E_USER_WARNING);
return false;
}
if(-1===fseek($resource,$offset)){
trigger_error("fget_contents(): can't move to offset $offset.The stream doesn't support fseek ",E_USER_WARNING);
return false;
}
$contents=fread($resource,$maxlen);
flock($resource, LOCK_UN);
fclose($resource);
return $contents;
}
for a little explanation :
i just combine the parameters for flock
with those for file_get_contents
so you just need to read alittle about these two functions to understand the code.However if you don't need advanced usage of this function you can just do
$variable=fget_contents($yourpathhere);
I think this line is the same as :
$variable=file_get_contents($yourpathhere);
Except that fget_contents will actually lock the file according to your flag...

Elementary
- 1,443
- 1
- 7
- 17
-
These (thorough &appreciated) answers apply to locking file_get... and file_put... separately, but that was not quite what I was asking. I want to lock both processes **together** whilst I read, modify & write. I can do this using flock(), fread() and fwrite() but I wondered if there was a shorter/neater way like e.g. putting an flock around an entire file_get.../file_put... operation. But file_put... doesnt seem to like that and, clearly, I cannot release the lock after get... as it would defeat the whole purpose. Thus I think I'll need to stick to my original long-winded code :-( – D.Gibson Aug 19 '18 at 14:43
-
Yep you should use fwrite because it isn't really clever to use file_get_contents and think as you said... Good luck – Elementary Aug 19 '18 at 14:48