PHP's include_once is just a static "instance" of that file? - php

Reading over the documentation about include_once it basically says that the file in question won't be re-included if it's included already.
Can I equate this in my head as a static instance of the script, or will this lead me to trouble down the road?
EDIT
Not looking for a tutorial on include_once, I understand it quite well. Would like to know if I can conceptually attach the properties and characteristics of a static member, to this idea.
EDIT 2
Would the downvoters care to explain? It's a conceptual question, with a clear answer.

I'm not sure how the actual function works, but the best way to think about it is:
"If this file has been included/required earlier in this stream, no need to include/require it again."
The point is to avoid including a file that "redefines" a class or function because it was already defined in that same file included earlier.
The important thing to keep in mind is the idea of the script (and any included scripts along the way) as having a start and a finish. Any calls to include_once checks if that file has already been included since the start of the whole script. If it has, it doesn't bother to include it again, it just goes off of the originally included file.
Once the script is finished (no work left to be done, stream is closed, interrupted, aborted, etc), then re-starting the process treats the first include/include_once of a file as the first include, since it's the first time it's been included since the new running of the script. In that case, your back to square one, with all values being set back to default or unset.

Related

What is the PHP manual talking about with clearstatcache()?

You should also note that PHP doesn't cache information about non-existent files. So, if you call file_exists() on a file that doesn't exist, it will return false until you create the file. If you create the file, it will return true even if you then delete the file. However unlink() clears the cache automatically.
Source: https://www.php.net/manual/en/function.clearstatcache.php
I've read this numerous times but simply cannot make any sense of it. What is the actual information it's trying to convey?
To me, it sounds as if it's contradicting itself. First it says that PHP doesn't cache information about non-existent files. Then it goes on to state that it will return true even if you delete the file. But also that unlink() clears the cache automatically.
Is it referring to the file being deleted outside of PHP? Isn't that the only thing it can mean? But the way it's put is so incredibly confusing, ambiguous and weird. Why even mention that file_exists() will return false until you create the file? It's like saying that water will remain wet even if you clap your hands.
Is it actually saying, in a very round-about way, that I have to always run clearstatcache() before file_exists() unless I want a potentially lying response because a non-PHP script/program has deleted the file in question after the script was launched?
I swear I've spent half my life just re-reading cryptic paragraphs like this because they just don't seem to be written by a human being. I've many, many times had to ask questions like this about small parts of various manuals, and even then, who knows if your interpretations are correct?
I'd like to first address your last paragraph:
I swear I've spent half my life just re-reading cryptic paragraphs like this because they just don't seem to be written by a human being.
Quite the opposite: like all human beings, the people who contribute to the PHP manual are not perfect, and make mistakes. It's worth stressing that in this case these people are not professional writers being paid to write the text, they are volunteers who have spent their free time working on it, and yet the result is better than many manuals I've seen for paid software. If there are parts you think could be improved, I encourage you to join that effort.
Now, onto the actual question. Before going onto the part you quote, let's look at the first sentence on that page:
When you use stat(), lstat(), or any of the other functions listed in the affected functions list (below), PHP caches the information those functions return in order to provide faster performance.
What this is saying is that when PHP asks the system about the status of a file (permissions, modification times, etc), it stores the answer in a cache. Next time you ask about the same file, it looks in that cache rather than asking the system again.
Now, onto the part you quoted:
You should also note that PHP doesn't cache information about non-existent files.
Straight-forward enough: if PHP asks the system about the status of a file, and the answer is "it doesn't exist", PHP does not store that answer in its cache.
So, if you call file_exists() on a file that doesn't exist, it will return false until you create the file.
The first time you call file_exists() for a file, PHP will ask the system; if the system says it doesn't exist, and you call file_exists() again, PHP will ask the system again. As soon as the file starts existing, a call to file_exists() will return true.
Put another way, file_exists() is guaranteed not to return false if the file exists at the time you call it.
If you create the file, it will return true even if you then delete the file.
This is the point of the paragraph: as soon as the system says "yes, the file exists", PHP will store the information about it in its cache. If you then call file_exists() again, PHP will not ask the system; it will assume that it still exists, and return true.
In other words, file_exists() is not guaranteed to return true if the file doesn't exist, because it might have previously existed, and had information filed in the cache.
However unlink() clears the cache automatically.
As you guessed, all of the above is about you monitoring if something else has created or deleted the file. This is just confirming that if you delete it from within PHP itself, PHP knows that any information it had cached about that file is now irrelevant, and discards it.
Perhaps a different way to word this would be to give a scenario: Imagine you have a piece of software that creates a temporary file while it's running; you want to monitor when it is created, and when it is deleted. If you write a loop which repeatedly calls file_exists(), it will start returning true as soon as the software creates the file, without any delay or false negatives; however, it will then carry on returning true, even after the software deletes the file. In order to see when it is deleted, you need to additionally call clearstatcache() on each iteration of the loop, so that PHP asks the system every time.

Replacement or equivalent to __destruct() and unset() for PHP 7+

I'm going through the journey of bringing our dating web app up to date past PHP 7+
I have been updating the depreciated code and squishing errors as they've popped up, thanks to the help of this site, and has a question in regards to our depreciated __destruct() functions.
I searched my error I was getting thrown, and found this link on github that solved my issue: https://github.com/sajari/simple-linkedin-php/issues/4
So supposedly the destruct functions break after PHP 7, and commenting them out DID fix my issue, but it left me worried.
Edit: Destruct still works, its just how my dated code was trying to
use it
I have one specific instances of the destruct being called in one of our class files that builds a job request page based on what job a user queries from our database.
/** free up memory
$tmp->__destruct();
unset($tmp);
**/
From what I can tell, everything is working fine, but I wonder what the consequences of this are. Should I replace it with some newer memory cleanup method? This app is so dated, I wonder if this clean-up is even needed anymore, or intentionally put in to stop a memory leak. My boss doesn't seem to know either.
I'm new to PHP in a professional sense, and would like to make sure this update still allows the same level of speed and usability for our clients.
Another stackoverflow question asked here: Deletion of a PHP object; also unset() and __destruct
A user answered by saying that the values are already cleared by the complete execution of a script, BUT could be explicitly cleared to stop any unintentional references.
This just lead to more questions. When that user means script, do they mean the specific function call?
To wrap this up, lets say that destruct and unset call was to stop a memory leak, what is an equivalent replacement for it?
Thanks!
I want to personally mark this question answered for my own sake. It
was extremely helpful!
$tmp->__destruct();
unset($tmp);
You should never be calling destructors directly like this. Calling unset($tmp) by itself will indirectly cause the destructor to fire when the object is removed. So, this code actually causes the destructor to be called twice, which is almost certainly not what you want.
When that user means script, do they mean the specific function call?
No, they mean that one particular PHP execution, from the first line of the first file to the last line of the last file. At the end of execution, everything is automatically freed. In PHP, this execution run usually refers to one single short web request, so explicit calls to unset() for the sake of "freeing memory" are virtually never needed because an implicit unset() is going to happen as soon as the request is done. You'd only ever have to worry about doing this manually if, for example, the $tmp object uses a massive amount of memory at the start of a request, doesn't need it for the rest of the request, and runs for a long time. If you're just calling unset() at the end of the request, it's useless.
It's most likely safe to remove both these lines. The first is redundant and the second is almost never needed.
Note, it's much more likely to use unset() to remove a variable from scope than to free memory, so take care to scan if there's some code later on that needs $tmp to not exist.

PHP include inside loop - is it hard on disk io?

Im working on a website that shows products.
The site is written in PHP.
to make it easier to maintain, I created a php code for the "product" item with thumbnail, price, etc.
I would like to know if it is hard on Disk IO to put an include file inside a foreach. Let say the array counts about 200 items.
foreach($wines AS $wine):
require 'components/wine.php';
endforeach;
Are we still ok or there will have some hosting issue?
Thanks!
Answer
Regarding your question though, its probably Ok with the disk. Files imported using require() are also cached in precompiled bytecode the same way as the main file (if you have OPCache or any cache system enabled), so PHP wont read it from disk every time you include it.
Recomendation
I would not recommend that approach at all. I think a more recomendable approach would be to define a function that returns or displays whatever you want to show, then require the file once and call the function between the loop.
I see many downsides in your approach, like:
Its a bad practice, it couples your code because now this file can only be included in this file. It becomes required that the contents of the file are aware of the file that its including it, making it harder to maintain and more prone to errors in the future.
It can arise problems in the future, eg. if someone declares a function inside the file, it would cause a crash as requiring the file twice would redeclare the function leading to an error
It will cause some overhead in the execution, as PHP perform some validations and operations when a file is included
If you want more information about require or OPCache I link documentation below
https://www.php.net/manual/en/function.include.php
https://www.php.net/manual/en/intro.opcache.php

Is this file operation really "atomic" and "safe"? If not, how can I make it so?

I have a function which is supposed to return a unique filename based on the input file path. For example, if the user sends in C:\meow\bark.txt, and C:\meow\bark.txt already exists, it returns C:\meow\bark_1.txt, or _2 if the _1 one already exists, and so on.
The crucial part of this function is currently like this:
if (!file_exists($candidate_file_path))
{
if (touch($candidate_file_path))
return $candidate_file_path;
}
That is, if the "candidate" file does not exist, and it can be created ("touched"), then it appears to be safe to return this as a unique file path.
However, I'm not so sure about this. My fear is that some other script, running at the same time, also tries to assign a file with the same name in the same dir at the same time. If script A is currently inside the first if, and is about to "touch" its candidate, and script B has just already done that, then script A will still have its touch() return true, because it just sets the file system metadata for the file, and that's what it returns as "true"/successful. Thus, in such a situation, however unlikely, I will end up with both scripts thinking that they have the same "unique" file path!
This is obviously a recipe for disaster, and eerily similar to my database "transactions" nightmares of the not-so-distant past.
While I'm vaguely aware of the concept of "exclusive file locks", I have to be honest: no matter how much I read about that and tried to use it in the past for other things, I could never figure out how. It would really help me if you could think of some way to make this operation "atomic", or perhaps simply to replace the touch call with some other function which I don't even know exists?
I should note that the PHP function is_writeable has caused me serious issues in the past, which made me stop using it, according to my own internal comments to myself. If this can be avoided, it would also be good.
This operation is not atomic and not safe.
But there is a way for you to create a file which is guaranteed not to exist by using fopen() with the 'x'(or 'x+' for added reading) mode as documented in the manual.

How do I unset spl_autoload_register() and from where does it run?

When using spl_autoload_register(), if I understand correctly, once you run it, PHP saves it for every file.
The question I have, and this is really three questions, is:
How do you remove a function from spl_autoload_register()?
Does spl_autoload_register() save the functions to be autoloaded and restore them upon restarting php?
Does the function in spl_autoload_register() always run from the same location?
Go to php.net/spl_autoload_register. On the left side, under spl_autoload_register, it says spl_autoload_unregister.
It saves the autoloders every time the script runs (which is every time someone visits the page).
If I understand this question then, yes. If you tell it where to find something then it will always look there (unless you do something iffy).

Categories