0

Is there any way in PHP, to get the checksum of a function during runtime?

I would like to use this for a function that is handling the comparision of two variables, and I would store the variable ids and the functions checksum in the database, so to not repeat the expensive comparision process each time the script is run, only if the function that is comparing the two variables, or any of the variables changed.

Adam Baranyai
  • 3,635
  • 3
  • 29
  • 68
  • Instead of a _"checksum of the function"_ (whatever you mean by this), store the version of the function and pass it together with the two values to compare to the function. The function code should know its current version. It has to be increased every time the code of the function is modified in a way that changes its behaviour or outcome. This approach ensures that the "checksum of the function" does not change when you upgrade to a different version of PHP or when you refactor the code. – axiac Jun 06 '21 at 11:26
  • By checksuming the function, I mean getting the whole body (code, or whatever) of the function, and running an `md5` on it (or any other string hashing function) , which should change, whenever something in the body of the function changes. (ie. adding a new space to it or something). What you propose is error prone imo, because if the developer forgets to update the version of the function when he changes the function, my script would not recompare the two arrays. The checksuming method reduces (unfortunately, not completely eliminates) this issue – Adam Baranyai Jun 06 '21 at 11:30

2 Answers2

2

I don't know of a way to get the function body in php, but you could store the function in it's own file and checksum the file.

wetmarble
  • 185
  • 1
  • 6
  • Yes, as an alternative solution, this would work, but I would like to keep this (and other simmilar) functions in a separate class to remain more structured. Basically, I could have 2-300 such functions all over the place, and it would be an overkill, to create just for this purpose 2-300 files. – Adam Baranyai Jun 07 '21 at 06:30
  • You could parse the file as a text file, extract the functions as strings, then hash them. – wetmarble Jun 07 '21 at 17:00
1

This is possible using the reflection API, but might be quite slow itself:

  1. Create a ReflectionFunction object
  2. Call getFileName() and load the source code, e.g. with file_get_contents() or file() (which splits the file into an array of lines)
  3. Call getStartLine(), and getEndLine(), and extract those lines from the source file
  4. That will give you the source code for the function, which you can then hash to form your cache key

There is also a library called BetterReflection which loads source code from a file and parses it without executing it, and can return re-constructed source code (i.e. functionally identical, but not laid out as in the original). This might be useful to avoid formatting changes causing the hash to change, but will be even slower.

If you have a large number of functions to hash, you will probably want to make a build script which loads a whole class or file, and loops over it generating a hash of each function. You can then store those hashes in a look-up table (saved on disk as a PHP or JSON array) which the caching code can use to look up by function name.

It's worth considering some alternative approaches which are likely to be simpler and more efficient:

  • Key the cache on the version of the application. This will probably have more false positives (unnecessary repeated work) but no false negatives (caches kept too long).
  • Manually increment a version within the function. This is more work to maintain, but if done correctly eliminates both false negatives and false positives.
IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • The function in question does not, and may not as a rule, call other functions, so that is not the issue. Falsely invalidating the cache should not be a major concern for us (if periodically the operation is performed once again, without any real change to the function, I can live with that), more so falsely validating it. Could you please give a concrete example on what kind of methods should I use from the reflection API? – Adam Baranyai Jun 07 '21 at 06:29
  • I am wondering, does a serialized `ReflectionFunction`, change when something in the function body changes? Or there is no guarantee to this? – Adam Baranyai Jun 07 '21 at 06:32
  • I've rewritten the answer, but then realised that somebody's already pointed out a duplicate above. – IMSoP Jun 07 '21 at 07:56