https://github.com/a-drew/laravel-sockets
A Sockets Management Provider built for Laravel 5, based on the Laravel's Database Provider
https://github.com/a-drew/laravel-sockets
api-wrapper laravel php socket tcp-client tcp-socket udp-socket
Last synced: 2 months ago
JSON representation
A Sockets Management Provider built for Laravel 5, based on the Laravel's Database Provider
- Host: GitHub
- URL: https://github.com/a-drew/laravel-sockets
- Owner: a-drew
- Created: 2018-10-29T14:23:10.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-05-11T17:54:00.000Z (about 7 years ago)
- Last Synced: 2025-08-02T08:05:41.864Z (11 months ago)
- Topics: api-wrapper, laravel, php, socket, tcp-client, tcp-socket, udp-socket
- Language: PHP
- Size: 8.79 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# About laravel-sockets
This project is a good place to start for developing an application that is requires
to retrieve or send data via UDP/TCP Sockets .
## Requirements
- PHP >= 7.0
- Laravel >= 5.5
## Quick Install
```
$ composer require wor/sockets:"^1.0"
```
OR
add `wor/sockets:"^1.0"` to your `require` list in the `composer.json` file.
#### Service Provider & Facade (Optional on Laravel 5.5+)
Register provider and facade on your config/app.php file.
```
'providers' => [
...,
Wor\Sockets\SocketsServiceProvider::class,
]
'aliases' => [
...,
'Sockets' => Wor\Sockets\SocketsFacade::class,
]
```
#### Configuration (Optional)
```
$ php artisan vendor:publish --provider="Wor\Sockets\SocketsServiceProvider"
```
## Debugging Mode
To enable debugging mode, just set SOCKET_DEBUG=true and the package will echo the raw payload being sent and received across Sockets.
IMPORTANT: Please make sure that SOCKET_DEBUG is set to false when your app is on production.
## Usage
### Basic Usage
1. Add the default socket remote to your .env file
```
...
SOCKET_CONNECTION=default
SOCKET_HOST=
SOCKET_PORT=
SOCKET_PROTOCOL=tcp
SOCKET_DEBUG=true
...
```
2. In Laravel or during a tinker session
```
Sockets::write('Message');
$response = Sockets::read(); //returns the string response from the socket.
```
### Intended Usage
This package is intended to be extended. There are two basic concepts at play here : Sockets & Requests.
#### Sockets
Sockets are the basic communication layer. They should are meant to be extended to
include any frame wrapping or encoding that you may want to use or that the receiving
service expects.
They should extend the base Socket class and implement the SocketInterface.
In short you should implement the read & write methods to match your expected I/O.
```
protocol/$this->version/$this->length/";
}
/**
* Salto SHIP protocol based write method **overloads base write() method**
* Wraps the message in the expected xml format and creates
*
* @param string $message to send
*
* @return bool success
*/
public function write(string $message): bool
{
$data = ''.$message.'';
$this->length = \strlen($data); //setups the length displayed in the header
return parent::write($this->getHeader().$data);
}
/**
* Salto SHIP protocol based read method **overloads base write() method**
* Reads header and uses expected message length to quickly load the response
*
* @param int $timeout in seconds
*
* @return string|null received message
*/
public function read($timeout = 25): string
{
$this->protocol = stream_get_line($this->socket,4, '/');
$this->version = stream_get_line($this->socket,3, '/');
$this->length = (int) stream_get_line($this->socket,8, '/');
stream_set_timeout($this->socket, $timeout);
$read = stream_get_contents($this->socket, $this->length);
return $read;
}
}
```
#### Requests
Requests are meant to encapsulate an action that is performed. They should match the endpoints
provided by the service you're working with. Think of them as database transactions. Once you
setup the payload and make the request it performs a write and read on the provided socket and
returns a parsed result.
Requests extend the base Request class and implement the RequestInterface.
```
boot();
parent::__construct($socket);
if (\is_array($params)) {
$this->setParams($params);
} elseif (\is_string($params)) {
// Allow to ignore parameters array and pass the name of the request directly
$name = $params;
}
if($name !== null) { // Avoid overriding self defined default request name
$this->setName($name);
}
$this->beforePayload();
$this->prepPayload();
}
/**
* Generic boot method to be changed in subclasses
* ran before the rest of the constructor
*/
public function boot(): void
{
//
}
/**
* Generic boot method to be changed in subclasses
* ran before setting up the payload
*/
public function beforePayload(): void
{
//
}
/**
* @param string $name
*/
public function setName($name): void
{
$this->name = $name;
}
/**
* @param array $params
*/
public function setParams($params): void
{
$this->params = $params;
}
/**
* Return formatted response of request
*
* @return Collection|mixed
*/
public function getResponse()
{
//$this->checkException();
return new Collection($this->collection);
}
/**
* Parse name and params into xml payload
*/
private function prepPayload(): void
{
$header = ''.$this->name.'';
$params = '';
foreach ($this->params as $key => $value) {
if ($key !== null && $value !== null) {
// cast boolean values to int for output to ship xml
!\is_bool($value) ?: $value = (int) $value;
// Output associative array as an ship parameter entry
$params .= '<'.$key.'>'.$value.''.$key.'>';
}
}
$this->payload = $header.$params.'';
}
/**
* Run the request on socket and return the response
*
* @return bool|mixed false if failed else return formatted response
*
* @throws SaltoException
*/
public function make()
{
if($this->socket !== null && $this->socket->write($this->payload)) {
$this->response = $this->socket->read();
$xml = simplexml_load_string($this->response);
$this->json = json_encode($xml);
$this->collection = collect(json_decode($this->json, true));
$this->checkException();
return $this->getResponse();
}
return false;
}
/**
* Check the response for known ship protocol exceptions
*
* @return bool
*
* @throws SaltoException
*/
public function checkException(): bool
{
if($this->collection->has('Exception')) {
$exception = $this->collection['Exception'];
switch ( (int) $exception['Code']) {
case 4:
throw new OperationNotSupportedException($exception['Message']);
break;
case 12:
throw new XMLDocumentException($exception['Message']);
break;
case 401:
throw new EncoderConnectionException($exception['Message']);
break;
case 403:
throw new EncoderTimeoutException($exception['Message']);
break;
default:
throw new SaltoException($exception['Message'], $exception['Code']);
break;
}
}
return false;
}
}
```
Then you are free to instantiate new requests and run them against your socket service.
```
$socket = Socket::socket('default');
$params = []; //the parameters you want to send through
$request = new SaltoRequest($socket, $params, 'GetInfo');
$response = $request->get();
```
In fact you can take it one step further and create action requests based on your new genetic service request.
```
$socket = Socket::socket('default');
$params = []; //the parameters you want to send through
$request = new GetInfoRequest($socket, $params);
$response = $request->get();
```
```