Laravel Websockets, some gotchas!

There is a really nice websocket composer package for laravel but a couple of issues that you may hit along the way! So the package is by beyondcode and it is here. A really nice package, but here are some gotchas that I came across.

  1. 403 Forbidden error on the auth URL
  2. 401 Unauthorized error on the auth URL
  3. Using namespaces within the listen to Echo method

So, the first 2 are kinder within the manual but I didn’t read it and in turn came up with the issues!. So going to split the 3 issues into separate areas below

403 Forbidden error on the auth URL

When you aren’t using the websocket locally, then you may hit request error of 403 and this is because of the gate defined within the Beyondcode class WebSocketsServiceProvider and method called registerDashboardGate

protected function registerDashboardGate() { Gate::define(‘viewWebSocketsDashboard’, function ($user = null) { return app()->environment(‘local’); });

and this as you can tell, is checking if the current application is running within the “local” environment setting and hence why you didn’t notice it whilst testing locally, the problem is within the config/websockets.php file

‘middleware’ =>

[ ‘web’, Authorize::class, ],

where the Authorize::class is the beyondcode class calling the above method, so we just need to replace with our authorization middleware e.g. jwt.auth.

401 Unauthorized error on the auth URL

The next issue I noticed was an error similar to

$key cannot obtain from null

This is because of the AuthenticateDashboard method that has

$app = App::findById($request->header(‘x-app-id’));
$broadcaster = new PusherBroadcaster(new Pusher( $app->key,

This is because the x-app-id wasn’t being passed in within the auth request, so altering the laravel Echo javascript object creation to include the following key value pair (please note I change the websockets.php path configuration to “websockets”

window.Echo = new Echo({ …….

authorizer : (channel, options) => {
return {
authorize: (socketId, callback) => {
axios.post(‘/websockets/auth’, {
socket_id : socketId,
channel_name: channel.name,
},
{ headers: { ‘x-app-id’: ‘<your ID from within the websockets.php configuration file, normally this is apps>’ } })
.then((response) => {
// error report
callback(false, response.data)
})
.catch((error) => {
// error report
callback(true, error)
// throw new Error(error)
})
},
}
},

Using namespaces within the listen to Echo method

The last part was the namespace issue within the echo listen to the method, where I don’t want to define the namespace of the broadcast every time like (where the App.Events was the namespace within php)

window.Echo.private(`dashboard.${dashboardID}’) .listen(‘App.Events.DashboardUpdate’, (e) => { e.message.value.forEach(function (value) { vm.$set(vm.data, value.key, value.value) }) })

So, like the above fix, we just need to add an option to the new Echo object within the javascript

window.Echo = new Echo({ …….

namespace : ‘App.Events’,

Those were the things that caused me to think, so thought it may be a good idea to post about it encase anyone else has the same issue, if you need more information on each please say!

php 7 – generator – yield’s

php 7 has now implement generators where you are able to return (yield) results from a method and only the ones that you will need.

// define the output as type Generator -- e.g. yield results.. the compiler will still work without this Generator keyword
function yieldSomeNumbers() : Generator {  
    yield 10;
    yield 13;
}
 
foreach (yieldSomeNumbers() as $v) {
    var_dump($v);
}

Will output

10
13

The ‘Generator’ at the end of the method ” : Generator” is not actual needed as the compiler will append it as such on the fly since the method is yield results.

For example, lets say that you are doing a search of numbers from 1-100 and are searching for the value of 10, so before generators the code would have been something like

function generateNumbers() {
    return range(1,100);   // load up a array of values 1-100 e.g. 1,2,3,4,5...
}
 
foreach (generateNumbers() as $v){
    var_dump($v);
    if ($v == 10) {
        var_dump("FOUND");
        break;
    }
}

The ‘foreach (generateNumbers()’ will be using the full array where as

function generateSomeNumbers() : Generator {
    foreach (range(1,100) as $v) {
        yield $v;
    }
}
 
foreach (generateSomeNumbers() as $v){
    var_dump($v);
    if ($v == 10) {
        var_dump("FOUND");
        break;
    }
}

will only return each yield upon request.

php 7 – strict typing and return types

This is going to be the first of my PHP 7 posts where PHP 7 has grown up and has PHP 7 taken a massive leap forwards!!!

So the first thing is return types, before PHP 7 there was no return typing e.g.

function add($a,$b) {
    return $a + $b;
}
 
echo add("hi there","good");

was a “valid” PHP code!!

But now with not only parameter type hinting, you are also able to use return types with strict typing as well!. So to start with, this is defining the return type of int (just before the function body there is the :int)

function add(int $a,int $b): int {
    return (int)($a + $b);
}
 
echo add(2,3);

The answer of course will be 5, but you could still be silly and allow PHP to convert string characters (that was alphanumeric) to integers, for example calling the above function like

echo add("2","3");

Would still work and give the answer of 5!, which is kinder wrong!.

So there is the strict typing which enforces the correct parameter being used.

So if you change the above code to

declare(strict_types=1);
 
 
function add(int $a,int $b): int {
    return (int)($a + $b);
}
 
 
var_dump(add(2,3));
var_dump(add("2","3"));
exit;

The output would be

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to add() must be of the type integer, string given, called in /home/genux/Programming/php7/scalar.php on line 12 and def
ined in /home/genux/Programming/php7/scalar.php:5
Stack trace:
#0 /home/genux/Programming/php7/scalar.php(12): add('2', '3')
#1 {main}
  thrown in /home/genux/Programming/php7/scalar.php on line 5

Which means that you have pass in the integer values, as in strict typing and not just assume PHP will be “cool” and just sort it out for you.

Lambda

After allot of coding of late, thought that I would place online a great syntax called lambda which allows you to do assign functions to a variable that is callable!!. So the functions like pref_replace_callback that has a function as the parameter to be used if any matches are meet.

So for a example, I think that source code always works the best.

function newFun ($name) { 
	$call = function ($second) use ($name) {
		return $second . $name; 
	};
	return $call($name);
 
}
 
echo newFun("hi there");

and the output would be

hi therehi there

What it is doing is assigning to the $call variable is the actual function call! which is able to be able to pass in via the parameters a parameter but also to “use” local variables within the function. The $name is passed in to the newFun function and is then use[d] within the lambda function, how cool is that!.

PHP – function use

As with the previous post about the use method within php (here), you are also able to use the use method attached to a callable function as in

function ($parameter) USE ($somevalue)

So you are able to use any variables that are within scope within the new function, below is an example where I am using the array walk methods callback (which means call a function that is available). The function is using the values within the array ($arrays 4 and 5) and adding them to the $value variable that is passed within the use parameters (here I am using the & symbol which means to pass in reference and not just a copy of the value (you are able to alter the actual parameter passed), so in this instance the $value starts of with 1, then adds 4 and then 5 to it which in turn the result is 10.

$value = 1;
$callback = function ($one) use (&$value) {
	$value += $one;
};
$arrays = array(4,5);
array_walk($arrays, $callback);
print_r("value : " .$value);

And the output would be.

value : 10

WFC Soap class within an class communicating with PHP

Within the Windows Foundation Classes you are able to create SOAP end points. These end points you are able to communicate using classes funny enough (because of the WFC being classes). But to communicate with these is fine with PHP and also when you sometimes have a class within an class as a parameter passing to the SOAP end point. Well you are able to do it within PHP as well.

If you have a WFC service and add these to the service for the ServiceContract and create the DataContract’s and DataMembers

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string NewValue(NewName name);
}
 
[DataContract]
public class SecondName
{
    int svalue1;
    int svalue2;
 
    [DataMember]
    public int Svalue1
    {
        get { return svalue1; }
        set { svalue1 = value; }
    }
 
    [DataMember]
    public int Svalue2
    {
        get { return svalue2; }
        set { svalue2 = value; }
    }
}
 
[DataContract]
public class NewName
{
    SecondName secondValue = new SecondName();
 
    [DataMember]
    public SecondName SecondValue
    {
        get { return secondValue; }
        set { secondValue = value; }
    }
}

Created the SecondName class as the second named class with the svalue1/2 within in turn the NewName named class will reference the SecondName class.

And then within the class that implements the interface here is the function name to call within the soap end point called NewValue.

public string NewValue(NewName namesec)
{
    return string.Format("Value : {0}", namesec.SecondValue.Svalue1 + namesec.SecondValue.Svalue2);
}

Well to find out what you need to pass to the soap call I was using an WFC application to write out the debugging information with altering the web.config by

    <system.serviceModel>
      <diagnostics>
        <messageLogging
             logEntireMessage="true"
             logMalformedMessages="false"
             logMessagesAtServiceLevel="true"
             logMessagesAtTransportLevel="false"
             maxMessagesToLog="3000"
             maxSizeOfMessageToLog="2000"/>
      </diagnostics>
    </system.serviceModel>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add name="messages"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData="c:\temp\messages.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

which in turns creates a file and in that file there is xml definition what is being sent.

<s:Body>
 <NewValue xmlns="http://tempuri.org/">
 <name xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfService1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
 <d4p1:SecondValue><d4p1:Svalue1>200</d4p1:Svalue1><d4p1:Svalue2>100</d4p1:Svalue2></d4p1:SecondValue>
 </name>
 </NewValue></s:Body>
</xml>

and within PHP you are able to copy this. but note that the parameter to send is “name” which is not the same as the parameter above (namesec) you have to send to “name” which is what the soap end point is looking for.

class SecondName {
    public $Svalue1;
    public $Svalue2;
}
 
class NewName {
    public $SecondValue;
 
    public function NewName($s1, $s2)
    {
        $this->SecondValue = new SecondName();
        $this->SecondValue->Svalue1 = $s1;
        $this->SecondValue->Svalue2 = $s2;
    }
}
 
$objN = new NewName(200,100);
 
//Create a SOAP client
$client = new SoapClient("http://192.168.0.3/Service1.svc?wsdl");
$retVal = $client->NewValue(array ("name" => $objN));
 
print_r($retVal->NewValueResult);

and the output is

Value : 300

Have attached a file of the project for the WFC webserver and also the php code.

PHP – Use

From a follow on from my previous post about namespace, when you want to use another name, shorter than the actual namespace of the namespace you are able to use “use”. Probably best to show in code

include "codingfriends.php";
 
use codingfriends as cf;
 
echo cf\sayHello()."<br/>";

the codingfriends.php file is

<?php
namespace codingfriends;
 
function sayHello()
{
    echo "Say hello from codingfriends.";    
}
 
function sayHelloFromSub()
{
    echo sub\sayHello();
}
?>

so that the “use” will alter the namespace of codingfriends to cf instead so that you are able to call codingfriends as cf, so when

echo cf\sayHello()."<br/>";

is called it will call the codingfriends\sayHello() function.