Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Gpio Laravel Package

ronanguilloux/php-gpio

PHP-GPIO provides an object-oriented interface to Raspberry Pi GPIO pins, letting PHP applications read inputs, set outputs, and configure pin modes. Useful for prototyping and controlling LEDs, relays, sensors, and other hardware from PHP.

Deep Wiki
Context7

Getting Started

Install and verify prerequisites

composer require ronanguilloux/php-gpio

Before writing code, confirm the host is actually a Pi with the legacy sysfs GPIO interface available:

ls /sys/class/gpio            # should list export, unexport, gpiochip*
groups                       # your user should be in the `gpio` group
sudo usermod -aG gpio $USER  # then log out/in

If /sys/class/gpio is missing (some newer kernels/distros, Pi 5), the library has nothing to talk to — stop and evaluate libgpiod instead.

Where to look first

  1. vendor/ronanguilloux/php-gpio/src/ — this is the authoritative source for the exact class names and method signatures. The library is from 2013, so README examples may lag the code. Look for the Gpio/Pin-style classes.
  2. tests/ in the repo (or on GitHub) — the tests are the most reliable usage reference.
  3. /sys/class/gpio/gpio<N>/ on a live device — every method in the library is a thin file write; watching these files is the fastest way to debug behavior.

First real use case: blink an LED / pulse a relay

<?php
require __DIR__ . '/vendor/autoload.php';

use PhpGpio\Gpio;   // confirm namespace in vendor/.../src

$gpio = new Gpio();
$pin  = $gpio->getPin(17);          // BCM numbering, not physical header pin
$pin->setDirection('out');

try {
    $pin->setValue(1);
    sleep(1);
    $pin->setValue(0);
} finally {
    $pin->unexport();                // leave the sysfs state clean
}

Run it from the CLI as the same user that will run it in production (gpio group). If it works as your shell user but not as www-data, the problem is permissions, not PHP.

Implementation Patterns

Wrap the library behind a small service

Do not sprinkle new Gpio() across controllers. Bind a single wrapper into the container and expose domain verbs:

class RelayBoard
{
    /** @var array<string,int> logical name => BCM pin */
    public function __construct(
        private Gpio $gpio,
        private array $pinMap
    ) {}

    public function switch(string $name, bool $on): void
    {
        $pin = $this->gpio->getPin($this->pinMap[$name]);
        $pin->setDirection('out');
        $pin->setValue($on ? 1 : 0);
    }
}

In Laravel this is a singleton in a service provider; in Symfony, a service definition with the pin map injected from config/services.yaml. This keeps the hardware detail out of the request path and makes the board mockable.

Actuate from CLI commands, not web requests

Pins hold state across requests, so a web call only needs to flip a value — but sysfs writes can fail silently or race. The robust pattern is:

  • HTTP endpoint validates the request and dispatches a queued job / artisan command.
  • The worker (running as a gpio-group user) performs setValue() and logs the result.
  • The UI reads current state from your own DB/cache, not by re-reading sysfs on every page load.
// Artisan command outline
public function handle(RelayBoard $board)
{
    $board->switch($this->argument('relay'), $this->argument('state') === 'on');
    $this->info('OK');
}

Polling for input pins

The library has no interrupt/edge support, so buttons and sensors are read by polling. Keep loops cheap and bounded:

$pin = $gpio->getPin(27);
$pin->setDirection('in');

while (true) {
    if ((string) $pin->getValue() === '0') {
        // handle press; debounce in software
    }
    usleep(50_000); // 20 Hz, don't spin the CPU
}

Prefer a long-running worker (systemd service, Supervisor) over a request-triggered loop, and always release the pin in a finally or registered shutdown function.

Testing

Extract an interface (PinWriter with write(int $pin, bool $value)) and mock it in unit tests. Reserve the real Gpio/Pin classes for a single integration test that is skipped when /sys/class/gpio is absent, so CI on non-Pi runners stays green.

Gotchas and Tips

  • Permissions are the #1 failure. www-data (or your php-fpm user) must be in gpio, and the pool must be restarted after the group change. Failing that, writes to /sys/class/gpio/.../value succeed only for root.
  • export is not idempotent. If the pin is already exported (by a previous crash or another process), export can error or be a no-op depending on kernel. Wrap export in a try/catch and treat “already exported” as success; check is_dir('/sys/class/gpio/gpio'.$pin).
  • Direction changes often require re-export. Switching a pin from in to out mid-run may not take effect until you unexport() and export again. Design your flow so direction is set once at startup.
  • Pin numbering is BCM, not the physical header position. A pin labeled “11” on the board is GPIO17. Document your mapping table in one place and never inline magic numbers.
  • sysfs GPIO is deprecated. It still exists on many Pi OS images but is being replaced by the libgpiod character device interface. Treat this library as legacy — fine for a hobby controller, risky for a long-lived product.
  • No PWM, no interrupts, no edge detection. Only on/off and polling. If you need soft-PWM (dimming LEDs, servo control), this package will not get you there.
  • Values are strings. getValue() mirrors the sysfs file contents ("0"/"1"), so use strict comparisons carefully; 0 == "0" is true but '0' === 0 is not.
  • PHP version drift. Last release is 2013. Expect friction on PHP 8.x — check for deprecated constructs, and be prepared to require dev-master or vendor a small compatibility patch. Pin the version and add the Pi integration test to CI so an upgrade doesn't silently break.
  • Concurrent writers race. A web request and a cron job both touching the same pin can produce flicker or stuck state. Serialize access per pin with a flock or funnel all writes through one worker.
  • Leave the hardware clean. Always unexport() on shutdown; an orphaned export survives your process and confuses the next run.
  • Debugging checklist: cat /sys/class/gpio/gpio17/direction, cat .../value, ls /sys/class/gpio, and dmesg | tail for kernel-level complaints. If the file changes but the LED doesn't, the problem is wiring, not code.
  • Extension point: subclass or decorate Pin to add logging, retry-on-write-failure, or metrics — that is the easiest seam the package offers without forking it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route