Composer Autoload Failing - require_once 'vendor/autoload.php'

Hi Local Community,

I’m encountering a persistent issue with Composer autoloading within my LocalWP environment (running on Linux) and could use some help diagnosing it.

Problem: I’ve developed a custom WordPress plugin (wp-secret-manager-connect ) that uses Composer to install the google/cloud-secret-manager PHP library. Despite confirming the installation and file structure, PHP consistently fails with a fatal error: Fatal error: Uncaught Error: Class "Google\Cloud\SecretManager\V1\SecretManagerServiceClient" not found in .../wp-secret-manager-connect.php

Environment:

  • LocalWP (latest version) on Linux (Debian based)
  • Tried multiple PHP versions provided by LocalWP (8.2.10, 8.2.23, 8.2.27, 8.3.17, 8.4.4) - the issue occurs on all of them.
  • WordPress 6.5.5

Troubleshooting Performed:

  1. Composer: Ran composer install and composer dump-autoload -o within the plugin directory. Also tried removing vendor/ and composer.lock and running a fresh composer install . Files are downloaded correctly into vendor/ .
  2. File Permissions: Verified file/directory permissions within the plugin folder (wp-secret-manager-connect/vendor/ ). Permissions are standard (drwxr-xr-x for dirs, -rw-r--r-- for files), and ownership matches the user running LocalWP.
  3. Plugin Conflict Test: Deactivated all other plugins. The error still occurs with only the custom plugin active.
  4. PHP Extensions: Verified via phpinfo() that mandatory extensions (json , openssl , mbstring , ctype ) are enabled.
  5. php.ini Settings: Checked the site’s active php.ini (via LocalWP interface). disable_functions is empty, include_path is standard, memory_limit is sufficient (256M).
  6. OPcache: Temporarily disabled OPcache (opcache.enable=0 in php.ini ) and restarted the site. The issue persisted.
  7. Minimal Test Script (Outside WP): Created a standalone PHP script in the web root that only includes the vendor/autoload.php file and tries to check for/instantiate the class. This script also fails with the same underlying problem (details below).

Key Diagnostic Finding:

Using diagnostic error_log statements in both the plugin and the standalone test script, the core issue seems to be how the autoloader is included:

  • The script finds vendor/autoload.php .
  • The line require_once 'vendor/autoload.php'; (or include ) executes, but instead of returning 1 or true , it returns the \Composer\Autoload\ClassLoader object itself (seen via var_export ).
  • Immediately after the require_once line, class_exists('Google\Cloud\SecretManager\V1\SecretManagerServiceClient') returns false .
  • This indicates the autoloader script isn’t successfully registering the classes with PHP when included in this environment, despite the file being read.

This unusual return value from require_once happens across all tested PHP 8.2+ versions in LocalWP and occurs both within WordPress and in a standalone PHP script.

(Side Note): I also encountered an unrelated library conflict error when trying to use nano from the terminal within the LocalWP site shell (libtinfo.so.6: version \ NCURSES6_TINFO_6.2.20211010’ not found`), which might hint at potential environment complexities within LocalWP.

Question:

Has anyone else encountered issues with Composer’s vendor/autoload.php not registering classes correctly (specifically require_once returning the ClassLoader object) within LocalWP’s PHP 8.2+ environments on Linux? Any insights into potential LocalWP configurations or environment quirks that might cause this behavior would be greatly appreciated!

Thanks!

I always get a little nervous diving into Composer’s autoloading configuration. I think I was able to mimic what you are describing:

  • composer.json in the site root with an autoload configuration (psr-4)
  • a src folder with a class file named Song.php
  • a top level php script that imports the autoloader and uses that class

Dumping the require return shows that I have an instantiated object:

Honestly, I’ve never tried dumping that require return value, so I don’t know if that’s typical, but mentioning it just in case it helps clarify things.

Towards the bottom of the above output, you can see the result of a method call to my class. Originally when I tried this, it wasn’t working until I included the namespace at the top of my Song.php file:

I’d recommend doublechecking namespaces for files as well as the logic for autoloading. Also, if my example too far off from what you’re doing, can you provide a little more detail or even an example zip with minimal recreation details?

1 Like

Thanks for the reply and for trying to replicate, @ben.turner!

I appreciate the point about namespaces – they are definitely crucial. In my case, the library I’m trying to use (google/cloud-secret-manager ) does use namespaces correctly (e.g., Google\Cloud\SecretManager\V1 ), and my plugin code includes the corresponding use statements after requiring the autoloader.

The specific issue seems to be that the autoloader itself isn’t registering properly. Even though require_once 'vendor/autoload.php' executes and returns the ClassLoader object (which might be normal, as you noted), the subsequent check class_exists('Google\Cloud\SecretManager\V1\SecretManagerServiceClient') fails immediately afterwards. This happens even in a minimal PHP script outside WordPress, just trying to include the autoloader and check for a class from the vendor directory.

It feels like the autoloader’s registration process is being interrupted or isn’t completing within the LocalWP PHP environment for some reason, preventing PHP from finding any classes defined in the vendor directory.

Has anyone else specifically seen require_once 'vendor/autoload.php' return the ClassLoader object and subsequently fail to find classes from the vendor directory in LocalWP on Linux with PHP 8.2+? Still trying to pinpoint if it’s a configuration quirk specific to LocalWP.

I found this in the docs, which I think might be where you are pulling things from:

Which has this example code:

require 'vendor/autoload.php';

use Google\Cloud\SecretManager\V1\Replication;
use Google\Cloud\SecretManager\V1\Replication\Automatic;
use Google\Cloud\SecretManager\V1\Secret;
use Google\Cloud\SecretManager\V1\SecretManagerServiceClient;

$client = new SecretManagerServiceClient();

$secret = $client->createSecret(
    SecretManagerServiceClient::projectName('[MY_PROJECT_ID]'),
    '[MY_SECRET_ID]',
    new Secret([
        'replication' => new Replication([
            'automatic' => new Automatic()
        ])
    ])
);

printf(
    'Created secret: %s' . PHP_EOL,
    $secret->getName()
);

When I pulled that into my original file of mozart.php, my lsp server complains about a missing class. When I run find . -name '*SecretManager*' to see where that file is on disk, it looks like it might be found in a slightly different location than the docs would lead you to think:

When I updated the use statement to include `…\Client\SecretManager…', things seem to be resolving correctly.

Can you take a closer look and let me know what you find?

Hi @ben.turner,

Thanks again for digging deeper and spotting the namespace issue! You were absolutely right – the class is under Google\Cloud\SecretManager\V1\Client\SecretManagerServiceClient .

I updated the use statement in my plugin code accordingly. This fixed the “Class not found” fatal error both when I deployed the plugin to our non-LocalWP development server and also locally within my LocalWP environment after further testing.

It seems the incorrect namespace was somehow preventing the autoloader from registering correctly or causing the class_exists() check to fail in a misleading way within the LocalWP environment, even though the require_once line itself didn’t throw an immediate error. Correcting the use statement resolved the entire issue locally as well.

The diagnostic logs now show OK - SecretManagerServiceClient class FOUND immediately after autoload. locally, and the plugin activates and runs without fatal errors.

1 Like

Awesome! I’m glad you got it working! :clinking_beer_mugs:

This topic was automatically closed 36 hours after the last reply. New replies are no longer allowed.