Cannot Redeclare Function in PHP: Why It Ran Twice

Fix PHP’s “Cannot redeclare function” fatal error by finding duplicate declarations, repeated includes, and WordPress plugin conflicts.

PHP cannot redeclare function error caused by the same helper function being loaded twice

PHP Fatal error: Cannot redeclare functionName() (previously declared in /path/to/file.php:line) means PHP tried to define the same function name twice in the same execution, which it does not allow. The message itself tells you where the first declaration lives; your job is finding the second one, which is usually not a second function you wrote by mistake but the exact same file getting loaded twice. Switch include or require to include_once or require_once, or wrap the declaration in function_exists(), and in the specific case of two WordPress plugins each declaring the same global function name, rename or namespace one of them.

What the error actually means, and what it does not

PHP has no concept of redefining a named function once it exists in the current execution; unlike a variable, a function name cannot be reassigned. The error fires the moment PHP’s parser or the include/require machinery encounters a second function functionName() block for a name already declared, and it is fatal, because PHP genuinely cannot decide which definition should win. The file and line number in the message point at where the function was declared the first time, not the duplicate. You have to find the second occurrence yourself, which is where the three causes below diverge.

Cause 1: the same file included through two different paths

require __DIR__ . '/helpers.php';
// ...later in the same request, from a different file...
require '/var/www/app/includes/helpers.php';

Both lines load the same physical file, but because the paths are written differently (a relative path in one place, an absolute path in another, or a symlinked directory reached two different ways), PHP has no way to know they are the same file without checking. This is the single most common cause and the fastest to fix:

require_once __DIR__ . '/helpers.php';

require_once and include_once track the resolved, real path of every file already loaded and silently skip a second load of one already included, per the PHP manual on require_once. Swapping every plain include/require for its _once counterpart across an included-functions file is the standard fix, and it is safe to apply broadly since a file that is genuinely only ever loaded once behaves identically either way.

Cause 2: the function declaration is inside code that runs more than once

foreach ($modules as $module) {
    require $module . '/init.php'; // init.php declares a function at the top level
}

If more than one module’s init.php happens to declare a function with the same name, or if the loop itself runs the same require twice for any reason, the second load fails the same way, even with require_once in place, because the two files are genuinely different files that happen to declare the same function name. This is not a file-loaded-twice problem; it is a naming collision between two legitimately different files. The fix here is not _once, it is renaming one of the two functions, or wrapping the declaration:

if (!function_exists('formatPrice')) {
    function formatPrice($amount) { /* ... */ }
}

function_exists() lets the first file to run win and the second one quietly skip its own declaration, which is a reasonable fallback for shared helper-function names across independently maintained files, though it hides the naming collision rather than truly resolving it. A longer-term fix is giving each module’s functions a distinct prefix or a proper PHP namespace so the collision cannot happen at all.

Cause 3: two WordPress plugins declaring the same global function name

WordPress plugins commonly declare loose, global functions rather than class methods, especially older ones, and PHP applies the exact same rule across every plugin loaded on the same request. If Plugin A and Plugin B both declare a global format_price(), whichever loads second fatals the entire site with this error, and the person debugging it may not immediately think to check unrelated third-party plugins, since neither plugin’s own code looks obviously broken in isolation.

// Plugin A's includes/helpers.php
function format_price($amount) { /* ... */ }

// Plugin B's includes/helpers.php, loaded later
function format_price($amount) { /* ... */ } // fatal: already declared by Plugin A

The fix belongs to whoever wrote the colliding plugin: wrap declarations in function_exists() as a defensive minimum, or better, prefix every function with something specific to the plugin (myplugin_format_price()) or move to a namespaced class entirely, which removes the possibility of a global-scope collision no matter how many other plugins are active. If the collision is in a plugin you do not control, deactivating one of the two plugins is the immediate, if unsatisfying, way to get the site back up while you report or patch the conflict.

Finding the duplicate fast

The error names the first declaration’s file and line. Search the whole codebase for the exact function name to find every place it is declared:

grep -rn "function functionName" --include="*.php" .

Every result beyond the one the error already told you about is a candidate for the actual duplicate. If the search turns up exactly one other file, and that file’s path differs from the first only by how it was reached (relative versus absolute, or through a symlink), you are looking at Cause 1. If it is a genuinely different file with unrelated content that happens to share the function name, you are looking at Cause 2 or Cause 3, depending on whether both files are yours. This kind of full-codebase search is the same instinct behind fixing headers already sent: both errors are usually solved faster by searching broadly for a pattern across every included file than by staring harder at the one file the error message happens to name.

FAQ

Does switching every include to include_once fix all three causes?
Only Cause 1. include_once and require_once deduplicate by resolved file path, not by function name, so two different files that happen to declare the same function name will still collide even with _once on both.

Is this the same error as a class redeclaration?
The underlying mechanism is the same, PHP will not let you declare the same name twice in one execution, and the fix pattern (class_exists() instead of function_exists(), or a proper autoloader with namespacing) mirrors this one closely. The message differs slightly (“Cannot redeclare class” rather than “Cannot redeclare function”), but the diagnosis process is identical.

Why did this only start happening after I added a new plugin?
The new plugin very likely declares a global function whose name collides with one already declared by an existing plugin or by the theme. Reading the stack trace or fatal error output to confirm exactly which two files are involved is the fastest way to identify the second plugin, since deactivating plugins one at a time to find it works but is slower than reading what PHP already told you.

Can this happen with an anonymous function or a closure?
No. Anonymous functions assigned to a variable can be reassigned freely, since the variable is what changes, not a global function name. This error is specific to named function and method declarations.

Is there a connection between this and a memory or performance problem?
Not directly, though both errors often trace back to the same underlying habit: code that assumes a file or a resource is only ever touched once, without actually verifying it. Allowed memory size exhausted is a similar case of an assumption about scope, how much data or how many iterations, turning out to be wrong in a way PHP eventually refuses to tolerate.

Written by

Shah Alom

Leave a Reply

Your email address will not be published. Required fields are marked *