johnbillion / extended-cpts

A library which provides extended functionality to WordPress custom post types and taxonomies.
GNU General Public License v2.0
974 stars 97 forks source link

Exclude from autoloading? #219

Closed JacobDB closed 10 months ago

JacobDB commented 10 months ago

I'm using this library via composer in both custom themes as well as custom a plugin. This is leading to "class already exists" errors, so I'd like to handle the inclusion myself, so that I can first check if the class already exists. I tried to add "exclusion" rules to my composer.json, but this doesn't seem to actually change anything.

"autoload": {
    "exclude-from-classmap": [
        "johnbillion/extended-cpts"
    ]
}

I'm a pretty basic Composer user, so apologies if this is something simple, I just can't find anything useful through Google and Copilot's been no help either.

johnbillion commented 10 months ago

It sounds like something is unconditionally loading Extended CPTs after the autoloader, because the Composer autoloader won't try to load a class if it already exists.

Are you manually including Extended CPTs somewhere? The extended-cpts.php file in the root of this library is meant as a fallback for sites not using Composer, so perhaps something is loading that file.

JacobDB commented 10 months ago

Strange, as far as I can tell, I'm not including that file directly, I'm simply including the generated vendor/autoload.php. Just to be clear, they use different autoload.php, both separately including extended-cpts.

Here's the composer.json for my plugin:

{
    "require": {
        "johnbillion/extended-cpts": "^4.3",
        "htmlburger/carbon-fields": "^3.3",
        "stepandalecky/kml-parser": "^0.2.2",
        "mexitek/phpcolors": "^1.0"
    },
    "config": {
        "allow-plugins": {
            "composer/installers": true
        }
    }
}

And here's how the autoload.php is included for the plugin:

$plugin_path = plugin_dir_path(__FILE__);

if (file_exists("{$plugin_path}vendor/autoload.php")) {
    require_once "{$plugin_path}vendor/autoload.php";
}

Here's the composer.json for my theme, with some info redacted:

{
    "name": "agency/client-name",
    "description": "A brand new WordPress theme built just for Client Name!",
    "type": "metapackage",
    "license": "UNLICENSED",
    "authors": [
        {
            "name": "Jacob Bearce",
            "email": "email@example.com"
        }
    ],
    "require": {
        "johnbillion/extended-cpts": "^5.0"
    }
}

And here's how the autoload.php is included for the theme:

$template_directory = get_template_directory();

if (file_exists("{$template_directory}/vendor/autoload.php")) {
    require_once "{$template_directory}/vendor/autoload.php";
}

Other than that, I'm not directly accessing anything within Composer. It doesn't seem like I'm doing anything unusual, but I could definitely just be doing something wrong.

ETA: Composer version 2.5.1 2022-12-22 15:33:54 (maybe updating that would help? nope, same thing on the latest version)

johnbillion commented 10 months ago

I must say I'm not sure how gracefully Composer handles multiple autoloaders. I would expect it to be fine because there are plenty of WordPress plugins that bundle a Composer autoloader (some of mine included) and they work fine when used within a Composer project that also loads an autoloader.

You might want to try the same with a Composer package other than Extended CPTs and see if the same problem arises.

JacobDB commented 10 months ago

Now that you mention it, I do think I've run in to this issue with Carbon Fields as well. I think I've found a solution though, here's my final composer.json files:

Plugin:

{
    "config": {
        "allow-plugins": {
            "composer/installers": true
        },
        "optimize-autoloader": true
    },
    "require": {
        "johnbillion/extended-cpts": "^5.0",
        "htmlburger/carbon-fields": "^3.3",
        "stepandalecky/kml-parser": "^0.2.2",
        "mexitek/phpcolors": "^1.0"
    },
    "provide": {
        "johnbillion/extended-cpts": "^5.0"
    }
}

Theme:

{
    "name": "agency/client-name",
    "description": "A brand new WordPress theme built just for Client Name!",
    "type": "metapackage",
    "license": "UNLICENSED",
    "authors": [
        {
            "name": "Jacob Bearce",
            "email": "email@example.com"
        }
    ],
    "config": {
        "optimize-autoloader": true
    },
    "require": {
        "johnbillion/extended-cpts": "^5.0"
    }
}

It was the "optimize-autoloader" bit, along with specifying that extended-cpts is provided by the plugin that did the trick. Not necessarily ideal, would be great if it was automatic, but I guess this is just how Composer works, so I'll live with it. Thanks for the input!

johnbillion commented 10 months ago

Thanks for the update. I'm tempted to say that's a Composer bug, but determining what is the underlying reproducible bug is probably a rabbit hole, so I'll close this off and we can carry on with our day jobs 😅