Laravel Echo Doesn't connect to socket channel - php

I want when my socket connection in opened increase some value in my welcome.blade.php.
this is my EventClass:
// app/Events/TestEvent.php
class TestEvent implements ShouldBroadcast
{
...
public function broadcastOn()
{
return new Channel('test');
}
}
this is my route :
// routes/web.php
Route::get('/fire', function () {
event(new \App\Events\TestEvent());
return 'ok';
});
this is Echo configuration in bootstrap.js :
// resources/js/bootstrap.js
...
import Echo from "laravel-echo"
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001' // this is laravel-echo-server host
});
and this is my welcome.blade.php :
// resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
</head>
<body>
<script src="{{ asset('/js/app.js') }}"></script>
<script>
Echo.channel('test')
.listen('TestEvent', e => {
console.log(e)
})
</script>
</body>
</html>
but when I fire the TestEvent my welcome page console is empty.

Since you defined the broadcastOn function, you need to make sure you are actually listening to that channel name. Currently you are listening to the event class name, which is the default channel name when you don't provide the broadcastOn function.
So, change your JavaScript code to listen to .test, and make sure to include the dot in front of the name!
All is well explained here: https://laravel.com/docs/8.x/broadcasting#broadcast-name

Related

Testing Push Notifications in Laravel Dusk

So I have an app that can bring up push notifications in the browser. The problem is that I need to create a UI test using Laravel Dusk to test if the push notification actually appears in the user's browser.
In real applications, push notifications are triggered from the server side in real-time using Websocket. Because there is some code logic in the front end before popping the push notification, so I think using Mocking Event Fake is still not enough.
I have tried reading the official documentation on Laravel Dusk but unfortunately haven't found a solution.
With an example page like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>Show Notification</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/push.js/1.0.8/push.min.js" integrity="sha512-eiqtDDb4GUVCSqOSOTz/s/eiU4B31GrdSb17aPAA4Lv/Cjc8o+hnDvuNkgXhSI5yHuDvYkuojMaQmrB5JB31XQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
const button = document.querySelector('button')
button.addEventListener('click', () => {
Push.create('Hello world!', {
body: 'Foo',
icon: 'https://example.com/images/icon.png',
link: 'https://example.com/',
timeout: 4000,
onClick: function () {
window.focus();
this.close();
},
})
})
</script>
</body>
</html>
The solution I might expect is something like this:
<?php
declare(strict_types=1);
namespace Tests\Browser;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class ExampleTest extends DuskTestCase
{
/**
* #test
*/
public function itShouldBeAbleToShowPushNotifications(): void
{
$this->browse(function (Browser $browser): void {
$browser
->visit('/')
->allowPushNotification() // The actual method doesn't exist, it's just an example I was hoping for
->click('button')
->assertSeePushNotification( // The actual method also doesn't exist
title: 'Hello world',
body: 'Foo',
icon: 'https://example.com/images/icon.png',
link: 'https://example.com/'
);
});
}
}
Is this possible? Or maybe there is a better alternative?

BotMan widget not replying, Using PHP Version 7.4.19 + Win 10 + XXAMP

I am testing botman chat. Followed documentation at https://botman.io/2.0/installation
Script open the chat widget at right bottom corner, but when I enter hello, it does not reply. Have tried multiple forums but not getting any solution.
Below is the script I am using
Installed botman
composer require botman/botman
Web Deriver
composer require botman/driver-web
index.php
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>COINS ChatBot</title>
<!-- <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/assets/css/chat.min.css"> -->
</head>
<body>
<script>
// Feel free to change the settings on your need
var botmanWidget = {
frameEndpoint: '/chat.html',
chatServer: 'chat.php',
title: 'ChatBot',
introMessage: 'Hi and welcome to our chatbot how can i help you ?',
placeholderText: 'Ask Me Something',
mainColor: '#F28240',
bubbleBackground: '#F28240',
aboutText: '',
aboutLink: '',
bubbleAvatarUrl: 'https://www.applozic.com/assets/resources/images/Chat-Bot-Icon#512px.svg'
};
</script>
<script src='https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/js/widget.js'></script>
</body>
</html>
chat.html
<html>
<head>
<title>BotMan Widget</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/assets/css/chat.min.css">
</head>
<body>
<script id="botmanWidget" src='https://cdn.jsdelivr.net/npm/botman-web-widget#0/build/js/chat.js'></script>
</body>
</html>
chat.php
<?php
require_once 'vendor/autoload.php';
use BotMan\BotMan\BotMan;
use BotMan\BotMan\BotManFactory;
use BotMan\BotMan\Drivers\DriverManager;
$config = [
// Your driver-specific configuration
// "telegram" => [
// "token" => "TOKEN"
// ]
];
DriverManager::loadDriver(\BotMan\Drivers\Web\WebDriver::class);
$botman = BotManFactory::create($config);
// Give the bot something to listen for.
$botman->hears('hello', function (BotMan $bot) {
$bot->reply('Hello yourself.');
});
$botman->hears('Good Morning', function (BotMan $bot) {
$bot->reply('Hey John');
});
$botman->hears('what is the time in {city} located in {continent}' , function (BotMan $bot,$city,$continent) {
date_default_timezone_set("$continent/$city");
$reply = "The time in ".$city." ".$continent." is ".date("h:i:sa");
$bot->reply($reply);
});
$botman->fallback(function($bot) {
$bot->reply('Sorry, I did not understand these commands. Here is a list of commands I understand: ...');
});
// Start listening
$botman->listen();
?>
After checking I found may be issue with caching, I have installed APCU PHP Cache but still no luck.

Simple HTML element in react.js code does not work in Xampp localhost

I am trying a very basic code in react.js :
File index.php has :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Add React in One Minute</title>
</head>
<body>
<div id="root"></div>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with "production.min.js". -->
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<!-- Load our React component. -->
<script type="text/javascript" src="my.js"></script>
</body>
</html>
Javascript file my.js has :
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
'<h1>Hello, {formatName(user)}! </h1>'
);
ReactDOM.render(
element,
document.getElementById('root')
);
But as output I get raw JS code instead of JS being rendered:
<h1>Hello, {formatName(user)}! </h1>
How to make it run ?
EDIT:
You can find the running code in codepen here. The element variable is declared as :
const element = <h1>Hello, {formatName(user)}!</h1>;
But I used single quotation around the element as otherwise I see error in the browser console:
Uncaught SyntaxError: Unexpected token '<'
Edit2: Fixed the codepen link. New link is this.
const element = '<h1>Hello, ' + formatName(user) + '! </h1>';
You're passing a string to render. You need to pass JSX.
Try something like -
const element = <h1>{formatName(user)}</h1>
To make sure JSX is being understood, you need to include Babel preprocessor as well. Add the Babel CDN to your imports -
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js" integrity="sha512-kp7YHLxuJDJcOzStgd6vtpxr4ZU9kjn77e6dBsivSz+pUuAuMlE2UTdKB7jjsWT84qbS8kdCWHPETnP/ctrFsA==" crossorigin="anonymous"></script>
A note for Node users
In a Node environment, where you cannot call ReactDOM.render(), you will need to make sure that you import React, like so -
import React from 'react';
Looks like you are trying to directly render JSX, but this requires a transpiler.
react without jsx
Each JSX element is just syntactic sugar for calling
React.createElement(component, props, ...children). So, anything you
can do with JSX can also be done with just plain JavaScript.
Code could possibly look more like
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const Element = ({ user }) => React.createElement(
'h1',
null,
`Hello, ${formatName(user)}!`,
);
ReactDOM.render(
React.createElement(Element, { user }, null),
document.getElementById('root'),
);
Or a bit more simply
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Harper',
lastName: 'Perez'
};
ReactDOM.render(
React.createElement('h1', null, `Hello, ${formatName(user)}!`),
document.getElementById('root'),
);
// or
ReactDOM.render(
<h1>Hello, {formatName(user)}!</h1>,
document.getElementById('root'),
);

Keep swoole websocket runing even if terminal is closed

I am trying to create a chat application using Socket and using Swoole as backend. I successfully create a connection to server-client but the issue I am facing now is that whenever I close terminal WebSocket is unable to connect.
Server code:-
<?php
//Create the websocket server object
$websocket_server = new swoole_websocket_server("MY_IP", 3000);
// Register function of the opening connection event
$websocket_server->on('open', function($websocket_server, $request){
var_dump($request->fd, $request->get, $request->server);
$websocket_server->push($request->fd, "Hello welcome\n");
});
// Register function of the receiving message event
$websocket_server->on('message', function($websocket_server, $frame){
echo "Message : {$frame->data}\n";
$websocket_server->push($frame->fd, "Server : {$frame->data}");
});
// Register function of the close event
$websocket_server->on('close', function($websocket_server, $fd){
echo "client_{$fd} is closed\n";
});
// Start the server
$websocket_server->start();
Client side Code:-
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script type="text/javascript">
var wsServer = 'ws://IP:3000';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
</script>
</body>
</html>
Everything is working fine the only issue is when we close terminal web socket id down.
I get the answer on Git. Please add below code in line
$websocket_server = new swoole_websocket_server("MY_IP", 3000);
$websocket_server->set([
'daemonize' => true,
]);

Laravel 5.4 inconsistent duplicate inserts

I get inconsistent duplicate inserts when running the following Laravel code: (I know I'm breaking all best practices, but this example code isolates the problem.)
App/routes/web.php:
<?php
use Illuminate\Support\Facades\DB; // NOTE: I am using the query builder, not a model
use Carbon\Carbon;
Route::get('formtest', function() {
return view('testing.index');
});
use Illuminate\Http\Request;
Route::post('formtest', function(Request $request) {
DB::table('pers2_testing_inserts')
->insert([
'data' => $request["test"],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
});
App/resources/views/testing/index.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TESTING</title>
</head>
<body>
<form id="form" action="" method="post" novalidate autocomplete="off" onsubmit="disableAndSubmit(event)">
<input type="text" name="test" id="text_box">
<input type="submit" id="submit_button">
</form>
<script type="text/javascript">
var text_box = document.getElementById('text_box');
var submit_button = document.getElementById('submit_button');
var form = document.getElementById('form');
function disableAndSubmit(e) {
submit_button.disabled = true;
if(text_box.value !== '') {
form.submit();
} else {
e.preventDefault();
submit_button.disabled = null;
}
}
</script>
</body>
</html>
My project is built in Laravel 5.4, PHP 7.1.7. I develop on a Mac, using vagrant as a virtual machine. My production server is a Windows Server 2008 R2 Standard Computer with XAMPP v3.2.2. The inconsistent duplicate inserting ONLY happens on the production server. Here is a screenshot of a few tests on the server.
I have inserts all over in my program, and any one of them can duplicate, and it's inconsistent. It shouldn't be that way. Is there something I should change in my XAMPP configuration? PHP configuration? Is there a workaround that I can implement that would prevent this from happening on the server?
try this:
<script type="text/javascript">
var text_box = document.getElementById('text_box');
var submit_button = document.getElementById('submit_button');
var form = document.getElementById('form');
function disableAndSubmit(e) {
e.preventDefault();
submit_button.disabled = true;
if(text_box.value !== '') {
form.submit();
return true;
} else {
submit_button.disabled = false;
return false;
}
}
</script>

Categories