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 Fsockopen Laravel Package

yakeing/php_fsockopen

yakeing/php_fsockopen is a lightweight PHP wrapper around fsockopen for low-level socket and HTTP connections. It provides a simple way to open sockets, send requests, and read responses without cURL, making it useful for small integrations or environments where cURL isn't available.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require yakeing/php_fsockopen

There is nothing to register. This is a plain PHP socket wrapper — no service provider, no facade, no config file, no published assets. After composer require, the only thing Laravel does is autoload the class.

Where to look first

  1. vendor/yakeing/php_fsockopen/README.md — it is short and contains the only canonical usage example. Treat it as the API contract; the method names below are representative, so confirm against src/ before writing production code.
  2. vendor/yakeing/php_fsockopen/src/ — usually one or two classes. Read the whole thing (it is small) so you know exactly how connect, write/send, read, and close behave, especially return values.
  3. composer show yakeing/php_fsockopen — confirm the installed version and PHP constraint.

First use case

The realistic day-to-day use is talking to something that is not HTTP: an internal TCP service, a legacy SMTP/IMAP/LDAP handshake, a local Unix-socket daemon, or a line-oriented text protocol. It is a replacement for hand-rolling fsockopen(), not for Laravel's HTTP client.

A good first experiment is an Artisan command that does a one-shot request/response:

// app/Console/Commands/PingDaemon.php
$socket = new \Yakeing\Fsockopen\Fsockopen();

try {
    $socket->connect('tcp://127.0.0.1', 9000, 2); // connect timeout in seconds
    $socket->write("PING\r\n");
    $reply = $socket->read();
    $this->info(trim($reply));
} finally {
    $socket->close();
}

If that works, wrap it behind an interface (see below) and never instantiate the package class anywhere else.

Implementation Patterns

Wrap it in a small adapter and bind it to the container. The package has no Laravel integration, so you create one. Define an interface so the socket can be faked in tests, and resolve config from config/services.php rather than hard-coding hosts.

// config/services.php
'daemon' => [
    'dsn'     => env('DAEMON_DSN', 'tcp://127.0.0.1:9000'),
    'timeout' => (int) env('DAEMON_TIMEOUT', 2),
],
// app/Services/DaemonClient.php
class DaemonClient implements DaemonClientContract
{
    public function __construct(private array $config) {}

    public function request(string $payload): string
    {
        $socket = new \Yakeing\Fsockopen\Fsockopen();

        try {
            [$scheme, $rest] = explode('://', $this->config['dsn'], 2);
            [$host, $port]   = array_pad(explode(':', $rest, 2), 2, null);

            $socket->connect($this->config['dsn'], $port, $this->config['timeout']);
            $socket->write($payload);
            return $socket->read();
        } finally {
            $socket->close();
        }
    }
}

Pattern: one connection per operation. In a web request or a queued job, open, transact, close. Do not memoize the socket in a singleton — under Octane or a long-running queue worker the resource will be stale and you will get silent read timeouts.

Pattern: read in a loop until you have what you need. read() typically returns whatever is currently in the buffer. For anything larger than a line, loop with a terminator or length check and enforce a total deadline:

$buffer = '';
$deadline = microtime(true) + 5.0;

while (microtime(true) < $deadline) {
    $chunk = $socket->read();

    if ($chunk === false || $chunk === '') {
        break; // EOF or timeout — check stream metadata if the wrapper exposes it
    }

    $buffer .= $chunk;

    if (str_contains($buffer, "\r\n\r\n")) {
        break;
    }
}

Pattern: push fire-and-forget traffic to the queue. For logging/metrics-style sends (UDP or a Unix datagram socket to a local collector), dispatch a job with dispatch()->afterResponse() or use Bus::batch so a slow or dead daemon never blocks the HTTP response.

Pattern: UDP and Unix sockets use the same class, different DSN. udp://host:port for datagram metrics, unix:///var/run/service.sock (or udg:// for Unix datagrams) for local daemons. This is genuinely the reason to reach for the package over raw fsockopen calls scattered through the codebase — one call shape, protocol in the DSN.

Pattern: scheduled health check. A scheduled command that connects and closes is a cheap liveness probe. Record the result with Log::warning or a metric; do not let a flapping daemon page anyone.

Testing. Fake at the adapter level: bind DaemonClientContract to a stub in the container and assert on the payload. Do not try to unit-test the package class itself; integration-test the adapter against a real local socket only in CI where you control the process.

Gotchas and Tips

  • Archived since 2019. Treat it as vendored code you own. Before deploying, run php -l on every file under src/ on your target PHP version. Pre-PHP 8 code of this era often uses removed constructs (curly-brace string offsets $s{0}, dynamic properties without #[AllowDynamicProperties], etc.). If it errors on PHP 8.2/8.3, fork it or replace it.
  • Connect timeout ≠ read timeout. The timeout argument to connect() only covers establishing the connection. Once connected, a read() on a silent peer blocks. If the wrapper exposes the stream resource or a timeout setter, call stream_set_timeout(); otherwise run the call inside a job with a retryUntil/timeout so a hung worker is killed.
  • false vs '' vs partial data. read() returning '' can mean "nothing yet", "EOF", or "timed out". If the wrapper does not surface stream_get_meta_data(), you cannot distinguish them reliably — this is the single biggest reason to keep the adapter thin and add your own deadline loop.
  • Short writes. fwrite can write fewer bytes than requested. If write()/send() does not loop internally, verify the return value and re-send the remainder. For binary protocols this matters; for line protocols it usually does not.
  • Never trim() protocol data. Binary payloads and length-prefixed frames break under trim, mb_*, or json_encode without care. Use strlen, raw bytes, and an explicit framing rule.
  • IPv6 needs brackets. tcp://[::1]:9000, not tcp://::1:9000.
  • TLS is limited. ssl:// / tls:// wrappers work only if the wrapper passes stream context options through. Verify certificate verification settings before trusting it; there is no Laravel-level verify => false knob.
  • No reconnect, no backoff, no pool. Implement retry at the job/adapter layer with RateLimited or backoff(). Do not retry a partial write on a non-idempotent protocol.
  • Warnings, not exceptions. fsockopen emits PHP warnings and returns false. If the package suppresses them with @, your try/catch will not fire — check the return value explicitly and convert to an exception yourself.
  • License: MPL-2.0. File-level copyleft. Consuming it as a dependency is fine; if you patch files under vendor/, those modified files must be made available under MPL. Prefer a fork or your own wrapper over in-place vendor edits.
  • Debugging toolkit. nc -vz host port to test reachability outside PHP, tcpdump -i any -A port 9000 to see the actual bytes, and strace -f -e trace=network php artisan your:command when you suspect a blocking call. Log the DSN and the time-to-first-byte per request — that tells you far more than a stack trace.
  • Extension point is your wrapper. There is nothing to extend in the package. Put reconnect logic, metrics, logging, deadline handling, and mocks in your adapter class, and keep the package import in exactly one file so replacing it later is a one-line change.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons