totallynotgroot
totallynotgroot

Reputation: 69

includes files not being found through require_once()

Hey guys before I begin my question, I'm gonna paste a photo of my folders structure so it will be easier to visualize.

enter image description here

Okay so, in the header.php highlighted above, I have this line of code:

<?php require_once("admin/admin_pages/includes/init.php"); ?>

And in that init.php file:

<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>

However, when I try to open the index.php file located in my root directory it gives this error:

enter image description here

The init.php that's being required_once is working. However it doesn't seem to find the files(which are in the same directory as the init.php) that are required in the init.php file itself. Why is this happening?

Note: All the paths work when I am playing around in my admin/admin_pages/index.php page.

enter image description here

EDIT: This is a screenshot of the contents in my includes folder.

<?php
//Just in case an includes file is not called in the init.php file.
function classAutoloader($class)
{
    $class = strtolower($class);
    $path = "includes/{$class}.php";

    if (file_exists($path)) {
        require_once($path);
    } else {
        die("The file named {$class}.php was not found.");
    }
}

spl_autoload_register('classAutoloader');

function redirect($location)
{
    header("Location: {$location}");
}
?>

EDIT: This is what is giving the error message FYI. I have setup an autoloader function. However, the file is not missing and should be loaded either way.

Upvotes: 1

Views: 3008

Answers (4)

Dana Katzman
Dana Katzman

Reputation: 9

Put the db_object.php file above the users.php file in the init.php file and it will be found. I'm working on the same course and thats the solution

Upvotes: 0

Progrock
Progrock

Reputation: 7485

This isn't an answer, but may help:

Consider the following.

If we have three files in the same directory:

a.php:

<?php
require_once 'b.php';
require_once 'c.php';

b.php:

<?php
class B extends C
{}

c.php:

<?php
class C
{}

If I run a.php I get this output:

 Fatal error: Class 'C' not found in /var/www/stackoverflow/req_test2/b.php on line 3

This shows that order matters with require calls.

If I swap out the contents of a.php for the following and run it:

<?php
spl_autoload_register();

$b = new B;
var_dump($b);

I get this output:

object(B)#1 (0) {
}

spl_autoload_register() without parameters here uses the default implementation of spl_autoload(): a reference to a class named Foo, will look to include a file foo.php from your include path.

The initialisation of B here references class C, and the autoloader above will take care of requiring the appropriate files as needed.

I'd recommend placing each class definition in a file of its own. With a one-one mapping of filename to class. You may also be interested in the PSR-4 style.

Declare your autoloader early. Utility functions can also be included upfront.

A fix for your code would be to add your includes folder to your include path, and to change your require line to $path = "{$class}.php";. I would personally remove the die line within your autoloader, as you may need to register more than one autoloader - these are stackable as are your include paths.

Upvotes: 0

totallynotgroot
totallynotgroot

Reputation: 69

Hey guys thank you all for your input. I have finally found the problem with my code. It is not because of the autoloader function.

I did not know that the order of the files being called in the init.php mattered. I have simply re-ordered the require_once() statements.

The db_object.php file is actually the file that contains the parent class for my objects (photos and users). The photo.php and users.php contain inherited classes from the db_object.php. Which would made sense on why we need to find the db_object.php first.

Before:

<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>

After:

<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("db_object.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
?>

Upvotes: 0

Niellles
Niellles

Reputation: 878

EDIT:

Since you've made some edits, in which you've presented us -- among other things -- with the existence of an autoloader, I've re-read your question. Two important things that jump out:

  1. This issue occurs in your index.php located in the root of your website.
  2. The error that's printed originates from classAutoloader().
  3. (You're not having any probblems with admin/admin_pages/index.php.)

It would seem that this is still a path issue similar to the one mentioned below. When the autoloader is called from ~/index.php it's checking whether your root contains includes/db_object.php and that's not the case.

You can fix this by specifying the path to your includes folder relative to the autoloader file, something like this:

$path = __DIR__ ."/path/to/includes/{$class}.php";

Although I don't see any problems with this solution, it doesn't look very elegant to me. Alternatively you could specify the path from your root.


Issues with your init.php file.

By requiring admin/admin_pages/includes/init.php you're running the code in init.php from the file that's requiring it. If that makes sense. You could write the following in header.php and it would behave the same as requiring init.php:

<?php
require_once("functions.php");
require_once("db_config.php");
require_once("database.php");
require_once("user.php");
require_once("session.php");
require_once("photo.php");
require_once("db_object.php");
?>

You may notice that that wouldn't make sense, since those paths aren't correct when called from header.php. You can fix this by using the __DIR__ constant:

The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(FILE). This directory name does not have a trailing slash unless it is the root directory. ~ The Manual


With the aforementioned information you could probably figure it out yourself, but to make my answer complete, change the code in init.php to:

<?php
require_once __DIR__ . "/functions.php";
require_once __DIR__ . "/db_config.php";
require_once __DIR__ . "/database.php";
require_once __DIR__ . "/user.php";
require_once __DIR__ . "/session.php";
require_once __DIR__ . "/photo.php";
require_once __DIR__ . "/db_object.php";
?>

Note that:

  1. require_once isn't a function but a statement, so you call it as such. The same goes for require, include and include_once.
  2. Per your question only the requiring of db_object.php fails... That seems kinda strange.

Pro-tip (as mentioned in the comments by AnyhonyB):

One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).

In PHP 5, this is no longer necessary. The spl_autoload_register() function registers any number of autoloaders, enabling for classes and interfaces to be automatically loaded if they are currently not defined. By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error. ~ The Manual

Upvotes: 1

Related Questions