<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ayowande Oluwatosin</title>
    <description>The latest articles on Forem by Ayowande Oluwatosin (@ayowandeapp).</description>
    <link>https://forem.com/ayowandeapp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1023540%2Fb785737c-0ccc-4ed9-9d32-c5aab946e3fd.jpeg</url>
      <title>Forem: Ayowande Oluwatosin</title>
      <link>https://forem.com/ayowandeapp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ayowandeapp"/>
    <language>en</language>
    <item>
      <title>🛠 Fixing `Undefined property: TwilioSmsMessage::$contentVariables` in Laravel (Twilio Notifications)</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Tue, 06 Jan 2026 22:14:47 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/fixing-undefined-property-twiliosmsmessagecontentvariables-in-laravel-twilio-notifications-13k4</link>
      <guid>https://forem.com/ayowandeapp/fixing-undefined-property-twiliosmsmessagecontentvariables-in-laravel-twilio-notifications-13k4</guid>
      <description>&lt;p&gt;While integrating &lt;strong&gt;Twilio SMS notifications&lt;/strong&gt; in a Laravel app using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"laravel-notification-channels/twilio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I ran into this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Undefined property: NotificationChannels\Twilio\TwilioSmsMessage::$contentVariables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though my notification code was perfectly valid and only used &lt;code&gt;-&amp;gt;content()&lt;/code&gt;, Laravel kept throwing this exception.&lt;/p&gt;

&lt;p&gt;This post explains &lt;strong&gt;why this happens&lt;/strong&gt;, &lt;strong&gt;how I fixed it&lt;/strong&gt;, and &lt;strong&gt;what to be careful about&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 The Problem
&lt;/h2&gt;

&lt;p&gt;The error occurs when &lt;strong&gt;some internal logic (or another package)&lt;/strong&gt; tries to access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$contentVariables&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on &lt;code&gt;TwilioSmsMessage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, in &lt;strong&gt;Twilio Notification Channel v4.1&lt;/strong&gt;, the base class &lt;code&gt;TwilioMessage&lt;/code&gt; &lt;strong&gt;does not define this property&lt;/strong&gt;, causing PHP to throw an undefined property exception.&lt;/p&gt;

&lt;p&gt;This is especially common if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You upgraded/downgraded packages&lt;/li&gt;
&lt;li&gt;You previously experimented with Twilio Content Templates&lt;/li&gt;
&lt;li&gt;A dependency expects &lt;code&gt;contentVariables&lt;/code&gt; to exist&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ The Workaround That Fixed It
&lt;/h2&gt;

&lt;p&gt;I fixed the issue by &lt;strong&gt;extending the base &lt;code&gt;TwilioMessage&lt;/code&gt; class&lt;/strong&gt; inside the package to explicitly define &lt;code&gt;contentVariables&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;File edited:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vendor/laravel-notification-channels/twilio/src/TwilioMessage.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✏️ Updated &lt;code&gt;TwilioMessage&lt;/code&gt; class
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;NotificationChannels\Twilio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TwilioMessage&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * The phone number the message should be sent from.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="nv"&gt;$from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="nv"&gt;$statusCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="nv"&gt;$statusCallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create a new message instance.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$contentVariables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create a message object.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Set the message content.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Set content variables (prevents undefined property errors).
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;contentVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Set the phone number the message should be sent from.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$from&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$from&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getFrom&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;statusCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$statusCallback&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;statusCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$statusCallback&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;statusCallbackMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$statusCallbackMethod&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;statusCallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$statusCallbackMethod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this change, the error disappeared completely.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Important Warning
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Editing vendor files is NOT recommended for production.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composer updates will overwrite the change&lt;/li&gt;
&lt;li&gt;Other environments won’t have the fix&lt;/li&gt;
&lt;li&gt;It hides the real compatibility issue&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Better Long-Term Alternatives
&lt;/h2&gt;

&lt;p&gt;If you hit this issue, consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ensuring all Twilio-related packages are on compatible versions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoiding &lt;code&gt;contentVariables&lt;/code&gt; when sending SMS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using Twilio REST API directly&lt;/strong&gt; if you need Content Templates (WhatsApp)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forking the package&lt;/strong&gt; and maintaining your fix properly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opening a GitHub issue / PR&lt;/strong&gt; on the package repo&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel Notifications&lt;/li&gt;
&lt;li&gt;Twilio SMS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;laravel-notification-channels/twilio&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and hit unexplained property errors, &lt;strong&gt;check the base message classes first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hope this saves someone hours of debugging 👋&lt;br&gt;
Happy coding 🚀&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>laravel</category>
      <category>twilio</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Real-Time Communication with WebSockets in Node.js: Testing with Postman</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Mon, 24 Feb 2025 23:28:52 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/real-time-communication-with-websockets-in-nodejs-testing-with-postman-3gdb</link>
      <guid>https://forem.com/ayowandeapp/real-time-communication-with-websockets-in-nodejs-testing-with-postman-3gdb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;WebSockets enable real-time, bidirectional communication between a client and a server. Unlike traditional HTTP requests, WebSockets maintain an open connection, allowing instant data exchange. In this article, we'll explore how to set up WebSockets in a Node.js application, integrate them with a blogging system, and test using Postman.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up WebSockets in Node.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To integrate WebSockets, we will use Socket.io, a popular WebSocket library for Node.js. Our implementation includes a centralized socket.js file for managing WebSocket connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure you have Socket.io installed:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install socket.io&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Initialization (socket.js)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We'll create a socket.js file to manage WebSocket connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let io;

module.exports = {
    init: httpServer =&amp;gt; {
        io = require('socket.io')(httpServer);
        return io;
    },
    getIo: () =&amp;gt; {
        if (!io) {
            throw new Error("Socket.io not initialized");
        }
        return io;
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module exports two functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;init: Initializes WebSocket on the HTTP server.&lt;/li&gt;
&lt;li&gt;getIo: Retrieves the active WebSocket instance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Integrating WebSockets in app.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modify your app.js to initialize WebSockets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const http = require('http');
const { init } = require('./socket');

const app = express();
const server = http.createServer(app);
const io = init(server);

io.on('connection', (socket) =&amp;gt; {
    console.log('Client connected');

    socket.on('message', (data) =&amp;gt; {
        console.log('Received message:', data);
        socket.emit('response', { message: `Message received: ${data}` });
    });

    socket.on('disconnect', () =&amp;gt; {
        console.log('Client disconnected');
    });
});

server.listen(4000, () =&amp;gt; {
    console.log('Server running on port 4000');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing WebSockets in a Blog Post System
&lt;/h2&gt;

&lt;p&gt;Let's create a blog post system where new posts trigger real-time notifications via WebSockets.&lt;/p&gt;

&lt;p&gt;Blog Post Controller (controllers/postController.js)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { getIo } = require('../socket');
const { User } = require('../models');

exports.createPost = async (req, res) =&amp;gt; {
    try {
        const user = await User.findByPk(req.userId);
        const { title, content } = req.body;
        const image = req.file;

        if (!image) {
            throw new Error('Image file is required!');
        }

        const imageUrl = image.path;
        const post = await user.createPost({ title, content, imageUrl });

        getIo().emit('posts', { action: 'createdPost', post });

        return res.status(201).json({ message: 'Post created successfully!', post });
    } catch (error) {
        return res.status(500).json({ message: error.message || 'Something went wrong.' });
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing WebSockets with Postman
&lt;/h2&gt;

&lt;p&gt;Postman now supports WebSocket testing. Follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Open a WebSocket Connection&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Postman.&lt;/li&gt;
&lt;li&gt;Click "New" → "WebSocket Request".&lt;/li&gt;
&lt;li&gt;Enter WebSocket URL: ws://localhost:4000.&lt;/li&gt;
&lt;li&gt;Click Connect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Send a Message&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Messages tab.&lt;/li&gt;
&lt;li&gt;Send a test JSON message:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "type": "chat",
   "message": "Hello WebSocket!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Click Send.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Listen for Incoming Messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the WebSocket server is set up correctly, you should receive a response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "message": "Message received: Hello WebSocket!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Testing Blog Post Notifications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a blog post via a REST API request (e.g., POST /api/posts).&lt;/p&gt;

&lt;p&gt;If successful, Postman (connected to WebSockets) should receive an event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "action": "createdPost",
   "post": { "title": "New Post", "content": "This is a new post" }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This confirms that real-time notifications work correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By integrating WebSockets into a Node.js blog system, we enable real-time updates when new posts are created. Testing WebSockets with Postman ensures everything works as expected. &lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Real-Time Notifications with Server-Sent Events (SSE) in Laravel and Vue.js</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Mon, 09 Dec 2024 13:36:47 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/real-time-notifications-with-server-sent-events-sse-in-laravel-and-vuejs-40pf</link>
      <guid>https://forem.com/ayowandeapp/real-time-notifications-with-server-sent-events-sse-in-laravel-and-vuejs-40pf</guid>
      <description>&lt;p&gt;Server-Sent Events (SSE) is a great solution for enabling real-time notifications or updates in your application. Unlike WebSockets, SSE allows for one-way communication from the server to the client, making it lightweight and easy to implement. In this tutorial, we'll walk through how to set up SSE in a Laravel backend and consume the events in a Vue.js frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;We’ll be creating a simple real-time notification system using SSE. The server (Laravel) will push notifications to the client (Vue.js) whenever there are new notifications for the authenticated user. Here's a breakdown of what we'll cover:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Backend (Laravel): Set up an SSE endpoint to stream notifications.&lt;/li&gt;
&lt;li&gt;Frontend (Vue.js): Set up an EventSource to listen for incoming notifications.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1: Backend (Laravel)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.1 Create an SSE Route in Laravel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your routes/api.php, create an endpoint for the SSE stream. This will allow your Vue.js frontend to establish an SSE connection and listen for notifications.&lt;br&gt;
use App\Http\Controllers\NotificationController;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::get('/notifications', [NotificationController::class, 'get']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1.2 Controller Method for Streaming Notifications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, in the NotificationController, implement the logic to fetch unread notifications from the database and stream them to the client via SSE.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;namespace App\Http\Controllers;

use App\Models\Notification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class NotificationController extends Controller
{
    public function get(Request $request)
    {
        $headers = [
            "Content-Type" =&amp;gt; "text/event-stream",
            "Cache-Control" =&amp;gt; "no-cache",
            "Connection" =&amp;gt; "keep-alive",
            "X-Accel-Buffering" =&amp;gt; "no",
        ];

        return response()-&amp;gt;stream(function () {
            while (true) {
                // Fetch the unread notifications for the authenticated user
                $notifications = Notification::where('clicked', 0)
                                             -&amp;gt;where('user_id', 2)  // For now, hardcoding the user ID, you can replace it with Auth::id() for dynamic user handling
                                             -&amp;gt;get();

                // If there are notifications, send them to the frontend
                if ($notifications-&amp;gt;isNotEmpty()) {
                    // Format notifications as JSON and send them via SSE
                    echo "data: " . json_encode($notifications) . "\n\n";
                }

                // Flush the output buffer
                ob_flush();
                flush();

                // Sleep for a few seconds before checking again
                sleep(5);
            }
        }, 200, $headers);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Streaming Response: The response()-&amp;gt;stream() method is used to send an infinite stream of events.&lt;br&gt;
Notifications: We are querying the Notification model for unread notifications (clicked = 0) for a specific user. The notifications are encoded as JSON and sent to the client.&lt;br&gt;
Headers: The headers are set for SSE (Content-Type: text/event-stream).&lt;br&gt;
Infinite Loop: The while (true) loop keeps the connection open and continuously sends new notifications every 5 seconds (adjustable by modifying sleep(5)).&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Frontend (Vue.js)
&lt;/h2&gt;

&lt;p&gt;Now, let's set up the Vue.js frontend to listen for these notifications using the EventSource API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1. Set Up Vue Component to Listen for SSE Events&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a Vue component that will listen for the incoming events from the SSE stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h3&amp;gt;Unread Notifications&amp;lt;/h3&amp;gt;
    &amp;lt;ul v-if="notifications.length"&amp;gt;
      &amp;lt;li v-for="notification in notifications" :key="notification.id"&amp;gt;
        {{ notification.message }}
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
    &amp;lt;p v-else&amp;gt;No new notifications&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      notifications: [], // Store notifications
    };
  },
  mounted() {
    // Initialize EventSource to listen to the /api/notifications endpoint
    const eventSource = new EventSource('/api/notifications');

    // Handle incoming events from SSE
    eventSource.onmessage = (event) =&amp;gt; {
      const data = JSON.parse(event.data); // Parse JSON data from the server
      this.notifications = data;  // Update notifications list
    };

    // Handle errors
    eventSource.onerror = (error) =&amp;gt; {
      console.error("EventSource failed:", error);
      eventSource.close(); // Close the connection if there's an error
    };
  },
  beforeDestroy() {
    // Close the SSE connection when the component is destroyed
    if (this.eventSource) {
      this.eventSource.close();
    }
  }
};
&amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;EventSource: We create an EventSource instance that listens to the /api/notifications endpoint. This establishes a persistent connection to the server.
onmessage: This event listener processes incoming messages. The data is parsed from JSON and added to the notifications array.
onerror: If an error occurs (e.g., if the SSE connection is lost), we log the error and close the connection.&lt;/li&gt;
&lt;li&gt;beforeDestroy: To prevent memory leaks, the SSE connection is closed when the component is destroyed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we’ve set up real-time notifications using Server-Sent Events (SSE) in a Laravel backend and a Vue.js frontend. SSE provides a simple and efficient way to push real-time updates to the client, making it an excellent choice for features like notifications. With minimal setup, you can enhance your application with live, real-time capabilities.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>laravel</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Search Algorithms</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Thu, 18 Jul 2024 09:24:15 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/search-algorithms-2613</link>
      <guid>https://forem.com/ayowandeapp/search-algorithms-2613</guid>
      <description>&lt;h2&gt;
  
  
  Understanding Binary Search in PHP
&lt;/h2&gt;

&lt;p&gt;Binary search is a more efficient algorithm for finding an element in a sorted array. It works by repeatedly dividing the search interval in half. Here's a detailed breakdown of your binarySearch function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function binarySearch(array $arr, float|int $x)
{
    $low = 0;
    $high = count($arr)-1;
    // $midIndex = (int) ($low + ($high - $low)/2);
    $i = 0;
    while($low &amp;lt;= $high){
        $i++;
        $midIndex = (int) ($low + (($high - $low)/2)); //the same as  intdiv($low + $high, 2);

        if($arr[$midIndex] == $x){
            return "The number {$x} was found in index {$midIndex} of the array. The number of iteration was {$i}";
        }elseif($x &amp;gt; $arr[$midIndex]){
            $low = $midIndex +1;
            echo $low."\n";
        }else{
            $high = $midIndex - 1;
        }
    }

return "The number {$x} was not found in the array";


}

echo binarySearch([1,2,3,4,5,6,7,8,9,10,44,45,46,47,48,49,50], 45)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The function binarySearch accepts two parameters:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;$arr: A sorted array of integers.&lt;/li&gt;
&lt;li&gt;$x: The number to be searched, which can be a float or an integer.&lt;/li&gt;
&lt;li&gt;$low is initialized to the first index of the array.&lt;/li&gt;
&lt;li&gt;$high is initialized to the last index of the array.&lt;/li&gt;
&lt;li&gt;$i is a counter to keep track of the number of iterations.&lt;/li&gt;
&lt;li&gt;The while loop runs as long as the search interval is valid ($low is less than or equal to $high).&lt;/li&gt;
&lt;li&gt;$midIndex is calculated as the middle index of the current interval.&lt;/li&gt;
&lt;li&gt;If the middle element is equal to $x, the function returns the index and the number of iterations.&lt;/li&gt;
&lt;li&gt;If $x is greater than the middle element, adjust $low to midIndex + 1 (narrow the search to the upper half).&lt;/li&gt;
&lt;li&gt;If $x is less than the middle element, adjust $high to midIndex - 1 (narrow the search to the lower half).&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Understanding Linear Search in PHP
&lt;/h2&gt;

&lt;p&gt;Linear search is one of the simplest searching algorithms used to find a particular element in an array. Let's break down the linearSearch function in PHP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function linearSearch(array $arr, float|int $x)
{
    for($i=0; $i &amp;lt; count($arr); $i++){
        if($x === $arr[$i]){
            return "The number {$x} was found in index {$i} of the array\n";
        }
    }

    return "The number {$x} was not found in the array\n";
}

echo linearSearch([1,5,6,3,4,11,3,2], 4);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The function linearSearch accepts two parameters:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;$arr: An array of integers.&lt;/li&gt;
&lt;li&gt;$x: The number to be searched, which can be a float or an integer.&lt;/li&gt;
&lt;li&gt;The for loop iterates over each element of the array. The count($arr) function returns the number of elements in the array.&lt;/li&gt;
&lt;li&gt;Inside the loop, the code checks if the current element ($arr[$i]) is equal to $x. If a match is found, it returns a message indicating the index at which the number was found.&lt;/li&gt;
&lt;li&gt;If the loop completes without finding the number, the function returns a message indicating that the number was not found in the array.&lt;/li&gt;
&lt;li&gt;Linear search is straightforward and easy to implement. It sequentially checks each element of the array until the desired element is found or the end of the array is reached. This approach is simple but can be inefficient for large arrays, as it has a time complexity of O(n).&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>php</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>CoderByte Question</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Thu, 11 Jul 2024 07:28:56 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/coderbyte-interview-question-4d4m</link>
      <guid>https://forem.com/ayowandeapp/coderbyte-interview-question-4d4m</guid>
      <description>&lt;p&gt;......the question was something like this.......&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question&lt;/strong&gt;: write a function that takes a string argument. The numerals used are I for 1, V for 5, X for 10, I for 50, C for 100, D for 500, M for 1000. Given IIIXXXVVVV is 200. Should return CC.&lt;/p&gt;

&lt;p&gt;Solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function rommanToIntAndBack($s){
    $numerals = [
        'M' =&amp;gt; 1000,'D' =&amp;gt; 500,'C' =&amp;gt; 100, 'L' =&amp;gt; 50, 'X' =&amp;gt; 10, 'V' =&amp;gt; 5,'I' =&amp;gt; 1, 
    ];

    $total = 0;

    for ($i = 0; $i &amp;lt; strlen($s); $i++) {
        $total += $numerals[$s[$i]];
    }

    $roman = '';
    foreach($numerals as $key =&amp;gt; $val){
        while ($total &amp;gt;= $val) {
            $total -= $val;
            $roman .= $key;
        }
    }
    return $roman;
}
rommanToIntAndBack('IIIXXXVVVV')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Associative Array (HashMap):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The $numerals array is an associative array that maps Roman numeral characters to their corresponding integer values.&lt;/li&gt;
&lt;li&gt;This array provides constant time complexity 𝑂(1) for lookups, which is efficient for converting characters to their integer values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Algorithm Analysis
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Part 1: Roman to Integer Conversion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Algorithm:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize $total to 0.&lt;/li&gt;
&lt;li&gt;Iterate through each character in the string $s:&lt;/li&gt;
&lt;li&gt;Look up the integer value of the character from the $numerals array.&lt;/li&gt;
&lt;li&gt;add the current value to $total.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt;&lt;br&gt;
The conversion from Roman to integer involves a single pass through the string, so the time complexity is O(n), where n is the length of the string.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt;&lt;br&gt;
The space complexity is O(1) as no additional space proportional to the input size is used (only a few variables are used).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2: Integer to Roman Conversion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Algorithm:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize an empty string $roman.&lt;/li&gt;
&lt;li&gt;Iterate through the $numerals array:&lt;/li&gt;
&lt;li&gt;For each numeral, while the integer value can be subtracted from $total, subtract it and append the numeral character to $roman.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity:&lt;/strong&gt;&lt;br&gt;
The conversion from integer to Roman numerals involves iterating through a fixed set of numeral values and repeatedly subtracting them from $total.&lt;br&gt;
In the worst case, the time complexity can be considered O(n), where &lt;br&gt;
n is the value of the integer. However, given the fixed number of Roman numeral symbols, it is more practical to consider it as O(1).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity:&lt;/strong&gt;&lt;br&gt;
The space complexity is O(1) for the numerical operations and O(n) for the output string, where n is the length of the resulting Roman numeral string.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>algorithms</category>
      <category>php</category>
    </item>
    <item>
      <title>Efficient PHP Script for Calculating Scores in a Baseball Game (code practice recuiter)</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Tue, 20 Feb 2024 17:04:43 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/efficient-php-script-for-calculating-scores-in-a-baseball-game-code-practice-recuiter-ch2</link>
      <guid>https://forem.com/ayowandeapp/efficient-php-script-for-calculating-scores-in-a-baseball-game-code-practice-recuiter-ch2</guid>
      <description>&lt;p&gt;Have you ever wondered how to efficiently calculate scores in a baseball game using PHP? Look no further! In this post, we'll delve into a well-optimized PHP script that effectively processes a sequence of baseball game operations and delivers accurate results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
$ops = ["5", "-2", "4", "C", "D", "9", "+", "+"];
$results = [];

foreach ($ops as $op) {

    if (is_numeric($op)) {
        // If the current operation is a number, add it to the results array
        $results[] = $op;
    } elseif ($op == "+") {
        // If the current operation is '+', calculate the sum of the last two scores and add the result to the array
        $score = end($results) + $results[count($results) - 2];
        $results[] = $score;
    } elseif ($op == "D") {
        // If the current operation is 'D', double the last score and add the result to the array
        $score = end($results) * 2;
        $results[] = $score;
    } elseif ($op == "C") {
        // If the current operation is 'C', remove the last score from the array
        array_pop($results);
    }
}

// Calculate the sum of all scores in the results array and echo the result
echo array_sum($results);
?&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operations Array: $ops = ["5", "-2", "4", "C", "D", "9", "+", "+"]; - Defines an array of operations (numbers, '+', 'D', 'C').&lt;/p&gt;

&lt;p&gt;Results Array: $results = []; - Initializes an empty array to store the scores.&lt;/p&gt;

&lt;p&gt;Main Loop: foreach ($ops as $op) { ... } - Iterates through each operation in the $ops array.&lt;/p&gt;

&lt;p&gt;Handling Numeric Values: if (is_numeric($op)) { ... } - If the current operation is a number, add it to the $results array.&lt;/p&gt;

&lt;p&gt;Handling '+' Operation: elseif ($op == "+") { ... } - If the current operation is '+', calculate the sum of the last two scores and add the result to the $results array.&lt;/p&gt;

&lt;p&gt;Handling 'D' Operation: elseif ($op == "D") { ... } - If the current operation is 'D', double the last score and add the result to the $results array.&lt;/p&gt;

&lt;p&gt;Handling 'C' Operation: elseif ($op == "C") { ... } - If the current operation is 'C', remove the last score from the $results array.&lt;/p&gt;

&lt;p&gt;Calculate and Echo Sum: echo array_sum($results); - Calculates the sum of all scores in the $results array and echoes the result.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>php</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Efficient PHP Function for Counting Valid Time Formats with '?' Placeholder (Turing code challenge)</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Tue, 20 Feb 2024 16:59:19 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/efficient-php-function-for-counting-valid-time-formats-with-placeholder-turing-code-challenge-di3</link>
      <guid>https://forem.com/ayowandeapp/efficient-php-function-for-counting-valid-time-formats-with-placeholder-turing-code-challenge-di3</guid>
      <description>&lt;p&gt;Are you in need of a versatile PHP function to count the number of valid time formats with a '?' placeholder? Look no further! In this post, we'll explore a well-optimized PHP function, countValidTimeFormats, that efficiently generates and validates time formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
function countValidTimeFormats($s) {
    $count = 0;
    $splited  = explode(':', $s);
    $range = stripos($splited[0], '?') !== false ? range(0, 24) : range(0,59);
    foreach($range as $num){

      $formattedTime = stripos($splited[0], '?') !== false ? 
              str_replace('?', $num, $splited[0]).':'.$splited[1] : 
              $splited[0] .':'.str_replace('?', $num, $splited[1]);
        // Validate the formatted time
        if (isValidTime($formattedTime)) {
            $count++;
        }
    }

    return $count;
}

function isValidTime($time) {
    $pattern = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/';
    return preg_match($pattern, $time);
}

// Example usage
echo countValidTimeFormats("?4:00"); // Output: 2
echo countValidTimeFormats("20:1?"); // Output: 10
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;countValidTimeFormats Function:&lt;br&gt;
Input Splitting: $splited = explode(':', $s); - Splits the input string into an array using the colon (':') as the delimiter. This separates the hours and minutes.&lt;br&gt;
Determine Range: $range = stripos($splited[0], '?') !== false ? range(0, 24) : range(0, 59); - Determines the range of values based on the presence of '?' in the hour component. If '?' exists, the range is set from 0 to 24 (hours); otherwise, it is set from 0 to 59 (minutes).&lt;br&gt;
Generate and Validate Formats: The foreach loop iterates through the specified range. It generates a formatted time string by replacing the '?' with the current value in either the hour or minute component based on the determined range. The formatted time is then validated using the isValidTime function.&lt;br&gt;
Count Valid Formats: If the generated time format is valid, $count++ increments the count.&lt;br&gt;
Return Count: The function returns the final count of valid time formats.&lt;br&gt;
isValidTime Function:&lt;br&gt;
Time Format Validation: $pattern = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])$/'; - Defines a regular expression pattern for validating the 24-hour time format (hh:mm).&lt;/p&gt;

&lt;p&gt;Validation Check: return preg_match($pattern, $time); - Uses preg_match to check if the provided time string matches the specified pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;The code efficiently generates and validates time formats based on the presence of '?' in the input string. It handles both hour and minute placeholders, ensuring adherence to the 24-hour time format. The provided example usage demonstrates how the function can be applied to count valid time formats for different input strings.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Simplify Large Numbers with Style: A Guide to Human-Readable Representations in JavaScript</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Fri, 02 Feb 2024 10:40:17 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/simplify-large-numbers-with-style-a-guide-to-human-readable-representations-in-javascript-4gb</link>
      <guid>https://forem.com/ayowandeapp/simplify-large-numbers-with-style-a-guide-to-human-readable-representations-in-javascript-4gb</guid>
      <description>&lt;p&gt;Introduction&lt;br&gt;
In the world of finance, dealing with large numbers is a common occurrence. Imagine handling numbers representing amounts in the billions or trillions; it's essential to present these figures in a user-friendly and readable format. This blog post will delve into a JavaScript function that converts large numbers into a more compact and human-readable form.&lt;/p&gt;

&lt;p&gt;The Challenge&lt;br&gt;
Consider a situation where you have a value, say 1,360,000,000,000, and you want to convert it into a more manageable format like 1.36T. The challenge is not just about adding commas but about intelligently choosing the appropriate unit (K, M, B, T) based on the magnitude of the number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reduceAmount(value){
    const shortsymbols = {
        4: 'T',
        3: 'B',
        2: 'M'
    }

    let number  = value.toString().split('.')[0];
    let commaCount = Math.floor((number.length-1)/3);

    if(commaCount &amp;gt; 1){
        let symbol = shortsymbols[commaCount];
        let dotPlacement = number.length % 3;

        if(dotPlacement === 0) dotPlacement = 3; 


        if(Number(number.substr(dotPlacement+1)) &amp;gt; 0) symbol += '+';


        number = number.substr(0, dotPlacement) + '.' + number.substr(dotPlacement)

        // Rounds to tenths place
        number = Math.floor(Number(number) * 10) / 10

        number += symbol
    } else {
        number = this.addCommas(number);
    }

    console.log(number);
    return number;
},

addCommas(x){
  x = (Math.round(x * 100)/ 100).toFixed(2);
  return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation&lt;br&gt;
Short Symbols: The function starts with a dictionary shortsymbols mapping the length of the number to a symbol (e.g., 'B' for billion).&lt;/p&gt;

&lt;p&gt;Number Formatting: The function takes a numeric value, converts it to a string, and splits it at the decimal point, considering only the whole part.&lt;/p&gt;

&lt;p&gt;Comma Counting: It calculates the number of commas required by dividing the length of the number (minus one) by three.&lt;/p&gt;

&lt;p&gt;Handling Large Numbers: If the number is in the millions or above, it applies a shorthand symbol and intelligently decides whether to add a plus sign based on the remaining part after the dot.&lt;/p&gt;

&lt;p&gt;Dot Placement: It calculates the placement of the dot and ensures that there's no need for a dot if the dot placement is 3.&lt;/p&gt;

&lt;p&gt;Rounding: It rounds the number to the tenths place.&lt;/p&gt;

&lt;p&gt;Result: The final result is a compact, rounded, and symbol-appended representation of the original number.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
This function goes beyond merely formatting numbers; it intelligently chooses the appropriate unit and presents large figures in a concise, user-friendly manner. Whether you're dealing with financial data or any domain with large numerical values, this function provides a valuable tool for better data representation.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Creating a Countdown Timer with Vue.js</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Sat, 27 Jan 2024 10:46:56 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/creating-a-countdown-timer-with-vuejs-21nm</link>
      <guid>https://forem.com/ayowandeapp/creating-a-countdown-timer-with-vuejs-21nm</guid>
      <description>&lt;p&gt;Service Level Agreements (SLAs) often come with strict timelines, and having a visual representation of the time remaining can be crucial. In this post, we'll explore how to implement a countdown timer in Vue.js to display the remaining time for SLAs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Set Up Your Vue Component&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;span v-if="sla.expired" style="color: red;"&amp;gt;{{ `SLA Expired` }}&amp;lt;/span&amp;gt;
    &amp;lt;span v-else style="color: rgb(80, 180, 80)"&amp;gt;{{ `${displayTime}` }}&amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import moment from 'moment';

export default {
  props: {
    sla: Object,
    created_at: String,
  },
  data() {
    return {
      intervalId: null,
      displayTime: '',
    };
  },
  mounted() {
    this.startCountdown();
  },
  beforeDestroy() {
    clearInterval(this.intervalId);
  },
  methods: {
    startCountdown() {
      const initialDate = moment(this.created_at).add(this.sla.time, 'hours');

      this.intervalId = setInterval(() =&amp;gt; {
        const countdownDuration = initialDate.diff(moment());
        let secondsRemaining = moment.duration(countdownDuration).asSeconds();

        const hours = Math.floor(secondsRemaining / 3600);
        const minutes = Math.floor((secondsRemaining % 3600) / 60);
        const seconds = Math.floor(secondsRemaining % 60);

        this.displayTime = `${hours &amp;gt; 0 ? hours + 'h ' : ''}${minutes}m ${seconds}s`;

        if (secondsRemaining &amp;lt;= 0) {
          clearInterval(this.intervalId);
          this.$set(this.sla, 'expired', true);
        }

        secondsRemaining--;
      }, 1000);
    },
  },
};
&amp;lt;/script&amp;gt;

&amp;lt;style scoped&amp;gt;
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the mounted lifecycle hook to initiate the countdown when the component is mounted.&lt;br&gt;
The beforeDestroy hook ensures that the interval is cleared to prevent memory leaks when the component is destroyed.&lt;br&gt;
The startCountdown method calculates the remaining time and updates the displayTime variable accordingly.&lt;br&gt;
The countdown is displayed dynamically, and when it reaches zero, the SLA is marked as expired.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Use the Countdown Timer Component&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for="(sla, j) in liquidasset.slas" :key="sla.id"&amp;gt;
      &amp;lt;CountdownTimer :sla="sla" :created_at="liquidasset.created_at" /&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import CountdownTimer from '@/components/CountdownTimer.vue'; // Update the path based on your project structure

export default {
  components: {
    CountdownTimer,
  },
  data() {
    return {
      liquidasset: {
        created_at: '2024-01-27T12:00:00', // Example date
        slas: [...], // Your SLAs array
      },
    };
  },
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Implementing a countdown timer in Vue.js can enhance the user experience, especially in scenarios where time is of the essence. By breaking down the logic into a reusable component, you can easily integrate countdown timers into various parts of your application.&lt;/p&gt;

&lt;p&gt;Feel free to customize the code further based on your specific requirements and styling preferences. Happy coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>vue</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Efficient Data Generation in Laravel: Leveraging JSON Files &amp;&amp; Laravel Factory for Your Database</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Sun, 06 Aug 2023 11:16:00 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/efficient-data-generation-in-laravel-leveraging-json-files-laravel-factory-for-your-database-47a7</link>
      <guid>https://forem.com/ayowandeapp/efficient-data-generation-in-laravel-leveraging-json-files-laravel-factory-for-your-database-47a7</guid>
      <description>&lt;p&gt;Hello! Generating dummy or fake data for testing purposes is a common need in software development, and Laravel provides several ways to achieve this. Let's explore some of the methods commonly used in Laravel to generate test data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using a JSON file to store dummy data, you can follow these steps:&lt;/li&gt;
&lt;li&gt;Create a folder named "data" inside the "database" folder of your Laravel project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Inside the "data" folder, create a file named "category.json" and add the following JSON data to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
    {
        "id": 1,
        "name": "Electronics"
    },
    {
        "id": 2,
        "name": "Clothing"
    },
    {
        "id": 3,
        "name": "Books"
    }
]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This JSON data represents a list of categories with their respective IDs and names.&lt;/p&gt;

&lt;p&gt;Next, you can read the JSON data from the file and use it in your Laravel application. For example, you can use the DatabaseSeeder.php&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

namespace Database\Seeders;

// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        //get the data
        $data = File::get('database/data/category.json');
        //convert to array, of the asscociative kind
        $categories= collect(json_decode($data, true));
        $categories-&amp;gt;each(function($category){
            DB::table('category')-&amp;gt;insert([
                'category_name'=&amp;gt;$category['name'],
                'category_id'=&amp;gt;$category['id']
            ]);
        });
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Using faker
Laravel comes with the Faker library by default, which allows you to create fake data like names, addresses, emails, and more.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;create a factory for a post modal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;php artisan make:factory PostFactory&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the PostFactory
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PostFactory extends Factory
{
 public function definition(): array
    {
        $title = fake()-&amp;gt;unique()-&amp;gt;sentence();
        $slug = Str::slug($title);
        return [
            'title'=&amp;gt;$title,
            'slug'=&amp;gt;$slug,
            'description'=&amp;gt;fake()-&amp;gt;paragraph(9, true),
            'category'=&amp;gt;Category::inRandomOrder()-&amp;gt;value('category_id'),
        ];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in the DatabaseSeeder.php,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        //create 20 rows in the table
        Post::factory()-&amp;gt;count(20)-&amp;gt;create();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, what if we want a relationship to build as well for the post. For instance, where an author has many posts, and we want a fake data for that as well??&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Asynchronous Loading in Vue</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Fri, 16 Jun 2023 20:12:30 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/asynchronous-loading-in-vue-3195</link>
      <guid>https://forem.com/ayowandeapp/asynchronous-loading-in-vue-3195</guid>
      <description>&lt;p&gt;Recently, I came across a performance issue on a Vue webpage where the loading time was excessively long. Upon thorough investigation, it became evident that several functions were being loaded simultaneously in the mounted lifecycle hook. While these functions were necessary for the page, it was not essential for all of them to be called simultaneously. This simultaneous loading was causing a slowdown in the page's performance.&lt;/p&gt;

&lt;p&gt;To address this issue, one approach is to load specific functions asynchronously. By leveraging the power of async/await, along with Promise and setTimeout, we can achieve asynchronous loading and execution of the required functions within the mounted lifecycle hook of our Vue component. This ensures that the functions are loaded and executed in a non-blocking manner, enhancing the overall performance of the page.&lt;/p&gt;

&lt;p&gt;For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mounted() {
  this.synchronousFunction();
  this.loadAsyncFunctions();
},

methods: {
  async loadAsyncFunctions() {
    await this.delay(1000); // Delay for 1 second
    await this.asyncFunction();
    await this.delay(2000); // Delay for 2 seconds
  },

  async delay(ms) {
    return new Promise(resolve =&amp;gt; setTimeout(resolve, ms));
  },

  synchronousFunction() {
    console.log('This function is called synchronously');
  },

  async asyncFunction() {
    console.log('This function is called asynchronously');
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we have a mounted lifecycle hook in a Vue component. Inside the mounted hook, we call a synchronous function synchronousFunction() and an asynchronous function loadAsyncFunctions().&lt;/p&gt;

&lt;p&gt;The loadAsyncFunctions() method utilizes the async/await syntax to load and execute functions asynchronously. It uses the delay() function, which returns a promise that resolves after a specified delay (in milliseconds). By awaiting the delay() function, we can introduce delays between the execution of different async functions.&lt;br&gt;
The delay method is a utility function that returns a promise which resolves after the specified delay using setTimeout.&lt;/p&gt;

&lt;p&gt;The synchronousFunction() is a regular synchronous function that is called immediately.&lt;/p&gt;

&lt;p&gt;The asyncFunction() is an example of an asynchronous function that is also called within the loadAsyncFunctions() method. It showcases the asynchronous nature of the function.&lt;br&gt;
Each async function is invoked using await, which ensures that the subsequent function is only called after the previous one has completed.&lt;/p&gt;

&lt;p&gt;By using this approach, the synchronous function is called immediately, while the asynchronous functions are executed with delays, allowing for smoother performance and better user experience.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>vue</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Write custom Javascript to customize tinymce. increase and decrease font size.</title>
      <dc:creator>Ayowande Oluwatosin</dc:creator>
      <pubDate>Tue, 14 Mar 2023 14:05:51 +0000</pubDate>
      <link>https://forem.com/ayowandeapp/write-custom-javascript-to-customize-tinymce-increase-and-decrease-font-size-4hhn</link>
      <guid>https://forem.com/ayowandeapp/write-custom-javascript-to-customize-tinymce-increase-and-decrease-font-size-4hhn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;TinyMCE is a popular open-source WYSIWYG (what you see is what you get) HTML editor. It is designed to be used within web content management systems, online forums, and other web-based applications. It is available as a JavaScript library that can be integrated with other web technologies. It provides basic text editing features such as bold, italic, underline, font size, font color, and headings, as well as some advanced features such as tables, image insertion, and media embedding. &lt;/p&gt;

&lt;h3&gt;
  
  
  Add editing features to tinymce
&lt;/h3&gt;

&lt;p&gt;TinyMCE can be extended with a variety of plugins that add additional editing features. Some popular plugins include a spellchecker, a visual table editor, a code editor, and a link checker. These plugins can be added to TinyMCE through the TinyMCE Plugin Manager. Additional plugins can also be added by downloading them from the TinyMCE website.&lt;/p&gt;

&lt;p&gt;In addition to plugins, TinyMCE can also be customized by writing custom JavaScript code. This allows developers to add additional editing features to the editor, such as custom buttons and dialogs. Custom code can also be used to modify existing features, such as changing the way the editor behaves when a user changes the font or the size of an image.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write custom Javascript code to customize tinymce
&lt;/h3&gt;

&lt;p&gt;To write custom JavaScript code to customize TinyMCE, you first need to create a new JavaScript file and include it in your HTML page. Then, you can use TinyMCE’s API to make changes to the editor.&lt;/p&gt;

&lt;p&gt;For example, you can add a custom button to the editor toolbar using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tinymce.init({
  selector: 'textarea',
  toolbar: 'increaseFont decreaseFont',
  editor.addButton('increaseFont', {
      // icon: element,
        text: 'A+',
        onclick:function(){                         
            var currentFontSize = editor.getContent({ format: 'html' }).match(/font-size: (\d+\w+)/);
            if (currentFontSize) {
                var currentSize = parseInt(currentFontSize[1].replace(/[^\d]/, ''));
                if(currentSize === 36){
                    return false;
                }
            var newFontSize = parseInt(currentFontSize[1].replace(/[^\d]/, '')) + 2;
            var newFontSizeUnit = currentFontSize[1].replace(/\d+/, '');
            editor.execCommand('fontSize', false, newFontSize + newFontSizeUnit);

            }else if(currentFontSize ===null){
                editor.execCommand('fontSize', false, 14 + 'pt');

            }
        }
    });
    editor.addButton('decreaseFont', {
        // icon: '',
        text: 'A-',
        onclick:function(){                         
            var currentFontSize = editor.getContent({ format: 'html' }).match(/font-size: (\d+\w+)/);
            if (currentFontSize) {
                var currentSize = parseInt(currentFontSize[1].replace(/[^\d]/, ''));
                if(currentSize === 8){
                    return false;
                }
            var newFontSize = parseInt(currentFontSize[1].replace(/[^\d]/, '')) - 2;
            var newFontSizeUnit = currentFontSize[1].replace(/\d+/, '');
            editor.execCommand('fontSize', false, newFontSize + newFontSizeUnit);

            }else if(currentFontSize ===null){
                editor.execCommand('fontSize', false, 10 + 'pt');

            }
        }
    })

});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code adds two new button to the TinyMCE editor toolbar with the text “A+ and A-”. When the A+ button is clicked, the code inside the onclick function will be executed which increases the font on the selected text. Aso, When the A- button is clicked, the code inside the onclick function will be executed which decreases the font on the selected text. You can add more buttons to the editor by adding more addButton() calls to the setup function.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>frontend</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
