I think you understand a lot. Although, I think you need an authoritative answer.
It is true that the documentation does not mention "rw+" . However, there is something better: the PHP source code !
Rabbit hole
It was difficult for me to navigate in the source code until I found an article with PHP source code for PHP developers ( part 1 , part 2 , part 3 , part 4 ). I know that links jump between two sites, this series is as follows. By the way, I did not find the announced part 5.
Note These articles are old, they talk about PHP 5.4.
Let's see what fopen actually does ... let's fall into a rabbit hole ...
First we look at the definition of a function (which I found on the recommendation of related part 2 above). I noticed that it uses php_stream_open_wrapper_ex , which I found elsewhere , it just uses _php_stream_open_wrapper_ex , which we find in stream.c .
What does _php_stream_open_wrapper_ex with mode ? It passes it stream_opener .
Searching for the definition of stream_opener led me to type php_stream_wrapper_ops in php_streams.h .
Finding a usage like php_stream_wrapper_ops led me to plain_wrapper.c .
In fact, there are many php_stream_wrapper_ops initializations that allow you to open different things. We look at php_fopen_wrapper.c as it has initialization php_stream_wrapper_ops where stream_opener is php_plain_files_stream_opener .
We get there ...
php_plain_files_stream_opener further in the same file . He delegates to php_stream_fopen_rel .
php_streams.h defines php_stream_fopen_rel with _php_stream_fopen . What is called back to plain_wrapper.c .
Finally, _php_stream_fopen calls php_stream_parse_fopen_modes . Which will take a line and display some flags, Yay!
Wonderland
Let's take a look at php_stream_parse_fopen_modes :
PHPAPI int php_stream_parse_fopen_modes(const char *mode, int *open_flags) { int flags; switch (mode[0]) { case 'r': flags = 0; break; case 'w': flags = O_TRUNC|O_CREAT; break; case 'a': flags = O_CREAT|O_APPEND; break; case 'x': flags = O_CREAT|O_EXCL; break; case 'c': flags = O_CREAT; break; default: return FAILURE; } if (strchr(mode, '+')) { flags |= O_RDWR; } else if (flags) { flags |= O_WRONLY; } else { flags |= O_RDONLY; } #if defined(O_CLOEXEC) if (strchr(mode, 'e')) { flags |= O_CLOEXEC; } #endif #if defined(O_NONBLOCK) if (strchr(mode, 'n')) { flags |= O_NONBLOCK; } #endif #if defined(_O_TEXT) && defined(O_BINARY) if (strchr(mode, 't')) { flags |= _O_TEXT; } else { flags |= O_BINARY; } #endif *open_flags = flags; return SUCCESS; }
For the abstract, this is what it does (ignoring the details):
It takes the first character mode and checks if it is r , w , a , x , c . If he recognizes any of them, he sets the corresponding flag. Otherwise, we have FAILURE .
It searches + somewhere in the string and sets the appropriate flags.
It searches for e , n and t (depending on the preprocessor directives) somewhere in the string and sets the appropriate flags.
Return SUCCESS .
Return to the real world
You asked:
What is the difference between fopen "r +" and "rw +" modes in PHP?
Nothing. PHP only cares that the line starts with "r" and has a "+" . "w" ignored.
Final note . Although it is tempting to play with her and write things like "read+" , be careful with this because this letter may someday have some meaning. It would not be compatible with the transition. In fact, in some context, "e" already makes sense. Instead, I suggest sticking to the documentation.
Thanks for the excuse to view the PHP source code.