A simple, modern PHP library for CUPS IPP (Internet Printing Protocol) communication with zero dependencies.
- 🖨️ Print documents to CUPS printers using IPP protocol
- 📋 Query printer status and capabilities
- 📄 Manage print jobs (cancel, hold, release)
- 🎯 Simple, fluent API for job configuration
- 🔐 Basic and digest authentication support
- 📦 Zero dependencies — only uses PHP's built-in cURL extension
- PHP 8.1 or higher
- cURL extension
- CUPS server
composer require nacholibre/coffee-cupsuse CoffeeCups\CupsClient;
use CoffeeCups\Job;
// Create a client (defaults to localhost:631)
$client = new CupsClient();
// Create and configure a print job
$job = new Job('My Document');
$job->setFile('/path/to/document.pdf')
->setCopies(2)
->setDuplex(true)
->setColor(true);
// Send to printer
$result = $client->print('HP_LaserJet', $job);
if ($result->isSuccessful()) {
echo "Job ID: " . $result->getJobId();
}use CoffeeCups\CupsClient;
use CoffeeCups\Job;
$client = new CupsClient();
$job = new Job('Receipt');
$job->setContent("Hello, World!\n\nThis is a test print.")
->setFormat('text/plain');
$result = $client->print('Receipt_Printer', $job);The Job class provides a fluent API for configuring print jobs:
// With name
$job = new Job('My Document');
// Without name (set later)
$job = new Job();
$job->setName('My Document');// From file (auto-detects format from extension)
$job->setFile('/path/to/document.pdf');
// From raw content
$job->setContent($pdfContent);$job->setFormat('application/pdf'); // PDF
$job->setFormat('application/postscript'); // PostScript
$job->setFormat('text/plain'); // Plain text
$job->setFormat('image/png'); // PNG image$job->setCopies(3);$job->setDuplex(true); // Two-sided, flip on long edge
$job->setDuplex(true, false); // Two-sided, flip on short edge
$job->setDuplex(false); // Single-sided$job->setOrientation('portrait');
$job->setOrientation('landscape');
$job->setOrientation('reverse-portrait');
$job->setOrientation('reverse-landscape');$job->setQuality('draft'); // Draft quality
$job->setQuality('normal'); // Normal quality
$job->setQuality('high'); // High quality// Common shortcuts
$job->setMediaSize('a4'); // A4 paper
$job->setMediaSize('letter'); // US Letter
$job->setMediaSize('legal'); // US Legal
$job->setMediaSize('a3'); // A3 paper
// Full IPP media size names also work
$job->setMediaSize('iso_a4_210x297mm');
$job->setMediaSize('na_letter_8.5x11in');$job->setMediaType('stationery');
$job->setMediaType('transparency');
$job->setMediaType('envelope');$job->setColor(true); // Color printing
$job->setColor(false); // Monochrome/grayscale$job->setPriority(75); // 1-100, higher is more urgent$job->setHold(true); // Hold the job for later release
$job->setHold(false); // Don't hold (default)use CoffeeCups\Ipp\IppAttribute;
$job->addAttribute(IppAttribute::keyword('finishings', 'staple'));
$job->addAttribute(IppAttribute::integer('number-up', 4));use CoffeeCups\CupsClient;
// Local CUPS server
$client = new CupsClient();
// Remote server
$client = new CupsClient(
host: 'print-server.local',
port: 631,
secure: false
);
// With authentication
$client = new CupsClient(
host: 'print-server.local',
username: 'admin',
password: 'secret'
);$result = $client->print('Printer_Name', $job);
if ($result->isSuccessful()) {
echo "Job ID: " . $result->getJobId();
echo "Job URI: " . $result->getJobUri();
} else {
echo "Error: " . $result->getMessage();
}// Get all printers
$printers = $client->getPrinters();
// Get specific printer
$printer = $client->getPrinter('HP_LaserJet');
echo $printer->name;
echo $printer->state; // 'idle', 'processing', 'stopped'
echo $printer->isAcceptingJobs;
// Check capabilities
if ($printer->supportsColor()) {
echo "Color printing supported";
}
if ($printer->supportsDuplex()) {
echo "Duplex printing supported";
}
// Get default printer
$default = $client->getDefaultPrinter();// Get jobs for a printer
$jobs = $client->getJobs('HP_LaserJet');
// Get only my jobs
$myJobs = $client->getJobs('HP_LaserJet', myJobs: true);
// Get completed jobs
$completed = $client->getJobs('HP_LaserJet', whichJobs: 'completed');
// Cancel a job
$client->cancelJob('HP_LaserJet', $jobId);
// Hold a job
$client->holdJob('HP_LaserJet', $jobId);
// Release a held job
$client->releaseJob('HP_LaserJet', $jobId);// Pause printer
$client->pausePrinter('HP_LaserJet');
// Resume printer
$client->resumePrinter('HP_LaserJet');use CoffeeCups\CupsClient;
use CoffeeCups\Job;
use CoffeeCups\Exceptions\ConnectionException;
use CoffeeCups\Exceptions\IppException;
try {
$client = new CupsClient();
$job = new Job('Test');
$job->setFile('/path/to/file.pdf');
$result = $client->print('Printer_Name', $job);
if (!$result->isSuccessful()) {
echo "Print failed: " . $result->getMessage();
}
} catch (ConnectionException $e) {
echo "Connection failed: {$e->getMessage()}";
} catch (IppException $e) {
echo "IPP error ({$e->getStatusCode()}): {$e->getMessage()}";
}CUPS uses URIs to identify printers:
ipp://localhost:631/printers/Printer_Name- IPP protocolipps://localhost:631/printers/Printer_Name- IPP over TLS
The library handles URI construction automatically when you provide a printer name.
Run unit tests (no external dependencies required):
composer install
./vendor/bin/phpunit --testsuite unitIntegration tests run against a real CUPS server via Docker:
# Start CUPS server and run integration tests
make test-integration
# Or run everything via Docker
make test-allYou can also start the CUPS server manually:
# Start CUPS server (available at localhost:6631)
make cups-up
# Run integration tests
CUPS_HOST=localhost CUPS_PORT=6631 ./vendor/bin/phpunit --testsuite integration --group integration
# Stop CUPS server
make cups-downThis project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request