☰
Trongate PHP Framework Docs
Introduction
Quick Start
Basic Concepts
Understanding Routing
Intercepting Requests
Module Fundamentals
Database Operations
Templates
Helpers
Form Handling
Form Validation
Working With Files
Image Manipulation
Working With Dates & Times
Language Control
Security
Tips And Best Practices

Using Composer Packages

Trongate works perfectly without Composer. It also works perfectly with it. The previous page covers why and when - this one covers how. The recipe itself is three steps and one line of code; most of what follows is the detail that stops those three steps going wrong.

Composer, Packagist And PSR-4

Three names that get treated as one - and none of them is PHP itself:

  • Composer - a dependency manager for PHP. A command-line tool that fetches the packages you ask for, records them in composer.json, and generates an autoloader for their classes.
  • Packagist - the public repository that Composer installs from (packagist.org). It's a catalogue, not a technology.
  • PSR-4 - a PHP-FIG standard describing how a namespace maps onto a folder, so a class can be found from its name alone. Most modern packages are PSR-4; Composer's autoloader is what turns those mappings into working requires.

They are related, but they are not the same thing - and you can use Composer without ever thinking about PSR-4.

Composer Is Optional

Nothing in Trongate requires Composer, and the framework - which ships with no dependencies and no vendor/ folder - won't complain if you add one:

  • Trongate itself - no Composer required.
  • Trongate's core - no PSR-4 required.
  • Your application - Composer is there if you want it.
  • Your packages - free to use whatever their own architecture calls for.

So reach for Composer only when it earns its place - a payment SDK, a PDF library, a mature date library. Otherwise write it yourself. That's the Native PHP way!

Install and Load a Package

For a normal web request, three steps and you're done.

  1. Install the package. If Composer isn't on your machine yet, get it from getcomposer.org/download - it's a one-line installer, and composer --version confirms it's working.

    Now cd into the root of your application and run:

    composer require dompdf/dompdf

    Composer creates vendor/, plus composer.json and composer.lock if you don't already have them.

    Which root? The folder that contains public/, engine/ and modules/ - not public/ itself. The autoloader line in the next step starts with APPPATH, which points at that root, so that's where vendor/ needs to be.

  2. Add Composer's autoloader to public/index.php. This file already exists in every Trongate v2 installation - you're editing it, not creating it. Add one line, so that the whole file reads as follows:

    PHP
    <?php
    require_once '../engine/ignition.php';
    
    require_once APPPATH . 'vendor/autoload.php';   // <- add this line!
    
    //Init Core Library
    $init = new Core;

    Look before you edit. If public/index.php already contains the autoloader line, skip to step 3.

    Trongate does not load Composer's autoloader for you, so this line is what wakes it up. Miss it and the package's classes simply aren't available - typically a Class not found error.

  3. Use the package in your module. Add a use statement - such as use Dompdf\Dompdf; - and call the package's methods as though its classes lived in your own module. The next section has a working example.

Two Autoloaders, One Application

Composer's autoloader does not replace Trongate's. Both can run at once, and neither needs to know the other exists:

  • Trongate's own loader only ever looks inside engine/ and modules/.
  • Composer's loader only ever looks inside vendor/.

That matters, because there is a tendency to assume that supporting Composer means adopting Composer throughout the framework. It doesn't. You do not have to rebuild Trongate, restructure your modules or change a single framework file in order to use a package.

Use It In Your Module

Create a module and add a use statement at the top of it. The example below is a new controller file at modules/invoices/Invoices.php - you're creating both the folder and the file:

PHP
<?php
use Dompdf\Dompdf;

class Invoices extends Trongate {

    public function test(): void {
        $dompdf = new Dompdf();
        $dompdf->loadHtml('<h1>Hello from Trongate v2</h1>');
        $dompdf->render();
        header('Content-Type: application/pdf');
        echo $dompdf->output();
    }

}

Visit /invoices/test and you get a real PDF from a Composer-installed package. Everything else is whatever the package's own documentation says. The same use statement works in models and views alike.

One rule remains: the class declared in a Trongate module file must stay global (class Invoices extends Trongate). Trongate resolves it by file name, so it can't live inside a namespace. Imported classes can.

That is your whole PSR-4 obligation. Trongate's core doesn't use PSR-4, and your modules don't have to either - but that is not incompatibility. A package that ships PSR-4 mappings - or a classmap, or plain includes - still works, because Composer's autoloader resolves the package's classes, not yours.

Package Assets: CSS And JavaScript

Some packages ship stylesheets or scripts as well as PHP. Trongate serves files from /vendor/ for you, so a package's CSS can be linked straight from there:

HTML
<link rel="stylesheet" href="vendor/acme/widget/widget.css">

CSS comes back as text/css. Anything that isn't CSS is served as text/plain, which browsers may refuse to execute - so don't point a <script> tag at /vendor/. Copy the package's JavaScript into your module's own assets instead, where it's served with the correct MIME type:

HTML
<script src="invoices_module/js/widget.js"></script>

See Module Assets for how those _module URLs work. And note that everything under /vendor/ is web-readable, so treat it as public - package code, never secrets.

Two Other Places That Line Goes

At the top of a module file

If you're giving a module to somebody else, put require_once APPPATH . 'vendor/autoload.php'; at the top of its controller file, straight after <?php and before your use statements. The module then works on a pristine copy of Trongate - a fresh public/index.php never breaks it.

In a CLI or cron script

Scripts bootstrap themselves, and Trongate's requires are path-relative - so chdir() into public/ first:

PHP
<?php
chdir(__DIR__ . '/../public');

require_once '../engine/ignition.php';
require_once APPPATH . 'vendor/autoload.php';

Modules::run('invoices/test');

If your script complains about $_SERVER keys, give it the basics: REQUEST_METHOD, HTTP_HOST, REQUEST_URI.

Housekeeping

Add /vendor/ to your .gitignore, but commit composer.json and composer.lock. The lock file is what makes everyone else's install identical to yours - a fresh clone runs composer install and rebuilds vendor/ from it. Do the same on your server, and never edit anything inside vendor/: it's generated code, and the next install will overwrite you.

Installed packages also become part of your application's supply chain, so get comfortable with composer audit. It's now part of your maintenance routine, and that's the honest price of inviting in third-party code.

When Things Go Wrong

A handful of failures account for most confused afternoons:

  • Class "..." not found means Composer's autoloader was never loaded. The lookup fails before Trongate gets a chance to do anything, so check that line in public/index.php first. With error display off, it looks like a bare 500.
  • Access denied: assets must be in subdirectories means your module folder name contains _module, a string reserved by the framework. Call it Invoices, not Invoices_module.
  • Vendor file not found. means the /vendor/ URL doesn't match a real file. Installed packages rarely put assets at the top of their own folder - check the package's layout before linking to it.
  • composer require refuses to install usually means a platform problem rather than a Trongate one: the package wants a newer PHP than you're running, or an extension that isn't loaded.

The Trongate Position

Trongate isn't trying to dictate how PHP developers work, and it isn't trying to shield you from the wider PHP ecosystem either. The position is simpler than that: keep the framework lean, keep the architecture explicit, use third-party packages when they provide genuine value, and don't take on dependencies just because everybody else does.

That gives you choice. A completely dependency-free Trongate application is a perfectly good outcome. So is one that pulls in five Composer packages. Neither requires the core architecture to change.

Advanced: you can also ship an entire module as a Composer package, so that composer require drops it straight into modules/. It needs a small installer plugin and it's strictly optional - copying the folder is still the simpler way to share a module.

We're continually improving the Trongate documentation. If anything is incorrect, unclear, incomplete, or could be better, we'd genuinely appreciate your input.

Share your thoughts in the Documentation Feedback.

Leave Feedback About This Page