• cTor (unregistered)

    if(!frist_exists()){ Frist!; }

  • MiserableOldGit (unregistered)

    I saw this before somewhere ... but in a different language, either it's a classic or it's been in a codebase I've been in front of .... hope I didn't write it in a drunk moment!

    Oh, and FRIST.

  • Cornify (unregistered) in reply to MiserableOldGit

    You forgot to "guard" your frist with a if frist exists check.

  • Guilhem (unregistered)

    Another option: cargo cult: someone saw this in WordPress plugins (where plugins don't know what functions other plugins might have defined) and reused it without knowing what it's for.

    By the way, removing the loop is not just cleaner, it is also faster. PHP internal functions are faster than PHP code.

  • mb (unregistered)

    My guess for why this exists: Somebody had no clue about include_once, and had to make sure including it multiple times didn't crash

  • Raj (unregistered) in reply to mb

    There is a significant performance impact with include_once that is not present in the submitted code.

  • Chronomium (unregistered)

    So when you call one of these functions, the behaviour you get is based on whichever one happens to be loaded first?

    That's...something.

  • isthisunique (unregistered)

    People should be using require_once rather than include_once and require rather than include. They should also be using require_once when that's what they actually need. I've almost never seen the need to use include with well structured code.

    When it comes to the performance of require_once, I've never had a problem with it. If someone has messed things up or in old versions of PHP then there might be a problem. In fact it's usually faster, as you're not including the same file multiple times which takes a very toll on recent versions of PHP even if the file is empty making require_once slower than require.

    Some people show tricks to make it faster but they're not real one to one replacements for require_once. They exclude things such as realpath. If you truly need to make it fast then there are ways to do that although not necessarily pretty. In most cases it's micro optimisation and YAGNI. I once made a system to do runtime and static analysis to work out all includes and quickly realised even if I could do that it's a waste of time and additional complexity where very little is really gained. If you need to go that far, write your application in C instead.

  • anonymous (unregistered)

    There's not really WTF here (other than maybe PHP language itself). In older PHP declaring function twice is a FATAL error which means it can't be catched. If these files are included in the system where author doesn't have full control over what gets loaded and when (say an internal application with extensible plugin system or corporate app were offshore team is bunch of idiots who can't be convinced to not copy-paste stuff around) this is the simplest way to make sure that poorly written plugin/file declaring global function doesn't crash entire app when some bizarre combination of plugins or modules is loaded. Someone decided that invoking wrong function (as long as the name match) is less evil than crashing everything on start (which btw is a real WTF)

    require_once wouldn't help if duplicate functions are declared in 2 different files so here we go, yet another PHP sadness article candidate.

  • ooOOooGa (unregistered) in reply to isthisunique

    require_once is for library files. So, 'require_once awesomeLib.php;' include is for html-generating template files that are optional. So, 'include bannerAds.php;' require is for html-generating template files that are required. So, 'require header.php;' I'm not sure of the point of include_once. Just php things, I guess.

  • ooOOooGa (unregistered) in reply to anonymous

    The WTF at this point is the horrible structure of the code. You should define a function once, and if you need to use it somewhere then link to it. That is standard for any language. In PHP there is the require_once operator to make that happen.

    If you have multiple functions with the same name, then they could be namespaced to keep them separate. Or have them be member functions of a class. PHP supports both options.

    The 'if (!function_exists(...))' shenanigans indicates to me that someone copy/pasted the same function inline all over the code base and then had to try and work around the 'function already defined' errors that kept causing the system to crash.

  • hkgjgjdjgdgj (unregistered)

    This is normal in frameworks, for example laravel, see their helpers.

  • PH-aPpalling (unregistered) in reply to Raj

    There is a significant performance impact with include_once that is not present in the submitted code.

    Actually this is false, there is a very minor performance impact when using include or require once as opposed to the bare form, since PHP does this sort of thing all the time there is an in-memory structure of files that have been included previously to check against that exists whether the file was include-ed or include_once-ed. I don't have access to the technicalities so I can't give precise information, but the cost of normalizing and checking a file path against this map will be greater than, but not significantly so, the cost of normalizing and checking a string representing a function name against the symbol table, if the file is large, you're avoiding doing this repeatedly, and if the file is large you also don't need to load and process the file's bytecode, instead getting away with a moderately complex guard check.

  • PH-aPpalling (unregistered) in reply to ooOOooGa

    require_once is for library files. So, 'require_once awesomeLib.php;' include is for html-generating template files that are optional. So, 'include bannerAds.php;' require is for html-generating template files that are required. So, 'require header.php;' I'm not sure of the point of include_once. Just php things, I guess.

    There are two dimensions to consider when pulling in another file, should if fatally error if the file isn't there, and, if the file has already been included should we do it again. Require determines whether the call should potentially fatally error, except in very limited circumstances when pulling in configuration or in the context of building a library for others to reuse, you almost always want require, if a source file is absent die, even if that source file was a template. The decision about whether to _once or not is a bit more interesting, generally we write files that expose functions that can produce data, but in the case that the file contents is the data itself, you probably want to omit _once, in php you can evaluate source files so a pattern like this $configArray = require('config/user.inc.php'); isn't so weird to do, and if it's a template file you might do something like ob_start( ); require('templates/leftpanel.inc.php'); $leftpanel = ob_get_contents( ); ob_end_clean( );

    You will almost always want to require_once.

  • Sole Purpose of VIsit (unregistered) in reply to Chronomium

    Rather sad that (a) Remy didn't notice the only real WTF here and (b) everybody else bar Chronomium is busy wittering on about stuff that doesn't matter in the least. Still, that's what talking about PHP does for you, I suppose.

    Look, it's interesting (and news to me) that PHP treats functions as first class language constructs. And therefore it is interesting that functions can be lazily computed, as here.

    But that alone does not qualify as a WTF. The only important question here is, how do you know that you have lazily automagicked up the function you want? Because you don't, do you? Even if you ignore the function signature (which apparently is not part of this godawful stupidity), you are still relying on little more than a naming convention. Which is incredibly stupid and dangerous.

    I don't know what the answer is here, but it isn't "best practices" and all the rest of the wittering in the article. Perhaps it's name spaces (I have no idea whether or not PHP does this). Perhaps it's a simple script run against the source repository that detects duplicate function names. Perhaps it's taking every single programmer involved in this mess out back and shooting them in the head before they can do even more damage.

    But, the lazy evaluation? That's pretty much besides the point in a scripting language.

  • Matthijs (unregistered) in reply to ooOOooGa

    Namespaces are a fairly new thing in PHP. As in, when I worked with PHP up until some six years ago, it was still common to see PHP versions in the wild that did not support them. If this is old code, it's likely that namespaces were not an option at time of writing.

    Of course, you would still need something that worked like a namespace back then. A fairly elegant solution I worked with treated folder names as namespaces by overloading the class-loader, using spl_autoload_register. Sure it was hacky, but you would never have to write an include/require, as long as your classes adhered to a simple naming convention. Evidently, some people chose a somewhat less elegant "solution"..

  • PHPDev (unregistered)

    This actually not uncommon, the reason to do this is that a file might be "unintentionally" included twice, this is not unsimilar to a C++ file guard (Pragma once stuff)

  • isthisunique (unregistered) in reply to anonymous

    If functions are 'duplicated', rather than suppressing the error and using a function which might actually have the same name and prototype but actually be a different function which does not give the same output for a given input, most experienced programmers, especially multi-discipline, make the language as strict and unforgiving as possible because it reveals errors sooner rather than later, errors that if swept under the rug continually not only undermines the programmer by reinforcing their naivety but that also tend to inflict more damage in terms of being harder to find, explain and leaving a trace on the data such as a process completing but laying down nonsense data all over the place with bits missing that can't be reconstructed. If you have a function declared twice like that you've done something wrong. In something like C even people use defines to accomplish a kind of require once (C is another nightmare in itself there, actually the process does remind me a bit of concatenating and requiring JS files).

  • isthisunique (unregistered)

    In PHP defining a function with the same name twice is a fatal error. However where the prototype is concerned, it's normally a warning then notices (missing argument then the parameters aren't defined so undefined variable errors in the function body). Some people turn warnings and notices into exceptions. I have been doing this for many years but it has become a bit of a standard now in many frameworks. Bad programmers will often turn notices and even warnings off which unfortunately is quite common. PHP wont complain about extra parameters except for internal functions. This might have changed in newer versions but I've not tested it.

    When you have two different functions with the same name, in many cases, unfortunately, based on practices such as the one in this WTF, you'll likely get arbitrary undefined behaviour based on the inclusion order. Some programmers actually try to fix this and have things included in a certain order for it a bit like overriding. When it comes down to that, I pity the fool. It also creates landmines where hidden to the programmer the order of includes is important where it normally shouldn't be.

    In traditional procedural we always manually namespaced functions with a prefix expressing the real or library for the functions. More recently however there's a preference on using static methods on objects for that. Even more recently, PHP namespacing has made things much easier.

Leave a comment on “Questioning Existence”

Log In or post as a guest

Replying to comment #481299:

« Return to Article