1

I am honest. I almost never get it how to use properly "require_once". Right now I am trying a simple thing:

PHP-Class EmergencyTicket.php:

<?php

require_once(dirname(__FILE__)."/../../classes/DB.php");
require_once __DIR__ . '/Ticket.php';

class EmergencyTicket extends Ticket {
 (... code ...)
}

PHP-Class Ticket.php

<?php
class Ticket
{
(... code ...)
}

The files are located on the server in: 1) Ticket 1: webservice/v1/Ticket/EmergencyTicket.php 1) Ticket 2: webservice/v1/Ticket/Ticket.php

In the Ticket2 file I get the following error message when loading:

Fatal error: Class 'Ticket' not found in /usr/www/users/kontug/api.medifaktor.de/webservice/v1/Ticket/EmergencyTicket.php on line 6

Line 6 is:

class EmergencyTicket extends Ticket {

I see the file Ticket.php in the folder and I just want to extend this class, but no file seems to be found. Is there anything else I can check for?

1
  • 1
    Are U sure u aren't using namespaces in your Ticket class? Commented Oct 20, 2014 at 19:31

4 Answers 4

2

Some things to keep in mind when requiring files:

  1. You must have the correct path.
  2. The file must have read permissions.
  3. Dependencies must be loaded first. If the class extends an abstract, has interfaces or traits, those must be loaded before the class declaration is reached. Likewise if dependencies also have dependencies, those must also be loaded before the dependencies themselves are loaded.

As per your listed information, #3 seems to be your problem. The parent class must be loaded before the child class declaration.

good practice to make this easier:

  • Declare constants that map to your application root, libraries, etc. before you need to require various files, so you will not need to use complicated navigation to find them.
  • Use an autoloader, preferably psr-0 or psr-4 compliant.

The quick way to check (reasonably robustly):

/**
 * Provided for documentor/apigen support.
 * This function will attempt to load a file, and return information about
 * failure if it cannot be found or is not readable. It will also by default
 * avoid double inclusion to prevent redeclaration errors, though this can be 
 * configured to be ignored if required. 
 * NOTE: This function will mitigate common inclusion mistakes like duplicated or missing directory separators and file extensions.
 * @param string $file The name of the file, may be the actual file or full path.
 * @param string $dir (optional) The directory to check for the file. This param is best used with search functions that know the file name but not explicitly the directory, which allows for more robust usage elsewhere with minimal variable modification. This function can be used perfectly fine without it though.
 * @param string $suffix (optional) The file suffix that will be checked for. This will be appended to your file, and defaults to .php. You must alter this parameter if you are searching for a different file type.
 * @param boolean $nodup (optional) If true, will not include a file that has already been loaded to prevent class redeclaration errors. If false, will require the file regardless.
 * @return boolean TRUE if file was included, FALSE if not included (NOTE: you may want to modify the return line in the catch block depending on your needs.)
 */
function _requireFile($file, $dir = NULL, $suffix = '.php', $nodup = TRUE) {
    //this is not necessary in this example, but is generally good practice, and will prevent accidentally duplicated or missing extensions.
    //This function assumes that it will be used frequently, and contains redundancies to mitigate common inclusion errors such as missing or duplicated extenstions, missing or duplicated directory separators, etc.
    $file = ( ( isset($dir) ) ? rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : NULL ) . rtrim($file, $suffix) . $suffix);
    try {
        if (!file_exists($file)) {
            //the file does not exist at the specified location, throw an exception with information about the request.
            throw new \Exception("File not found at: " . $file);
        } elseif (file_exists($file) && !is_readable) {
            //the file exists in the specified location, but cannot be read due to a file permission conflict. Throw an exception with information about the request and how to fix it.
            throw new \Exception("File exists but is not readable at: " . $file . " <hr>You can correct this by using 'chmod 755 " . $file . "' from the command line.");
        }
        //This allows you to perform a duplication check to avoid class redeclaration errors. If you intend to include the file multiple times, pass the $nodup param as FALSE or 0 to ignore this check.
        if (!$nodup == TRUE && in_array($file, get_included_files())) {
            return FALSE;
        } else {
            //The file exists, is readable, and passed the no-duplication check, require the file. Note that require_once was intentionally not used to provide the option to require files multiple times if needed. If you are only ever going to use this for files that should not be redeclared, you can change this to require_once but it will really not make any appreciable difference.
            require($file);
            return TRUE;
        }
    } catch (\Exception $e) {
        //You may want to use a logging function here rather than echoing to the screen. The echo statement is provided for quick debugging, but should not be used in production.
        echo 'Error fetching file at ' . $e->getLine() . ' of ' . $e->getFile() . ': ' . $e->getMessage();
        //you may want to rethrow the exception and catch it in the referencing method or function, kill the program, or otherwise mitigate errors here depending on your program structure. Non-essential files should not kill your program though.
        return FALSE;
    }
}

$file = "/path/to/file.php";
_requireFile($file);

//OR

$dir =  "/path/to/";
$file = "/path/to/file.php";
_requireFile($file, $dir);

//OR

$dir =  "/path/to/";
$file = "/path/to/file";
$suffix = ".php";
_requireFile($file, $dir, $suffix);

The better way:

-Use a PSR-4 or PSR-0 autoloader.

Sign up to request clarification or add additional context in comments.

1 Comment

Old question, but this was a thorough and well explained answer. Great job @mopsyd.
0

Since you already had typos in your examples earlier, I'm very suspicious that this is a good real example.

  1. The error message for instance misses a .php extension.
  2. Also, the error message you got would not happen if Ticket1.php could not be found, because that would fail as a fatal error first.

Your source is fine, the only reason you would get the error you say you got, is if there's another file named Ticket1.php which you are also including successfully, and it doesn't have that class definition.

If that's not the problem you are having then you need to make a second attempt writing this question with real, working code. Try to simplify your stuff a bit and give us something we can execute on our own systems.

For example, this works for me:

Ticket1.php

<?php

class Ticket1 { }

?>

Ticket2.php

<?php

require_once 'Ticket1.php';

class Ticket2 extends Ticket1 { }

Running either Ticket1.php or Ticket2.php gives me no errors.

One thing you should look out for, and it may be related is the directory you are including from.

If a third script includes Ticket2.php from a different directory, this will fail.. because the current directory for PHP is always the directory of the first script you started.

To make sure this is not the issue you are having, include the file like this:

require_once __DIR__ . '/Ticket1.php';

__DIR__ is a magic PHP constant that always contains the full path of the file's directory where you are using the constant.

1 Comment

"full parent directory path" --- I'd say "current file directory", not "parent"
0

Check it out:

require_once (__DIR__ . DIRECTORY_SEPARATOR . 'Ticket.php');

1 Comment

DIRECTORY_SEPARATOR is not the solution here. OP is using / which is correct both on linux and windows
0

I have the same problem and I tried to use include('path/to/file.php') instead of require_once. Well, it just works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.