<?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>DEV Community: James Seconde</title>
    <description>The latest articles on DEV Community by James Seconde (@secondej).</description>
    <link>https://dev.to/secondej</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%2F322862%2F631de7ec-9a3f-4f1f-8b8b-4c43ff8d78c7.jpg</url>
      <title>DEV Community: James Seconde</title>
      <link>https://dev.to/secondej</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/secondej"/>
    <language>en</language>
    <item>
      <title>Sending SMS Messages with PHP</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Wed, 20 Aug 2025 13:45:00 +0000</pubDate>
      <link>https://dev.to/vonagedev/sending-sms-messages-with-php-4db5</link>
      <guid>https://dev.to/vonagedev/sending-sms-messages-with-php-4db5</guid>
      <description>&lt;p&gt;In this tutorial, we’re going to send SMS messages with as few lines of PHP as possible. Firstly, with a raw script, and secondly, using a minimal web application framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP 8.1+&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt;, for package management&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.vonage.com/sign-up" rel="noopener noreferrer"&gt;A Vonage API Account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Send Text with Raw PHP
&lt;/h2&gt;

&lt;p&gt;We’re going to start by creating a new Composer project and pulling in the Vonage PHP SDK. Using the command line, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir vonage-sms
cd vonage-sms
composer init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Composer will ask you a series of questions - you can leave these all to the defaults as we’re only doing the bare minimum of effort. The process should create your &lt;code&gt;composer.json&lt;/code&gt; file. So, we can add the Vonage PHP SDK now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require vonage/client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to create our script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch send-sms.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the new PHP file and make sure Composer’s autoload is pulled in:&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

require_once './vendor/autoload.php';

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

&lt;/div&gt;



&lt;p&gt;To send an SMS, we need three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A set of credentials taken from the Vonage Dashboard&lt;/li&gt;
&lt;li&gt;A Client object&lt;/li&gt;
&lt;li&gt;A text to send&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given this, here are the final lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$credentials = new \Vonage\Client\Credentials\Basic(YOUR_API_KEY, YOUR_API_SECRET);
$client = new Vonage\Client($credentials);
$message = new Vonage\Messages\Channel\SMS\SMSText(
  YOUR_NUMBER,
  'Vonage',
  'Hello from Vonage!'
);

$client-&amp;gt;messages()-&amp;gt;send($message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plug in the required details to the constant variable placeholders and hit send:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a1923pu4m15oehiqvox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a1923pu4m15oehiqvox.png" alt="Our SMS has been sent!" width="625" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four lines of code is pretty good! The second part is plugging this into a basic web framework so that you can POST a message instead of hard-coding it as we have above.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Send SMS via. Slim Framework
&lt;/h2&gt;

&lt;p&gt;For the second example, we’re going to be using the &lt;a href="https://www.slimframework.com/" rel="noopener noreferrer"&gt;Slim Framework&lt;/a&gt;, so install that with Composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require slim/slim:"4".*
composer require slim/psr7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command here installs Slim’s PSR-7 (Request Interface) implementation. We’re going to create a route that takes a POST request with a JSON body containing some text.&lt;/p&gt;

&lt;p&gt;Here is the modified &lt;code&gt;send-sms.php&lt;/code&gt; file:&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

use Slim\Psr7\Request;
use Slim\Psr7\Response;

require_once '../vendor/autoload.php';

$app = \Slim\Factory\AppFactory::create();

$app-&amp;gt;post('/send', function (Request $request, Response $response) {
   $rawBody = $request-&amp;gt;getBody()-&amp;gt;getContents();
   $requestData = json_decode($rawBody);
   $text = $requestData-&amp;gt;text;

   $credentials = new \Vonage\Client\Credentials\Basic('232130c9', 's09IJad98fa0t9j09ad8fa90s');
   $client = new Vonage\Client($credentials);
   $message = new Vonage\Messages\Channel\SMS\SMSText(
     YOUR_NUMBER,
     'Vonage',
     $text
);

   $client-&amp;gt;messages()-&amp;gt;send($message);

   $response-&amp;gt;getBody()-&amp;gt;write("Vonage sent this text!");
   return $response;
});

$app-&amp;gt;run();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of running this code, we’re mocking using a web platform instead, so we’re going to use PHP’s built-in webserver to fire up a development environment from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php -S localhost:8888 -t send-php.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To send the message, you’ll want an HTTP tooling client that makes it easy to send POST requests - I’ve opted for Kong’s &lt;a href="https://insomnia.rest/" rel="noopener noreferrer"&gt;Insomnia&lt;/a&gt; but you could also use &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; or even a raw cURL request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceppuer97ku4fhch21u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceppuer97ku4fhch21u7.png" alt="API Tooling is super helpful" width="626" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Now we have a route where you can send the message text to a server for it to complete the process. You can, of course, add additional keys to the JSON payload to add the from and to cellular numbers. Fancy building something out of it? Check out our &lt;a href="https://github.com/Vonage/vonage-laravel" rel="noopener noreferrer"&gt;Laravel integration&lt;/a&gt; or check out further reading on sending messages with this API in Symfony.&lt;/p&gt;

&lt;p&gt;Have a question or something to share? Join the conversation on the &lt;a href="https://developer.vonage.com/en/community/slack" rel="noopener noreferrer"&gt;Vonage Community Slack&lt;/a&gt;, stay up to date with the &lt;a href="https://ww3.nexmo.com/subscribe-the-vonage-developer-newsletter" rel="noopener noreferrer"&gt;Developer Newsletter&lt;/a&gt;, follow us on &lt;a href="https://x.com/vonagedev" rel="noopener noreferrer"&gt;X (formerly Twitter)&lt;/a&gt;, and subscribe to our &lt;a href="https://www.youtube.com/@VonageDev" rel="noopener noreferrer"&gt;YouTube channel &lt;/a&gt;for video tutorials. Stay connected, share your progress, and keep up with the latest developer news, tips, and events!&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/send-sms-from-php-with-failover-dr" rel="noopener noreferrer"&gt;Sending SMS from PHP with Failover: The Cupcake Bakery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/type-safety-done-right-php-array-hacking" rel="noopener noreferrer"&gt;Type Safety Done Right - PHP Array Hacking&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/scrub-up-cleaning-your-php-application-with-phpstan" rel="noopener noreferrer"&gt;Scrub Up! Cleaning Your PHP Application With PHPStan&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Vonage/vonage-php-sdk-core" rel="noopener noreferrer"&gt;Vonage PHP SDK&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>How To Send WhatsApp Messages with Laravel</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Wed, 14 Feb 2024 15:09:02 +0000</pubDate>
      <link>https://dev.to/vonagedev/how-to-send-whatsapp-messages-with-laravel-1idp</link>
      <guid>https://dev.to/vonagedev/how-to-send-whatsapp-messages-with-laravel-1idp</guid>
      <description>&lt;p&gt;If you’re not familiar with the Messages API, you can send text, images, and video to Facebook Messenger, Viber, WhatsApp, and the more basic SMS channel. Vonage has a sandbox testing environment for you to play with these, so in this tutorial, we’re going to use that to play with WhatsApp Messaging using a demo Laravel application I’ve already set up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;We’re going to keep this as simple as possible. You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP8.1+&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;git &lt;/li&gt;
&lt;li&gt;&lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ui.idp.vonage.com/ui/auth/registration" rel="noopener noreferrer"&gt;A Vonage API Account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Clone the Repository Code
&lt;/h2&gt;

&lt;p&gt;Using the command line, clone the application code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone git@github.com:Vonage-Community/blog-messages-laravel.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the &lt;code&gt;.env.example&lt;/code&gt; as &lt;code&gt;.env&lt;/code&gt; to create our environment variables file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd blog-messages-laravel
$ cp .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, install the dependencies with composer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ composer install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Set up the Vonage Dashboard
&lt;/h2&gt;

&lt;p&gt;First, we’re going to need an application ID to send messages. Head to the Vonage Dashboard, and create a new application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frktsj4kss83w5fspuq6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frktsj4kss83w5fspuq6i.png" alt="Screenshot of the Application panel in the Vonage Dashboard" width="625" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name your application with an identifier (i.e. laravel-messages) and turn on the Messages capability. You’ll need to add two webhooks here, but we won’t actually be using these so you can put dummy placeholders in e.g. &lt;code&gt;https://www.example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Hit “Generate public and private key”. You’ll notice that a &lt;code&gt;private.key&lt;/code&gt; will be generated: move this into your application code’s root directory. Take note of the Application ID that is created: we’ll need this shortly.&lt;/p&gt;

&lt;p&gt;That takes care of the Application settings, so we now need to set up the Sandbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dashboard.nexmo.com/messages/sandbox" rel="noopener noreferrer"&gt;Head to this page&lt;/a&gt; or navigate to it using the left sidebar under &lt;code&gt;Troubleshoot &amp;amp; Learn &amp;gt; Developer Tools &amp;gt; Messages Sandbox&lt;/code&gt;and follow the instructions to create a WhatsApp sandbox by scanning the QR code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl46vbpooyb1v4y96xom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl46vbpooyb1v4y96xom.png" alt="Screenshot of the Messages Sandbox" width="620" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a fully integrated solution in production, you would need a WhatsApp Business Account (WABA) registered with Meta. What the sandbox allows you to do is use a temporary WABA - you’ll now have your number on an allow list, with a preset number that is linked to Vonage’s servers.&lt;/p&gt;

&lt;p&gt;Once the number has been set up, you can scroll down to some example cURL code that gives you the sender number to use:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xbl8ipu65zcp59e24nx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xbl8ipu65zcp59e24nx.png" alt="Screenshot of the Sandbox code snippets section showing the from number" width="618" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure The Application Environment
&lt;/h2&gt;

&lt;p&gt;When we created the &lt;code&gt;.env&lt;/code&gt; file, you’ll notice that there are three variables to fill out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VONAGE_APPLICATION_ID=
VONAGE_PRIVATE_KEY_PATH=
VONAGE_FROM_NUMBER=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should now have all three of these. The &lt;code&gt;from&lt;/code&gt; number was created in the previous step, enter &lt;code&gt;private.key&lt;/code&gt; as our path (the application code uses the Laravel helper function base_path() to determine the fully qualified path, so if you wanted to move the key into a different directory structure you’d do it relative from the root). Our Application ID can be pasted in from the Vonage Dashboard when we created a Vonage Application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boot Up the Application
&lt;/h2&gt;

&lt;p&gt;No fancy stuff like &lt;a href="https://laravel.com/docs/10.x/sail" rel="noopener noreferrer"&gt;Sail&lt;/a&gt; or &lt;a href="https://herd.laravel.com/" rel="noopener noreferrer"&gt;Herd&lt;/a&gt; here: we’re just going to use the built-in PHP server that Laravel wraps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we should get the lovely landing page by navigating to &lt;code&gt;localhost:8000&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0d56unlsh6u9m0t14jc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0d56unlsh6u9m0t14jc.png" alt="Screenshot of Laravel's default splash screen" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve not got any way for the Vonage servers to give us incoming message webhooks, so to get a public URL we are going to use &lt;a href=""&gt;ngrok&lt;/a&gt; to map to our running Laravel application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ngrok http 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr2t8upqijb7j1zrkclz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcr2t8upqijb7j1zrkclz.png" alt="Screenshot of ngrok running on the command line" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a public URL! The last part of the configuration is to create our webhooks, so head back to the Messages Sandbox on the Vonage Dashboard. Take the public URL we have, and add /webhooks/status and /webhooks/inbound to the relevant fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F211ol08rk1l7rojqm893.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F211ol08rk1l7rojqm893.png" alt="Screenshot of the webhooks section in the Messages Sandbox" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test It!
&lt;/h2&gt;

&lt;p&gt;Head to &lt;code&gt;localhost:8000/message&lt;/code&gt; and send a message!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6izvgznckxeh3qgi70zd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6izvgznckxeh3qgi70zd.png" alt="Screenshot of the Laravel app running waiting for a phone number input" width="442" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt02qrpa5psy5hypxois.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt02qrpa5psy5hypxois.png" alt="Screenshow of device running WhatsApp showing our messages" width="786" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Do That?
&lt;/h2&gt;

&lt;p&gt;It’s time to dive into the code. All of the logic is only in the &lt;code&gt;routes/web.php&lt;/code&gt; file instead of in controllers to keep things simple. Two important routes to look at make up the essential parts of the app. Firstly, the outgoing message route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::post('/message', static function(Request $request) {
   $number = $request-&amp;gt;input('number');
   $fromNumber = config('vonage.from_number');
   $text = 'Hello from Vonage and Laravel :) Please reply to this message with a number between 1 and 100';
   $message = new Vonage\Messages\Channel\WhatsApp\WhatsAppText($number, $fromNumber, $text);

   $credentials = new Keypair(file_get_contents(config('vonage.private_key_path')), config('vonage.application_id'));
   $client = new Vonage\Client($credentials);
   $client-&amp;gt;messages()-&amp;gt;getAPIResource()-&amp;gt;setBaseUrl('https://messages-sandbox.nexmo.com/v1/messages');
   $client-&amp;gt;messages()-&amp;gt;send($message);

   return view('thanks');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the form and POST request when sending out the initial message. The only task of this route is to take the number entered in the form and to send out a WhatsApp message. If you’re wondering how we send this to Vonage, the answer is in the Vonage PHP SDK. The SDK Client object takes a credentials object (in this case, a Keypair instance), which we pass in the Application ID and Private Key path environment variables we created earlier to the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$credentials = new Keypair(file_get_contents(config('vonage.private_key_path')), config('vonage.application_id'));
$client = new Vonage\Client($credentials);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information on how you can use the PHP SDK, &lt;a href="https://github.com/Vonage/vonage-php-sdk-core?tab=readme-ov-file#client-library-for-php" rel="noopener noreferrer"&gt;check out the ReadMe&lt;/a&gt; that gives examples for using the Messages API. To send a message, we create a WhatsAppText object, pass in the the destination number and the sandbox &lt;code&gt;from&lt;/code&gt; number configured earlier.&lt;/p&gt;

&lt;p&gt;Before we send the message using the client, there is an important step that is specific to our use case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$client-&amp;gt;messages()-&amp;gt;getAPIResource()-&amp;gt;setBaseUrl('https://messages-sandbox.nexmo.com/v1/messages');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line here uses the decoupled nature of the PHP SDK (all of the parts of the SDK can be reconfigured or swapped out) to pull out the production-configured APIResource object and override it with the sandbox URL. So, all the client needs to do now is send it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$client-&amp;gt;messages()-&amp;gt;send($message);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Receive an Incoming WhatsApp Message
&lt;/h2&gt;

&lt;p&gt;The second part is coding a route that listens for incoming webhooks that have come from Vonage - these will be triggered every time someone replies to the thread we created in the first step. Here is the endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::post('/webhooks/inbound', static function(Request $request) {
   $data = $request-&amp;gt;all();
   $number = (int)$data\['text'];

   if ($number &amp;gt; 0) {
       $randomNumber = random_int(1, 8);
       $respondNumber = $number * $randomNumber;
       $toNumber = $data\['from'];
       $fromNumber = config('vonage.from_number');
       $text = "The answer is " . $respondNumber . ", we multiplied by " . $randomNumber . ".";
       $message = new Vonage\Messages\Channel\WhatsApp\WhatsAppText($toNumber, $fromNumber, $text);

   $credentials = new Keypair(file_get_contents(config('vonage.private_key_path')), config('vonage.application_id'));
   $client = new Vonage\Client($credentials);
   $client-&amp;gt;messages()-&amp;gt;getAPIResource()-&amp;gt;setBaseUrl('https://messages-sandbox.nexmo.com/v1/messages');
   $client-&amp;gt;messages()-&amp;gt;send($message);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we extract the details we need to reply to the message - namely the phone number to reply to and the number they sent as part of the message. With this information, the number sent is multiplied by a random number between 1 and 8 and we fire off a reply with the same structure as how we sent the initial message.&lt;/p&gt;

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

&lt;p&gt;And there we have it: ways to interact using WhatsApp in Vonage! As you can imagine, this sort of setup is ideal for automated chatbots such as a helpline, but what will you build? Let us know on the &lt;a href="https://developer.vonage.com/community/slack" rel="noopener noreferrer"&gt;Vonage Community Slack&lt;/a&gt; or hit me up on &lt;a href="https://phpc.social/@SecondeJ" rel="noopener noreferrer"&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Vonage-Community/blog-messages-laravel" rel="noopener noreferrer"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/VonageDev" rel="noopener noreferrer"&gt;Vonage Developers (X)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/api/messages-olympus?source=messages" rel="noopener noreferrer"&gt;Messages API Reference&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/messages/concepts/messages-api-sandbox?source=messages" rel="noopener noreferrer"&gt;Messages API Sandbox Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/scrub-up-cleaning-your-php-application-with-phpstan" rel="noopener noreferrer"&gt;S﻿crub Up! Cleaning Your PHP Application with PHPStan&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/sending-sms-messages-with-php-dr#sending-an-sms-via-a-php-api-with-slimphp" rel="noopener noreferrer"&gt;Sending an SMS via a PHP API with SlimPHP&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/en/blog/send-sms-from-php-with-failover-dr" rel="noopener noreferrer"&gt;S﻿ending SMS from PHP with Failover: The Cupcake Bakery&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.vonage.com/community/slack" rel="noopener noreferrer"&gt;Vonage Community Slack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vonage</category>
      <category>laravel</category>
      <category>messages</category>
      <category>api</category>
    </item>
    <item>
      <title>On Meritocracy</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Fri, 28 May 2021 07:40:55 +0000</pubDate>
      <link>https://dev.to/secondej/on-meritocracy-1gh7</link>
      <guid>https://dev.to/secondej/on-meritocracy-1gh7</guid>
      <description>&lt;p&gt;I am a product of the PHP community - it's how I got into software development, it's why I have my career, it's why I now do Developer Relations.&lt;/p&gt;

&lt;p&gt;There are three factors that made me choose this path. They are all from the same conference, in 2012. Those factors are three specific speakers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Jenny Wong&lt;/li&gt;
&lt;li&gt;Lorna Mitchell&lt;/li&gt;
&lt;li&gt;Jessica Rose&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You see, the thing is, to my naive eyes at that point in my tech career it didn't strike me as at all different in any way that these three people were not men. What I had failed to acknowledge is the reason &lt;em&gt;why&lt;/em&gt; there was such a top line-up at PHPUK 2012. The reason was because it was being curated by people who were levelling up the field by doing research and getting the best people in to speak that represented what the community -should- look like due to the talent out there. Only now, with a lot more experience from networking with communities and developers have I realised that sexism is absolutely rampant in the field I am supposed to call my home. But why hadn't I noticed?&lt;/p&gt;

&lt;p&gt;Let's talk about the "CIS-white-man-privilege" card.&lt;/p&gt;

&lt;p&gt;To some, using these terms may cause an inevitable groan that conjure up other terms from the other side of the fence such as "Social Justice Warrior". My role here, however, is to convince you (if you've groaned) that this card exists, so I'll back it up with evidence of my experiences.&lt;/p&gt;

&lt;p&gt;I wanted to be a developer, so I went to meetups. I went to conferences. I spoke with other developers. I confidently bagged a backend developer role, entering as a junior, in my 30's. I have no CS degree, I had no experience as a software developer at the time. I was enthusiastic, eager to learn. That's all you need right?&lt;/p&gt;

&lt;p&gt;When entering into tech this way and getting into Developer Relations, again I was confident. I wanted to do it, I started speaking, I started writing. I convinced a business to let me do these things. I started my own meetup. I did all of these things without being challenged. And the reason &lt;em&gt;why&lt;/em&gt; I hadn't been challenged is because I'd got wind that tech was a meritocracy: that "Uncle" Bob Martin had said it was all about the code. Nothing more, nothing less.&lt;/p&gt;

&lt;p&gt;It's not though, is it? It's not a meritocracy:&lt;/p&gt;

&lt;p&gt;I've not been at a conference as a developer and been mistaken for a recruiter or sales because of my gender.&lt;/p&gt;

&lt;p&gt;When building my public brand, I've not had direct messages on Twitter advising me that right now, my best option is to quit tech and raise children at home.&lt;/p&gt;

&lt;p&gt;After speaking at events, I've not had unsolicited emails with twenty five bullet points on advice about how to make my talk better.&lt;/p&gt;

&lt;p&gt;I've not had to justify my position as being a software developer by being questioned in-depth about a super-abstract computer science concept because I made a passing remark in conversation.&lt;/p&gt;

&lt;p&gt;Yes, these are real world cases, so we need to stop pretending this doesn't happen. If you think it doesn't happen, the important line I want you to acknowledge is that the truth is &lt;em&gt;"it doesn't happen to me"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I first started encountering things like this in my first agency environment, where the Christmas party, consisting of about 55 developers -of which only two were not male- decended into (I'm not joking here) an arm-wrestling contest. At that company I also vividly remember an individual in management assessing the looks of a visiting recruiter out loud to no response. The blank response resulted in them exclaiming, "was that sexist? It was probably sexist. Ah, well", and everyone turned their chairs back to their screens.&lt;/p&gt;

&lt;p&gt;This isn't the industry I want to work in. I mean, this is behind closed doors - if you want to see it in public, I'd say &lt;a href="https://twitter.com/zuzana_kunckova"&gt;Zuzana Kunckova&lt;/a&gt; announcing the creation of the Larabelles community for non-male Laravel developers was a pretty good example. I'm not going to post the link, but a ton of developers dogpiled in with "why is there a need for this, we're all equal? This is dividing us and is pointless". &lt;/p&gt;

&lt;p&gt;It wasn't the right question. The right question should have been, "what has made non-male developers feel like they need to set up a new community with an emphasis on it being a safe environment?" That's the real question, and the ones they were asking answered the question I put forward perfectly.&lt;/p&gt;

&lt;p&gt;There is one final example of this to give, and it's important to me because it is the reason I have finally written an article like this.&lt;/p&gt;

&lt;p&gt;This article was written for &lt;a href="https://unbreak.tech/"&gt;unbreak.tech&lt;/a&gt;, an initative from &lt;a href="https://twitter.com/whitep4nth3r"&gt;whitep4nth3r&lt;/a&gt; that was created after a twitch raid that saw her enduring a shocking wave of sexual harrassment. Non-male tech streamers should not have to experience this in these times. This is appalling. My regret when writing this article is that, on seeing this being unbreak being created, I haven't taken as much action as I could have.&lt;/p&gt;

&lt;p&gt;One of my objectives with this article is to point out how bad things are, still, in 2021. The other is showing how we can change things.&lt;/p&gt;

&lt;p&gt;In my talk of 2019 on elitism in tech, I advocated for steering away from what I described as "gatekeeper hell" by using &lt;a href="https://en.wikipedia.org/wiki/Nudge_theory"&gt;nudge theory&lt;/a&gt;. We all have a small part to play in 'nudging' people away from outdated stereotypes. But does it work?&lt;/p&gt;

&lt;p&gt;Yes, it does. We need allies within our ranks to lead by example. The example I always go to is &lt;a href="https://twitter.com/SamanthaGeitz/status/1167065400502345728"&gt;Samantha Geitz's story about her first Laracon experience.&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We need more leaders like Matt. &lt;/p&gt;

&lt;p&gt;We need more allies. &lt;/p&gt;

&lt;p&gt;We all need to do our bit.&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>community</category>
      <category>culture</category>
    </item>
    <item>
      <title>Brum Tech Tapas: A Retrospective</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Thu, 27 May 2021 07:54:29 +0000</pubDate>
      <link>https://dev.to/jump24/brum-tech-tapas-a-retrospective-5g7b</link>
      <guid>https://dev.to/jump24/brum-tech-tapas-a-retrospective-5g7b</guid>
      <description>&lt;p&gt;Launching a new event for the city, towards what will be hopefully the end of the COVID crisis was always going to be a daunting task. Wary of the dreaded ‘Zoom fatigue’, numbers for online events have slowly been dropping over the past year or so. But, with a huge push from the team at Jump24, we did it - and our building excitement before launching was satisfied with something we really enjoyed and are proud of.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jump24.co.uk/journal/running-and-speaking-at-online-events-what-weve-learned/"&gt;We previously wrote a blog post&lt;/a&gt; on launching online events, and what we’d learned in the process. Building on that, it makes sense to write up what we learned during the launch of Brum Tech Tapas (and we learned a lot!). There is, however, a lot to take in. So, in the spirit of “tapas” being “bitesize chunks”, we thought we split our thoughts into three natural categories. First up, it’s:&lt;/p&gt;

&lt;h1&gt;
  
  
  BRUM
&lt;/h1&gt;

&lt;p&gt;This is a local event, created for the community here, with a line up of speakers doing work in the region. &lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting Speakers
&lt;/h2&gt;

&lt;p&gt;The speakers really provide the core content of the whole event, and drive the direction of the event – so our speaker selection was very carefully planned. As a team, we created a shortlist (which became a very long list in a matter of hours!) of who we wanted to invite. Our lists contained people expert in the areas outlined in the introduction – so for a quick reminder:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4vPFhojC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-4-1024x531.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4vPFhojC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-4-1024x531.png" alt="Image of me speaking at Brum Tech Tapas" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We approached people in a number of ways – Twitter Direct Messages, LinkedIn Direct Messages, email addresses we found on websites. Communication is hard when so many channels are available, but really Twitter was probably the most effective. There is reasoning behind this – one of the targets for Brum Tech Tapas content from speakers was to get the “inside story” or honest account of what they work on rather than the sales pitch. For some speakers, this doesn’t apply, but for those operating in corporate spaces it certainly rings true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diversity / Inclusion
&lt;/h2&gt;

&lt;p&gt;In our world of tech, the demographics of those speaking at meetups and conferences are still massively skewed towards middle-aged white men – commonly known as ‘manels’. Well, you won’t see one of those at Brum Tech Tapas. This is an event for the West Midlands, so it is essential to the mission that speaker selection represents the region correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code of Conduct
&lt;/h2&gt;

&lt;p&gt;We believe that a Code of Conduct (CoC) is absolutely vital. We adapted the one used by PyCon US (&lt;a href="https://us.pycon.org/2020/about/code-of-conduct/"&gt;https://us.pycon.org/2020/about/code-of-conduct/&lt;/a&gt;) for Brum Tech Tapas that you can find here (&lt;a href="https://brumtechtapas.co.uk/code-of-conduct/"&gt;https://brumtechtapas.co.uk/code-of-conduct/&lt;/a&gt;). Launching the event online means applying the CoC somewhat differently, so Chris, Dan and Ollie moderated the YouTube chat room. Thankfully CoC violations are rare (especially for a new event) but given our ambition to grow, we made sure we were doing things the right way. It didn’t go unnoticed, given that several of our attendees gave positive feedback that we had a CoC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;p&gt;The principal driver behind how we conceived and executed Brum Tech Tapas comes from the world of Developer Relations. You can read a decent outline on what this looks like from Matthew Revell’s Hoopy consultancy &lt;a href="https://developerrelations.com/strategy-and-metrics/the-four-pillars-of-developer-relations"&gt;here&lt;/a&gt;. Like with any good event, it’s about putting the community first.&lt;/p&gt;

&lt;p&gt;Interesting things happened as a result, some of which we couldn’t have predicted but were delighted to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asset Reuse
&lt;/h2&gt;

&lt;p&gt;We contacted several tech organisations in the city to see if they were interested in promoting the event. It may sound like I’m easy to please, but given how hard it is to collaborate and promote ourselves within the region, it was a genuine delight to see our assets being reused without any ask in return.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZT2fDtUf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-5-1024x536.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZT2fDtUf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-5-1024x536.png" alt="Image created by Birmingham Tech to promote Brum Tech Tapas" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iDxmt1YB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-6-1024x573.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iDxmt1YB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-6-1024x573.png" alt="Image created by Innovation Alliance to promote Brum Tech Tapas" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The top image comes courtesy of &lt;a href="https://birmingham.tech/"&gt;Birmingham Tech&lt;/a&gt;, who promoted our event through their platform and created this promo image themselves – and it looks great! The second image appeared to our surprise from &lt;a href="https://innovationwm.co.uk"&gt;Innovation Alliance&lt;/a&gt; – while we didn’t have any direct contact with them, I suspect this was the work of &lt;a href="https://twitter.com/tn_midlands"&gt;Naomi Nash&lt;/a&gt; at &lt;a href="https://technation.io/"&gt;Tech Nation&lt;/a&gt; who helped us promote through their network. Both Naomi and &lt;a href="https://twitter.com/yiannismaos"&gt;Yiannis&lt;/a&gt; had generated interest through their spheres of influence, which put my mind at ease that people were indeed interested in what we were putting together.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Wider Audience
&lt;/h2&gt;

&lt;p&gt;Now, this was harder. We could do promotion through our tech network but our speaker pool lay outside of our comfort zone. Our starting point was to get word-of-mouth out there from people who we have approached about speaking or promoting. You can’t suddenly declare yourself as a connected expert in the art world of Birmingham, for instance, so instead we had a lot of conversations with people who ARE expert in those spaces. We pitched Brum Tech Tapas as a concept to them, and if they liked what they see – they could speak or recommend speakers to us. Because, after all, the event is for the community.&lt;/p&gt;

&lt;p&gt;Rather than plan, plan and plan with massive ambitions for Brum Tech Tapas, we just wanted to launch the event and get the momentum going for more events. As such, we didn’t set massive targets, because really just launching the event and getting attendees could be seen as a success. We also made it free, to encourage participation and send a message that this is a not-for-profit event.   So, we set relatively low targets – 50 tickets ‘sold’ through EventBrite, with perhaps a 45-50% turnout from that. We were absolutely delighted when around 60 people watched the live event during most of its 2 ½ hour duration . We most definitely counted that as a win.&lt;/p&gt;

&lt;p&gt;On the subject of tickets – when sales started coming in, we saw many familiar faces of colleagues, friends and peers within tech. However, shortly after launch we were selling tickets to people totally unfamiliar to us, mostly in waves after using social media to promote other organisations and interesting people, which brings us neatly onto:&lt;/p&gt;

&lt;h2&gt;
  
  
  Promoting the Region
&lt;/h2&gt;

&lt;p&gt;One of the approaches we wanted to take was to give shout outs to all the amazing people and organisations that we want to connect with, potentially as speakers or who would know people in their own industries that could speak (or attend!). In doing so, we &lt;a href="https://www.youtube.com/watch?v=Porng9S0nRk"&gt;discovered so much more about these areas of the city’s creative ecosystem&lt;/a&gt;. Here are a couple of examples:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fbvx5REV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fbvx5REV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-2.png" alt="Image of tweets about Civic Square scheme" width="582" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hk54pdol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hk54pdol--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/04/image-3.png" alt="Image of Digbeth" width="581" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The conclusion here is that we achieved what we set out to do, and that promoting the people and organisations that we see doing great stuff establishes the connections we want to make for future events. Put your trust in the community before your own requirements, and people will take you seriously.&lt;/p&gt;

&lt;p&gt;Next up, we’ll cover the “tech” part of Tech Tapas. After all, we’re a tech company streaming an event online-only for now, so there was bound to be some interesting snags along the way, right?&lt;/p&gt;

</description>
      <category>community</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Remote Code Pairing with PHPStorm</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Fri, 07 May 2021 09:25:27 +0000</pubDate>
      <link>https://dev.to/jump24/remote-code-pairing-with-phpstorm-gbe</link>
      <guid>https://dev.to/jump24/remote-code-pairing-with-phpstorm-gbe</guid>
      <description>&lt;p&gt;Among the many challenges developers face when working 100% remote are those times when you face a problem that results in you staring at your IDE blankly for minutes on end.&lt;/p&gt;

&lt;p&gt;The ability to swivel your chair around and quickly throw out “have you got 2 minutes to rubber duck this bit of code please?” has become a distant memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7LO_P1xl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/02/ducks-1024x683.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7LO_P1xl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/02/ducks-1024x683.png" alt="Loads of rubber ducks in a factory" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pair programming is a practice that I have encountered far less than I feel is acceptable within agency software development. As always, everything evolves around time; from what I have experienced across this sector, if it’s not coding that feature and getting it out the door as quickly as possible, it’s not worth the company’s time.&lt;/p&gt;

&lt;p&gt;Of course, at Jump24 we don’t operate like that, because investing time in &lt;a href="https://jump24.co.uk/journal/tools-of-our-trade/"&gt;our tooling&lt;/a&gt; is part of what we do. We can’t all be &lt;a href="https://twitter.com/skirani/status/1149302828420067328"&gt;10x Engineers&lt;/a&gt; and so, with the company completely remote, how do we solve the rubber duck problem?&lt;/p&gt;

&lt;p&gt;Remote pair programming tools have been around for some time – Saros, which is available for IntelliJ and Eclipse, has &lt;a href="https://github.com/saros-project/saros/releases/tag/v0.8"&gt;been in development since 2006&lt;/a&gt; for example. One of the other IDEs we use at Jump24 is VSCode (or &lt;a href="https://vscodium.com/"&gt;VSCodium&lt;/a&gt;, which is VSCode with Microsoft’s telemetrics reporting taken out) has several extensions available that also do remote sessions – CodeTogether is a solid choice in my experience.&lt;/p&gt;

&lt;p&gt;Like many organisations, 2020’s COVID crisis has propelled some of these tools to the forefront of developers’ consciousness – and it seems Jetbrains responded by accelerating development on it’s remote pairing plugin. While it’s already been mentioned that VSCode has remote pairing extensions available, the same features were astonishingly requested in Jetbrains’ Issue Tracker as long ago as 2004. Spearheaded presumably by COVID demands from remote workers, finally on 2020-09-18 &lt;a href="https://blog.jetbrains.com/blog/2020/09/28/code-with-me-eap/"&gt;Code With Me&lt;/a&gt; was released.&lt;/p&gt;

&lt;p&gt;So, when trying to debug a particularly tricky set of &lt;a href="https://jump24.co.uk/our-work/"&gt;feature tests&lt;/a&gt; with &lt;a href="https://twitter.com/_pads"&gt;Ben Paddock&lt;/a&gt;, it seemed like the perfect time for us to experiment with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Before
&lt;/h2&gt;

&lt;p&gt;What would the next steps have previously been before Code With Me, then? Well, choose your video conferencing suite of choice, share screen and one of you drives the session. It’s not the most intuitive of solutions, but it does at least mean your partner can see and dictate potential changes with you over video.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems
&lt;/h2&gt;

&lt;p&gt;The biggest blocker for this type of pairing is that the ‘client’ human has no control over the IDE. Indeed, this is true of real life: when trying to think of potential solutions in code, one of you can only dictate to the other who is driving. I’m sure many readers would agree that, sometimes, dictating code and code changes is hard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Code With Me has a couple of advantages over similar plugins such as CodeTogether. Here’s the two key features at Jump24 we found that were essential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Because it uses a remote Java client developed by Jetbrains, it sandboxes the whole IDE on the host to the client. This means that the client doesn’t need to have the codebase. In our development where individual developers work on large, split codebases with entire Docker stacks, this gives a massive boost by not necessarily needing the entire project downloaded, dependencies from Javascript and PHP run and docker-compose spun up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Because this client replaces the functionality of what ssh would be doing if you were to remote pair in something like, for example, vim and tmux, it means you both have 100% keypress access to the same remote terminal. If you were both debugging on a remote server, sure this doesn’t seem special. But, couple this with our large Docker stacks and both of you can run a command line ssh’d within the Docker stack on the host machine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aha! But Security!
&lt;/h2&gt;

&lt;p&gt;So, in terms of security and given that you can share an entire codebase with another “dumb IDE”, what’s going with those comms under the hood?&lt;/p&gt;

&lt;p&gt;The answer is: they’re going through Jetbrains’ servers. The infosec managers cry “ISO27001!” and if you’re in a large MegaCorp your pairing dreams are over. But, one of the really lovely features rolled out with this plugin is you can &lt;a href="https://www.jetbrains.com/help/cwm/code-with-me-quick-setup.html"&gt;run your own Code With Me server&lt;/a&gt;. Take that, MegaCorp!&lt;/p&gt;

&lt;h2&gt;
  
  
  Similar approaches: VSCode
&lt;/h2&gt;

&lt;p&gt;It’s worth noting that, &lt;a href="https://xkcd.com/378/"&gt;because I have some streak of masochism about me&lt;/a&gt;, I actually use two IDEs: PhpStorm for backend development in PHP and React/Vue and VSCodium for node.js and vanilla JS.&lt;/p&gt;

&lt;p&gt;CodeTogether has been available for VSCode for quite some time now, and while you might be tempted to scoff that users of that IDE have been ahead of the game, the two key features noted (remote shared terminal, run your own server) make Code With Me just take the edge. I expect these features to likely be on the way, mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: more joyful pairing
&lt;/h2&gt;

&lt;p&gt;Zoom calls and Skype screen sharing in the time of COVID have become tiresome, but switching to this toolset makes remote pairing a world of difference for the better. There’s just too many upsides to ignore here – as well as key features mentioned, it’s just the little things when trying to untangle your spaghetti. When you’ve both got the IDE running rather than one transmitted across via screen share, your linter works, both of you can use code completion and can navigate through classes – the list goes on.&lt;/p&gt;

&lt;p&gt;And, more to the point: surely anything is better than trying to dictate to the user what code to write.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mODLx34l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/02/joyfulpairing-768x432.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mODLx34l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://jump24.co.uk/uploads/2021/02/joyfulpairing-768x432.png" alt="A Turtle on a keyboard, because finding images is hard" width="768" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Running and speaking at Online Events: what we’ve learned</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Mon, 07 Dec 2020 14:09:23 +0000</pubDate>
      <link>https://dev.to/jump24/running-and-speaking-at-online-events-what-we-ve-learned-4dij</link>
      <guid>https://dev.to/jump24/running-and-speaking-at-online-events-what-we-ve-learned-4dij</guid>
      <description>&lt;p&gt;My start at Jump24 was never going to be straightforward – the United Kingdom was in full COVID-19 lockdown, bringing down tech meetups and conferences worldwide at the point when I was fully launching into a Developer Relations role, which would immediately have to be redefined to make our developer outreach work. But: we currently have a talk and live code demo session currently on tour – so how did we do it, and what experience have we gained? But first: some observations about the impact of COVID-19 on our communities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slow to adapt: how tech got caught napping
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8jxazabxwnzmn7znj66f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8jxazabxwnzmn7znj66f.png" alt="Screenshot of events being cancelled on meetup.com" width="606" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s hardly a surprising outcome with what happened after the Prime Minister announced full lockdown on 24th March. 34 tech events happened in the first two months in the West Midlands region in the UK, including regulars from DevOps, AWS, Ruby, Javascript, Xamarin/.NET, Docker and ProductTank. After lockdown in April and May, just 6 of the regular meetups happened after switching online, almost all of them Zoom calls. &lt;/p&gt;

&lt;p&gt;This was only for our region of course: the unexpected overhead of suddenly needing to organise and promote on entirely digital platforms meant that grassroots meetups dropped off all over the world and conferences got cancelled with no time to arrange alternative online setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speaking: Turbocharged development with Xdebug, Docker &amp;amp; PhpStorm
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa4dsgxtgtzan4u5w1llv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa4dsgxtgtzan4u5w1llv.png" alt="Screenshot of James Seconde giving Xdebug talk" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the first question we had to ask was that if some usergroups were being continued online, should we go ahead with the idea of delivering a talk we’d prototyped internally? First, we’d have to solve the elephant in the room: this was due to be a live code demo. So, to deliver this talk we’d need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A speaker, me&lt;/li&gt;
&lt;li&gt;Google Slides, using Chrome&lt;/li&gt;
&lt;li&gt;A bash terminal&lt;/li&gt;
&lt;li&gt;PhpStorm&lt;/li&gt;
&lt;li&gt;Firefox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you juggle all this in virtual form, and how do you make it presentable? Step forward Jump24’s Ollie Matthews: Operations Manager and avid gaming streamer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons from the gaming world
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Finpaul9j17hjsllqvqzb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Finpaul9j17hjsllqvqzb.jpg" alt="Photo of our streaming setup" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multiple input sources to create a slick streaming platform, you say? Well, it came as no surprise that professional gamers have had this mastered for quite some time. Ollie outlined the equipment needed, so here’s how we built the home studio for streaming:&lt;/p&gt;

&lt;h2&gt;
  
  
  The office streaming setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Macbook Pro 2016 (Touchbar)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://everymac.com/systems/apple/macbook_pro/specs/macbook-pro-core-i9-2.3-eight-core-15-mid-2019-touch-bar-specs.html"&gt;https://everymac.com/systems/apple/macbook_pro/specs/macbook-pro-core-i9-2.3-eight-core-15-mid-2019-touch-bar-specs.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the field of web application development, particularly in the realms of PHP, Javascript/Node and Ruby, the dominant Operating System on a user level tends to be skewed towards macOS. We use Macs for developing in Laravel, so it’s worth noting that our experience in putting together a streaming setup is already going to differ from the gaming world, where Windows is by far the dominant platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elgato Stream Deck
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.elgato.com/en/gaming/stream-deck"&gt;https://www.elgato.com/en/gaming/stream-deck&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnh8hmb8cyyt8aaporzop.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnh8hmb8cyyt8aaporzop.jpg" alt="Photo of our Stream Deck" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elgato’s Steam deck is really the keystone feature of the setup – the ability to create a custom setup that can control lighting, desktop applications (so this tackled the quick switch between terminal, IDE, Firefox and Google Slides on Chromium), Twitch, and OBS (in particular scenes &amp;amp; transitions) is a gamechanger. This bit of kit is no stranger to the gaming world: streamers use it regularly for Twitch (and other socials integration such as Twitter), recording and scene control. Elgato has recently opened up the button marketplace, adding new control sets such as integration for VSCode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elgato Key Light
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.elgato.com/en/gaming/key-light"&gt;https://www.elgato.com/en/gaming/key-light&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr75xtzksz8jt8j53r0ej.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr75xtzksz8jt8j53r0ej.jpg" alt="Photo of our Key Light" width="768" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite many people’s beliefs, lighting is one of, if not the most important part of any streaming setup. So, the next thing we went for in the Elgato family is the Key light. Yes, this may seem a little expensive compared to other LED panels or ring lights but this particular light seamlessly integrates into the rest of our setup – including the Stream Deck.&lt;/p&gt;

&lt;p&gt;With its sleek design it can fit into any space or desk setup, and hooking it up to your PC via wifi allows you to tweak the brightness and temperature to best suit your needs.&lt;/p&gt;

&lt;p&gt;Despite the premium nature of this product, the setup wasn’t all plain sailing. The Key Light requires a 2.4ghz banded Wifi and doesn’t work with 5ghz. I have a dual band router, so when I switched on 2.4ghz it firstly had a weak signal despite not being far away (common with poor routers dished out by providers). Secondly, my new TV fights with the Key Light over who gets to be connected to the network.&lt;/p&gt;

&lt;p&gt;For more advanced colour options, you might want to consider the Elgato Ring Light, but still has the same potential burden regarding control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rode NT-USB with boom or Elgato Wave:3
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.rode.com/microphones/nt-usb"&gt;https://www.rode.com/microphones/nt-usb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elgato.com/en/wave-3"&gt;https://www.elgato.com/en/wave-3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgw8npf3xaluzff3qnm48.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgw8npf3xaluzff3qnm48.jpg" alt="Photo of our Elgato Wave 3" width="768" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally I’d purchased the Blue Yeti on the back of many recommendations, but it shipped broken. Rode’s USB mic might not have the multi pattern recording modes that the Yeti does, but it does come with a decent pop filter and reasonable price tag. In the office setup we use the Elgato Wave:3 with a boom and filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logitech Streamcam
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.logitech.com/en-gb/products/webcams/streamcam.960-001281.html"&gt;https://www.logitech.com/en-gb/products/webcams/streamcam.960-001281.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjvwzuqdd1zyoxq4p8xq0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjvwzuqdd1zyoxq4p8xq0.jpg" alt="Photo of our Streamcam" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choices for HD streaming are vast, and so sifting through the pages of 1080p cameras can be daunting. The important bit here is to answer the glaring question: “do I need a 1080 webcam?”. Well, what we wanted at Jump24 was as professional a setup as we could get, which included a 1080 cam. However, it’s worth pointing out that if your scenes are mostly a small corner box with a slide deck taking centre stage (or on a live demo like ours – a terminal, browser etc.) then realistically any cam will likely be sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elgato Green Screen
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.elgato.com/en/gaming/green-screen"&gt;https://www.elgato.com/en/gaming/green-screen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is something new we have added to our setup but yet to implement. Using a green screen will allow us to expand our Overlay options when doing events, from branded backdrops, animations to simply removing a messy background. &lt;/p&gt;

&lt;p&gt;A green screen can be something that eliminates issues; add a chrome key filter in your broadcasting app of choice and, just like magic: the background has disappeared.&lt;/p&gt;

&lt;h3&gt;
  
  
  OBS Studio
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://obsproject.com/"&gt;https://obsproject.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open Broadcaster Studio has been at the forefront of game streaming for at least five years. It’s ability to take almost any media input and generate an output for streaming, and for free as Open Source Software makes it an industry standard of sorts. There are disadvantages, however – the majority of its users tend to be on Windows platforms, so if you’re using the MacOS or Linux ports it can be a little more buggy. In order to hook up OBS to various hosting platforms where no integration with OBS is possible, it needs the ‘Virtual Camera’ feature, that will take the OBS output and pipe it into a virtual device. The likelihood is that if you are in control of your stream, you can hook up OBS to YouTube or Twitch with API keys directly and thus won’t need to use the Virtual Camera, but when you are being hosted and control is out of your hands it will be needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Being Hosted: your meetup’s tech stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zoom / Skype
&lt;/h3&gt;

&lt;p&gt;Zoom capitalised on their new found advantage by offering unlimited free tier calls. It’s probably not that much of a surprise then that Zoom seems to have become the default. I’ve done the talk a couple of times now on Zoom with OBS’s Virtual Camera output and not found any issues with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jitsi
&lt;/h3&gt;

&lt;p&gt;Jitsi would absolutely not play ball with the OBS Virtual camera output – problems included output resolution and “flipping” the output image. What made Jitsi unusable for us, however, is that there is a tendency for meetups using it to have the free tier (for understandable reasons). Unlike the resource Zoom has to throw at free tier usage, it was clear that the servers were heavily throttling the connection. That’s not a problem if you’re doing a brief meeting, but presenting and pulling down docker containers? Nope.&lt;/p&gt;

&lt;h3&gt;
  
  
  Streamyard
&lt;/h3&gt;

&lt;p&gt;Streamyard is a popular option, and from a speakers’ perspective has decent features: a backstage broadcasting area and a screenshare perspective that takes care of the scene layout for you. There is, however, a disadvantage to this (as we discovered) in that you can’t use OBS’s virtual camera output. The image resolution is cropped awkwardly, but more importantly with OBS you’re trying to replicate a feature that Streamyard is designed for. This is where there’s a big difference in Streamyard between speaking and hosting: as a speaker, you don’t have control whereas when hosting you can include backdrops with branding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkif1rjugg1tr1zctkpg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkif1rjugg1tr1zctkpg3.png" alt="Jitsi, Zoom and Streamyard logos" width="763" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting: Tech stack options with Kevin Lewis
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwt7h7gm5kwwpffyvl28i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwt7h7gm5kwwpffyvl28i.png" alt="Preview of Jump24 tweet about forthcoming events" width="585" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, we’ve covered being the speaker in virtual meetups, but what about hosting your own? Before COVID hit, we were planning to launch a new tech, art &amp;amp; culture event in the city, BrumTech Tapas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvwxzps2dcwk5n3jk6yti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvwxzps2dcwk5n3jk6yti.png" alt="BrumTechTapas design banner" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the switch to virtual, we needed to think about our options from an organisers’ view. Rather than go into this foray blindly, I spoke to Vonage’s &lt;a href="https://twitter.com/_phzn"&gt;Kevin Lewis&lt;/a&gt;, whom I knew had a mountain of experience in this area due to his events work with the &lt;em&gt;You Got This Conference&lt;/em&gt; Series, &lt;em&gt;Women of React&lt;/em&gt; and &lt;em&gt;Vonage’s Developer Day&lt;/em&gt;.&lt;/p&gt;




&lt;p&gt;Online events provide some really exciting opportunities to build experiences that just wouldn’t be possible in a physical space, for the affordances that tech brings. When organizing events, you can try and emulate offline events complete with networking setups, work towards an Apple WWDC-style highly-produced live TV show, or create more novel experiences such as Roguelike Celebration. &lt;/p&gt;

&lt;p&gt;When choosing your setup, there are five core considerations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Complexity of Operation – how confident is your team to use more complex tooling?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creative Flexibility – how customized do you need the output to be? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moderation Bandwidth – how much people-power do you have for moderation, and how does the choice of platforms impact this?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attendee Experience – what is an ideal experience for attendees? Do you want to facilitate networking? Should it all be in one platform?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Speaker Experience – how involved or complex can your speaker experience be while still being appropriate for who you have invited?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some of these items are inextricably linked – having more creative flexibility is likely to increase complexity, for example. &lt;/p&gt;

&lt;p&gt;My first full-scale online conference was Women of React back in April. We used Skype (with NDI) and OBS for managing the stream, YouTube for hosting the stream and Discord for community interactions. We got a really lovely set of custom scenes and full control over what was seen or heard, but it was a pain to keep on top of. The speakers and MC had to really work through all of the technical quirks (which they did fantastically), but it was difficult. &lt;/p&gt;

&lt;p&gt;Using a video call, piping data into OBS via the NDI protocol and pushing out a completed stream to your host means your one device will be doing lots of computationally-expensive operations, and if it fails to deliver the whole event will suffer. There are contingencies to this – such as renting a more powerful cloud-hosted machine and completing the work on it, but this comes at an additional cost and setup time.&lt;/p&gt;

&lt;p&gt;My team at Vonage chose to use a platform called Remo for Vonage Developer Day – which has a networking component aiming to emulate offline events. Attendees can gather and move around tables – each a small video call between groups. &lt;/p&gt;

&lt;p&gt;Through all the events I’ve run, I still believe Streamyard provides the best overall setup for publishing livestreams. While you are creatively limited to just the 7 pre-set layouts provided, they are designed with care and almost every use case in mind. &lt;/p&gt;

&lt;p&gt;Also consider the need for networking in the long, long year that is 2020. I am a fan of giving people spaces to meet, but nothing will replace being in the same room. Many folks have screen fatigue, and many will be motivated only by consuming the organized content. Consider if this is true in your community and whether you can place somewhat-forced networking efforts aside for a happier time. &lt;/p&gt;

&lt;p&gt;If you want to find out more about the considerations and outcomes around Women of React, Vonage Developer Day and You Got This From Your Couch – you can &lt;a href="https://www.youtube.com/watch?v=56rvtjZ9x3g"&gt;watch my talk&lt;/a&gt; from DevRelCon Earth earlier this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Branding – design considerations
&lt;/h2&gt;

&lt;p&gt;The new branding for Brum Tech Tapas along with the website had just been completed before we went into the first lockdown. The idea was to keep it simple and not focus solely on the tech community. A lot of this was achieved by building the website and the photography we used to represent the diverse cultural scene in Birmingham. &lt;/p&gt;

&lt;p&gt;The next design aspect we had to tackle was moving the talks over to Twitch. Something as designers we had no experience in. We started taking a look at other Twitch coder accounts and noticed that the aesthetics weren’t always a priority, something we wanted to avoid. As this was something relatively new for tech talks in Birmingham we wanted to make sure we put our best foot forward, using our branding to create something aesthetically pleasing whilst allowing for multiple speakers to be shown and live coding to be clear and visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual means more accessible options
&lt;/h2&gt;

&lt;p&gt;The equipment we put together and time invested in designs etc. comes at a cost. The decisions that we made are based on the notion that you don’t have to invest much to get a polished, professional setup that looks no different from international tech firms’ branding and content delivery.&lt;/p&gt;

&lt;p&gt;While that’s certainly the conclusion for what we were looking for, it’s important to bear in mind that to speak at a meetup or to host one, you technically don’t need any of this. This is vital to know if you’re starting out speaking and need some exposure, or you’re booting up a new usergroup (or transitioning online for the first time). All you actually need is an internet connection, a webcam and people to join. As with most things, the end goals of what you want to achieve dictate the requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual meetups and conferences: advantages and disadvantages
&lt;/h2&gt;

&lt;p&gt;So, given that we’ve gone through planning, let’s have a bit of a postmortem on the key things to think about when it comes to running virtual tech events. As we approach tech events from a Developer Relations perspective – raising awareness of our work and doing developer outreach for education, it’s now very apparent what can run smoothly and what snagging points you can encounter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Speaker Pools
&lt;/h4&gt;

&lt;p&gt;The rules have now been redefined – you can officially contact someone elsewhere on the planet and ask if they want to speak at your meetup. It’s worth noting that, while there is an element of truth to that sentence, many of the meetups I have spoken at have very much stuck to a pool of speakers already within their network. While it might have potentially opened more doors to speakers, it’s also worth considering that it doesn’t give you an immediate ‘yes’ from everyone.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cost
&lt;/h4&gt;

&lt;p&gt;The cost of what you’re looking at has pretty much been outlined in the article. In-person meetups require spaces, the oh-so-stereotypical “Pizza for 30 developers” and drinks sponsorships. If you’ve got a fancier meetup, you might have catering. The cost of running a meetup can be £0 if you want it to be; even the price of a conference is suddenly astonishingly low considering the speakers you might have been able to virtually pull in.&lt;/p&gt;

&lt;h4&gt;
  
  
  Potential Reach
&lt;/h4&gt;

&lt;p&gt;The point of a local usergroup is that you form smaller communities around common themes – the convenience of opening it up without a physical form means that your attendance might well spike. In the usergroups we’ve spoken at on our current talk, it’s noticeable how the attendance is actually higher. In the PHP world this does however have a drawback – one of the reasons you’ll see more one some of the events is because PHP developers are aware of other local usergroups. There is a scenario playing out right now that we’ve seen. A point Raised by one of the usergroups we spoke at stated that the same talks are going round the circuit and thus someone from Bristol might not want to watch a talk on at PHPSW: because they already saw it at PHPMiNDS in Nottingham.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhe2g3e5lqioqdxejbjuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhe2g3e5lqioqdxejbjuw.png" alt="Cartoon by Tom Fishburne on standard Zoom meeting nightmares" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Loss of 1-2-1 interaction
&lt;/h4&gt;

&lt;p&gt;Developer Relations still thrives on in-person 1-2-1 interactions – from my experience personally this is still the best way to network and create a hub of people with similar interests to get feedback and opinions off. Without that, the hardest part of expanding your network has pretty much gone. Yes, in speaking to event organisers, recreating this part of outreach has been attempted, but as of yet not many that I’ve spoken to have reported a successful method for doing it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Internet speeds
&lt;/h4&gt;

&lt;p&gt;This one stands out by a country mile. If COVID has shown us anything, it’s how reliant in the tech world we are for the Internet for software development beyond the obvious limitations of CI pipelines and Docker pulls. &lt;/p&gt;

&lt;p&gt;Your speaker’s connection goes down 5 hours before the event because someone drilled through a pipe. Your speaker’s connection goes down during the event while speaking because geese have attacked the exchange. What do you do?&lt;/p&gt;

&lt;p&gt;That’s only from the speakers’ perspective. During the tour of our current talk, my internet speed was fairly poor, and an unexpected need to pull an nginx container resulted in my best Minecraft look. But what if you encounter this when you’re on StreamYard and hosting the whole event? Well, then you’ve not really got any options. But you can prepare by making sure you host from a high speed connection, especially if you have speakers from across the globe, and especially if they’re not in the standard Western world tech bubble.&lt;/p&gt;

&lt;h4&gt;
  
  
  The curse of remote working
&lt;/h4&gt;

&lt;p&gt;This is one of the biggest issues with moving virtual. You’ve just spent eight hours of your day on Zoom calls, JIRA and your IDE open in front of you, barely moving apart from the get the occasional coffee which is also now done in silence.&lt;/p&gt;

&lt;p&gt;Come 6:30pm, is opening up a Zoom call with 30 people in to have a virtual tech talk (that, in some cases, is being recorded and will be available at any point in the future you choose anyway) really how you want to spend your evening?&lt;/p&gt;

&lt;h4&gt;
  
  
  Losing outreach: Slack/Discord
&lt;/h4&gt;

&lt;p&gt;This is Developer Relations. Marketing people might well not see the problem with throwing out “for discussions, sign up to our Slack/Discord!”, but we know the pain of being told for the 10th time in a month to sign into a new social media platform for one event that will be used once.&lt;/p&gt;

&lt;p&gt;This particular subject has been covered recently by &lt;a href="https://twitter.com/jna_sh"&gt;Joe Nash&lt;/a&gt;, offering to open up discussions as to why &lt;em&gt;Let’s Just Create a New Slack&lt;/em&gt; really isn’t the one-size-fits-all solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgik66mw5qe0nht33uua3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgik66mw5qe0nht33uua3.png" alt="Screenshot Joe Nash's Twitter feed saying please don't create another slack" width="591" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://twitter.com/jna_sh/status/1326514552251568130"&gt;https://twitter.com/jna_sh/status/1326514552251568130&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more fitting options, specifically around the biggest sticking point of live feedback/community comms – moderation – check out Joe’s tweets and subsequent discussions on why certain platforms have advantages over Slack. What’s interesting is that Discord comes up time and time again in conversations – another crossover from the gaming world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: A more versatile outreach
&lt;/h2&gt;

&lt;p&gt;So, what are the results of what we did? Well, like most people I expect, we’re ready for physical events again for sure. But for now, I’ll put it this way: we’re now equipped and experienced in hosting and delivering virtual content. This is something we certainly couldn’t do before, and besides: without the COVID crisis many large tech companies did have the ability to create content in this way. So, by preparing for virtual content and calling in advice across disciplines both internally and externally – Jump24 has a far more versatile outreach capability. Which, after all, is the point of Developer Relations, isn’t it?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With thanks to Ollie Matthews, Anneka Mistry, Kevin Lewis and Joe Nash.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>PsySh - More than just REPL</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Fri, 28 Aug 2020 15:26:43 +0000</pubDate>
      <link>https://dev.to/secondej/psysh-more-than-just-repl-3cek</link>
      <guid>https://dev.to/secondej/psysh-more-than-just-repl-3cek</guid>
      <description>&lt;p&gt;Most backend developers know about interactive modes, that certainly isn’t a secret.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jimseconde@jim-amd-u18$: php -a&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;jimseconde@jim-amd-u18$: node&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;p&gt;&lt;code&gt;jimseconde@jim-amd-u18$: python3&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;All give you an active interpreter for that respective language. It’s used mostly for testing or confirming behaviour on the fly - ironically because you have a mountain of code in the middle of your app, your linter isn’t picking up on anything suspicious and exceptions are being thrown where you don’t want. Perhaps you want to look at how something is type juggling instead - again, your linter can’t help you with that.&lt;/p&gt;

&lt;h5&gt;
  
  
  PHP
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: php -a
&amp;gt; $foo = '342';
&amp;gt; $bar = 'give me a string';
&amp;gt; var_dump($foo + $bar);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Node
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: node
&amp;gt; console.log(234 / 3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Python3
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: python3
&amp;gt; print('give me a string' . 3424)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While an active interpreter is useful, it has one major limitation: it’s the standard &lt;br&gt;
library of functions of a language, not a framework or your whole application's code.&lt;br&gt;
So we’d have to import anything we want to test line by line:&lt;/p&gt;
&lt;h5&gt;
  
  
  Node
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: node
&amp;gt; barkNoise = 'woof'
&amp;gt; console.log(bark(barkNoise))
ReferenceError: bark is not defined
&amp;gt; import { bark } from './app/some_functions/myFunctions.js'
&amp;gt; console.log(bark(barkNoise))
woof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  PHP: How PSR-4 &amp;amp; Composer changed how we code in PHP
&lt;/h4&gt;

&lt;p&gt;While it looks like a daunting name, PSR-4 is just the specification for how code is structured, &lt;br&gt;
allowing a modular component system in your php app. At runtime, composer uses an autoloader &lt;br&gt;
system to get every class you’ve got in your app and loads it into that php thread in memory. &lt;br&gt;
This is why when you code something in, for example, &lt;a href="https://www.slimframework.com"&gt;Slim&lt;/a&gt;, &lt;a href="https://laravel.com"&gt;Laravel&lt;/a&gt; or &lt;a href="https://symfony.com"&gt;Symfony&lt;/a&gt;, you can use an &lt;br&gt;
import to get a class from -somewhere else- in your app, and because of autoloading, it’s &lt;br&gt;
available during runtime.&lt;/p&gt;
&lt;h4&gt;
  
  
  From PHP interactive shell to PsySh
&lt;/h4&gt;

&lt;p&gt;We’ve already established that &lt;code&gt;php -a&lt;/code&gt; just spins up a raw shell. But - what if we &lt;br&gt;
could spin up a shell that uses composer’s autoloader to throw the whole app into memory, &lt;br&gt;
then gives you your command line? If you did that, every single class and all the &lt;br&gt;
functionality of your app sudden becomes available!&lt;/p&gt;

&lt;p&gt;This is exactly what PsySh does. In &lt;a href="https://symfony.com"&gt;Symfony&lt;/a&gt; or &lt;a href="https://www.slimframework.com"&gt;Slim&lt;/a&gt;, you can get it using composer: &lt;br&gt;
&lt;code&gt;composer require psy/psysh&lt;/code&gt;. In &lt;a href="https://laravel.com"&gt;Laravel&lt;/a&gt;, a version of it comes out of the box, named &lt;code&gt;tinker&lt;/code&gt;. &lt;br&gt;
You can fire it up using &lt;code&gt;php artisan tinker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's also worth noting that in tinker, not only has composer autoloaded every class, it's also fired Laravel's entry point to the app, including all of the bootstrapped features - so, features like the Service Container and Config are available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: php artisan tinker
&amp;gt;&amp;gt;&amp;gt; config('app.my_awesome_variable');
&amp;gt;&amp;gt;&amp;gt; $myPusherService = app()-&amp;gt;make('PusherService');
&amp;gt;&amp;gt;&amp;gt; $myPusherService-&amp;gt;pushToQueue(['send me']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  More than debugging: 4 use cases
&lt;/h4&gt;

&lt;p&gt;PsySh is usually described as a debugger, but I’d say it’s a lot more powerful than that. Let’s &lt;br&gt;
have a look at four areas it can be used to interact with our apps:&lt;/p&gt;
&lt;h5&gt;
  
  
  Shopify API library
&lt;/h5&gt;

&lt;p&gt;In previous blog posts, &lt;a href="https://devtheatre.net/blog/shopify-laravel"&gt;I've written how to use composer to get a REST API wrapper.&lt;/a&gt;.&lt;br&gt;
The wrapper is used to fetch and push whatever your app requires &lt;br&gt;
in its business logic to interact with a Shopify store (in this case). It’s baked into your app’s code though, &lt;br&gt;
so using something like &lt;a href="https://www.getpostman.com"&gt;Postman&lt;/a&gt; or &lt;a href="https://insomnia.rest"&gt;Insomnia&lt;/a&gt; to manually query the API would be better suited for &lt;br&gt;
quick queries. With PsySh though, the API is now -just available-. Even better, you may&lt;br&gt;
 have extended the API wrapper with bespoke functionality - now that’s available too. 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;jimseconde@jim-amd-u18$: php artisan tinker
&amp;gt;&amp;gt;&amp;gt; $api = new \EastsideCo\Shopify();
&amp;gt;&amp;gt;&amp;gt; $shopifyProduct = $api-&amp;gt;get('admin/products/324235.json')-&amp;gt;products;
&amp;gt;&amp;gt;&amp;gt; $localProduct = new \App\Product::create($shopifyProduct);
&amp;gt;&amp;gt;&amp;gt; $localProduct-&amp;gt;save();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice that PsySh also gives you interactive feedback. If you call the Eloquent &lt;code&gt;save()&lt;/code&gt; function for instance,&lt;br&gt;
as long as the entity passes validation, it will return and print true below. In the case of an API response or the&lt;br&gt;
result of a database query, it'll return and print a json array of the response, even if it's been set to a variable.&lt;/p&gt;

&lt;p&gt;Your API class instance is generated the same way it would have been if &lt;br&gt;
you were running the whole application at runtime (because, as everything has been &lt;br&gt;
loaded in PsySh, technically this is exactly what has happened). So, whatever custom &lt;br&gt;
methods you’ve coded are now available - 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;&amp;gt;&amp;gt;&amp;gt; $blogPayload = ['09012938','My new blog post'];
&amp;gt;&amp;gt;&amp;gt; \App\API::createBlogPost($blogPayload);
true
&amp;gt;&amp;gt;&amp;gt; $api-&amp;gt;fetchImagesByVariantId('90812309')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Laravel’s Eloquent ORM interaction
&lt;/h5&gt;

&lt;p&gt;The main usage you’ll see of Laravel’s inclusion of PsySh is in the ORM documentation, and &lt;br&gt;
it’s a good example of where it’s extremely powerful. With &lt;br&gt;
the ORM loaded completely into your command line, you can use any extended &lt;br&gt;
custom functionality you’ve built into your ORM and test it. &lt;br&gt;
This now effectively completely removes the need to access &lt;br&gt;
your database’s command line - you can even write raw SQL &lt;br&gt;
into the ORM and run that.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jimseconde@jim-amd-u18$: php artisan tinker
&amp;gt;&amp;gt;&amp;gt; \DB::select(SELECT * FROM products WHERE id = 4)-&amp;gt;get();
&amp;gt;&amp;gt;&amp;gt; \App\Product::find(342)
&amp;gt;&amp;gt;&amp;gt; \App\Variants::where('sku', 'like', 'TABLE1')-&amp;gt;get();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Laravel’s Storage driver
&lt;/h5&gt;

&lt;p&gt;Here’s another example of where PsySh can be really powerful. &lt;br&gt;
Every Laravel class that comes with the Framework is now available - so, let’s &lt;br&gt;
take the File Storage system that is built on top of the powerful &lt;a href="https://flysystem.thephpleague.com/docs"&gt;Flysystem&lt;/a&gt; PHP library. &lt;br&gt;
Let’s imagine you need to extract a specific SQL query for data analysis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; $dataQuery = \DB::('SELECT a.id, a.title, b.title, b.price, b.sku from products a INNER JOIN variants b on a.id = b.product_id')-&amp;gt;get();
&amp;gt;&amp;gt;&amp;gt; // $dataQuery is a select query returned as a .json
&amp;gt;&amp;gt;&amp;gt; // dump out the data to the storage path
&amp;gt;&amp;gt;&amp;gt; \Storage::disk('local')-&amp;gt;put('datadump.json', $dataQuery);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On your server, your query result json is now written to &lt;code&gt;/storage/app&lt;/code&gt; &lt;br&gt;
(if you’ve still using the defaults, otherwise it will be written to the &lt;br&gt;
configured path for the local driver). &lt;/p&gt;

&lt;p&gt;We’ve just the local driver here, but if you want to you can use any of &lt;br&gt;
the other drivers - such as the AWS S3 one. Want to send the same&lt;br&gt;
 payload into an S3 bucket? Sure!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; \Storage::disk('s3')-&amp;gt;put('datadump.json', $dataQuery);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Dispatching Jobs or Events
&lt;/h5&gt;

&lt;p&gt;If your app makes extensive use of the Job queue system (currently&lt;br&gt;
I use AWS’s SQS messaging system for Job queues, and use &lt;a href="https://redis.io"&gt;Redis&lt;/a&gt; for broadcasting &lt;br&gt;
events over websockets) or has a more a complex Event-driven architecture system, &lt;br&gt;
you can use PsySh to do routine maintenance or to debug the application structure. &lt;br&gt;
Here’s an example of fetching an order by the API, then firing an event to the queue listeners:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; $orderToCancel = $api-&amp;gt;get('admin/orders/32448.json');
&amp;gt;&amp;gt;&amp;gt; // fire event to the queue to cancel the job
&amp;gt;&amp;gt;&amp;gt; Event::dispatch(new CancelOrderJob($orderToCancel));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've found the power of an interactive shell like this to be invaluable in day-to-day operations. For more&lt;br&gt;
information on PsySh and tinker, check out the docs and repos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://psysh.org/"&gt;https://psysh.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bobthecow/psysh"&gt;https://github.com/bobthecow/psysh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/laravel/tinker"&gt;https://github.com/laravel/tinker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To see an example of the same kind of enhanced REPL power outside of PHP, I recommend having a look at how Python's &lt;a href="https://www.djangoproject.com"&gt;Django&lt;/a&gt; implements the same patterns using &lt;code&gt;./manage.py shell_plus --ipython&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Happy shelling!&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>symfony</category>
      <category>debugging</category>
    </item>
    <item>
      <title>A Fifth Pillar of Developer Relations</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Mon, 24 Aug 2020 08:16:53 +0000</pubDate>
      <link>https://dev.to/secondej/a-fifth-pillar-of-developer-relations-44fd</link>
      <guid>https://dev.to/secondej/a-fifth-pillar-of-developer-relations-44fd</guid>
      <description>&lt;p&gt;I don't think anyone could have predicted how bad 2020 would end up, but it certainly brought to light some thinking about how I'd like Developer Relations to change.&lt;/p&gt;

&lt;p&gt;There is a specific reason for writing this article, but I realised that the topic it covered went a lot deeper, and exposes new trends in tech while raising some fairly important questions to consider both in Developer Relations and Web Development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hooray for Hugo
&lt;/h3&gt;

&lt;p&gt;So, the original reason for writing this is that returning visitors might have noticed a shiny new &lt;a href="https://devtheatre.net/blog/"&gt;Dev Theatre&lt;/a&gt; site. It's written in &lt;a href="https://gohugo.io"&gt;Hugo&lt;/a&gt;, using the fantastically functional and beautiful theme &lt;code&gt;hugo-future-imperfect-slim&lt;/code&gt;. To give a slight bit of gushing for the tech: I LOVE this JAMStack. Golang compiles this site at lightning speed - at least five times faster than what was a rather over-engineered Gatsby codebase. I've found it to be a hugely positive experience, at a time when there have been few positives, so let's get this out of the way:&lt;/p&gt;

&lt;h3&gt;
  
  
  Gatsby
&lt;/h3&gt;

&lt;p&gt;The reason the site is migrated is the whistle-blowing from a contractor on the running of &lt;a href="https://www.gatsbyjs.com"&gt;Gatsby&lt;/a&gt; as a company. You can find this &lt;a href="https://twitter.com/tesseralis/status/1293649007739191296"&gt;here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, OK: companies can be badly run, it happens. But what was it about this incident that made it any different, for me at least?&lt;/p&gt;

&lt;p&gt;In the Bay Area, startups are regularly going from a CEO founder and co-founding CTO one minute, to whispering the word "blockchain" out into the Venture Capital Wild West to be rewarded with millions of dollars in other people's cash. The company somehow scales to having 100 employees, maybe some scattered around the globe remote, hiring extremely expensive DevRel with what seems like a roll of the dice when it comes to how that scaling has been structured. From this perspective, Gatsby scored the right technologies at the right time, securing its name as &lt;strong&gt;the&lt;/strong&gt; React JAMStack and massively scaling as a result. The whistleblower in this case identifies a host of problems that come with the disorganisation that brings, but arguably the most damage was done with the response. The response is what made me realise that there are some topics to consider when you're involved in Developer Relations, and Gatsby serves as fairly good case study.&lt;/p&gt;

&lt;p&gt;Here is the response from Gatsby CEO Kyle Matthews:&lt;br&gt;
&lt;a href="https://twitter.com/kylemathews/status/1294006966310731776"&gt;https://twitter.com/kylemathews/status/1294006966310731776&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm always fascinated with the response companies and/or individuals concoct when faced with a major PR crisis. There is a tendency for Politicians, for instance, to give spectacular insights into their lack of self awareness by either doubling down or responding with something utterly moronic that they think people will swallow at face value.&lt;/p&gt;

&lt;p&gt;So in this case, with Gatsby, you'd have &lt;em&gt;thought&lt;/em&gt; that the alarm bells went off at GatsbyHQ, and the board would push the button to get a Public Relations consultancy to handle the hot potato.&lt;/p&gt;

&lt;p&gt;What actually happened was the CEO put out a statement saying, to words of this effect: "We are sorry that you feel offended, running this business is hard, we're launching a Cloud Product soon by the way, we are not actually going to do anything about the points raised because we don't care".&lt;/p&gt;

&lt;h3&gt;
  
  
  PR Damage is administered
&lt;/h3&gt;

&lt;p&gt;I wonder what effect Gatsby thought it would have? Realistically, what happened next was painfully predictable. End users on Twitter started discussing migrating from Gatsby to other technologies immediately (including me). Sounds harmless (what impact could I have, just being the end user of an Open Source framework?) but coupled with the aforementioned impending launch of Gatsby Cloud, one of it's first commercial products suddenly potentially lost a massive chunk of it's users, ergo it's revenue. Elsewhere, major influencers in the worlds of Developer Relations, DevOps, Javascript, InfoSec/DevSecOps - you name it - were quick to fire ridicule on the handling of it all.&lt;/p&gt;

&lt;h3&gt;
  
  
  2020: a year of confusion
&lt;/h3&gt;

&lt;p&gt;The Gatsby fallout is really just another tech botch to add to what has been a year of upheaval. We've had companies slow to act on COVID-19 (including in the DevRel space, companies that I shall leave nameless hiring in the middle of the pandemic with the requirement to be based in the Bay Area only, so presumably you start remote in San Francisco but when this all blows over you have to be on site which makes &lt;em&gt;absolutely no sense&lt;/em&gt;), we've had a deluge of companies completely at odds about what "to do" about Black Lives Matter (the most baffling probably being &lt;strong&gt;TeeSpring&lt;/strong&gt; pulling ANTIFA T-shirts because they're political, while continuing to sell QAnon and other far Right Wing stuff like White Pride merchandise which presumably doesn't qualify). &lt;/p&gt;

&lt;p&gt;We also had the attempted launch of "&lt;strong&gt;Genderify&lt;/strong&gt;", a seemingly pointless API that would attempt to guess your binary gender based on a name. One user was quick to point out that they were identifed as female, until they added "Dr" as a prefix, at which point it regendered them male. When challenged on this, the developers completely washed their hands of it and said it was simply the data doing the talking, not their product. Genderify not surprisingly didn't last long, presumably sinking with a wad of Ventre Capital money flushed down the toilet.&lt;/p&gt;

&lt;p&gt;On a similar front in product, we had one of &lt;strong&gt;Intercom&lt;/strong&gt;'s Product owners vomiting out an outrageous display of bravado on Twitter for a launch aimed directly at a competitor, Zendesk, about how terrible their product is and how amazing Intercom's was. This misplaced chunk of my-Dad-is-bigger-than-yours was at least correctly handled by Intercom, who pulled the thread and apologised for getting the tone wrong.&lt;/p&gt;

&lt;p&gt;In the Developer Relations space, &lt;strong&gt;Google&lt;/strong&gt; decided to hide when one of it's Advocates blew the whistle on a harrowing description of violent abuse at the hands of one of their other employees, presumably (at first) deemed too important to immediately fire.&lt;/p&gt;

&lt;p&gt;Local to my tech ecosystem haunts, the &lt;strong&gt;Laravel&lt;/strong&gt; framework found some new heroes in the form of the &lt;a href="https://www.larabelles.com"&gt;Larabelles&lt;/a&gt; usergroup, which was shot down by a load of predicable "replyguy" responses asking why there was a need for women to have their own usergroup, while seemingly unaware that the very nature of what they were doing was answering their own question. There has been a string of these recently, which in context this year isn't particularly more than any other year going back to the dawn of software development, but it still irks. One of the points given to me by &lt;a href="https://twitter.com/michellesanver"&gt;Michelle Sanver&lt;/a&gt;, former President of PHPWomen raised was that these sorts of things are becoming more prominent as women and LGBT developers are now more confident to speak out against such bigotry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Relations and PR as a fifth pillar
&lt;/h3&gt;

&lt;p&gt;So, all of this raises an important feature of DevRel that I've not actually seen discussed at great length: PR. There are &lt;a href="https://devrel.net/strategy-and-metrics/the-four-pillars-of-developer-relations"&gt;"Four pillars" of DevRel&lt;/a&gt; commonly cited, identified by Matthew Revell's Hoopy consultancy in April 2019. These are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Outreach&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Community&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Education &amp;amp; Support&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What these incidents are bringing to light is that Developer Relations practitioners are, in most cases, the face of the company they work for, and that is a &lt;em&gt;big&lt;/em&gt; responsibility. There is harmony on both sides when it comes to DevRel - the company have their role representing them on stage at conferences and meetups, while experienced Developer Advocates have become massive influencers within the world of software development, and use that to promote the company.&lt;/p&gt;

&lt;p&gt;Take, for instance, the approach of how Developer Advocates are presented in &lt;a href="https://twitter.com/mary_grace"&gt;Mary Thengvall&lt;/a&gt;'s DevRel Bible, "&lt;a href="https://www.amazon.co.uk/Business-Value-Developer-Relations-Communities/dp/1484237471/ref=sxts_sxwds-bia-wc-p13n1_0?crid=COMGI4AQQWVR&amp;amp;cv_ct_cx=the+business+value+of+developer+relations&amp;amp;dchild=1&amp;amp;keywords=the+business+value+of+developer+relations&amp;amp;pd_rd_i=1484237471&amp;amp;pd_rd_r=15180c46-5d57-42e2-b085-1d4c3785a9d1&amp;amp;pd_rd_w=2U0Zn&amp;amp;pd_rd_wg=CBh4K&amp;amp;pf_rd_p=9b1a9511-9af9-4d06-8643-d54ebec511ef&amp;amp;pf_rd_r=5TJR2SGRW4BCVJM2PQKT&amp;amp;psc=1&amp;amp;qid=1598194024&amp;amp;sprefix=the+business+value+of+%2Caps%2C200&amp;amp;sr=1-1-fdbae751-0fa5-4c0f-900b-865654896618"&gt;The Business Value of Developer Relations: How and Why Technical Communities Are Key To Your Success&lt;/a&gt;". It presents, on the cover, illustrated likenesses of leading figures in DevRel who are interviewed in the book. The superstars appear to be us - that's how much influence we're supposed to be wielding. &lt;/p&gt;

&lt;p&gt;I can give you a personal example of this in action - take, for instance, &lt;a href="https://cassidoo.co"&gt;Cassidy Williams&lt;/a&gt; moving to &lt;a href="https://www.netlify.com"&gt;Netlify&lt;/a&gt;. Her trademark humour started to be teased out of the Netlify corporate Twitter account, and it was clear without announcing it that Cassidy was now using it. She's a well known name in tech, and so personally now I associate Netlify (which hosts this site) with Cassidy, her skills and her humour and openness to being approached for advice. Sometimes Advocates (depending on their roles) are even first line support for a lot of developers they've formed relationships with.&lt;/p&gt;

&lt;p&gt;That is indeed &lt;em&gt;a lot&lt;/em&gt; more power than sometimes we're aware of. If that's the case, we really need a Fifth Pillar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Public Relations&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kindness &amp;amp; Influence for good
&lt;/h3&gt;

&lt;p&gt;We need that pillar in our arsenal of skills because it's a bigger burden to carry than some of us might be aware of. Practitioners of DevRel do &lt;strong&gt;need&lt;/strong&gt; to adhere to the "relations" part of the role, because if we misuse the platform we're building for ourselves then we're not advancing the industry as a whole - which is something that as influencers I believe we have the power to do. Misusing that platform or throwing controversy on top of it doesn't go unnoticed: just ask "Uncle" Bob Martin, Greg Sidelnikov or Richard Stallman.&lt;/p&gt;

&lt;p&gt;At NorDev Conference this year I saw &lt;a href="https://www.youtube.com/watch?v=2a8bSByZ3aE"&gt;Jon Skeet talk on Kindness&lt;/a&gt;, and I believe in Developer Relations empathy is a core skill we really should all have. It goes hand in hand with the responsibility of carrying that Public Relations profile of your employer - there's something less for them to worry about if you carry out your education to other developers with kindness, patience and understanding of others. This goes beyond just patience with others' code skills - we're leading by helping others regardless of race, religion or gender identity at a employer that also understands the same core values that we do. Hopefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  A curriculum
&lt;/h3&gt;

&lt;p&gt;I think what I'd &lt;em&gt;like&lt;/em&gt; to see is PR &lt;em&gt;awareness&lt;/em&gt; as part of DevRel; I'm not stating that we should all be PR experts (we already need to maintain enough skillsets across a broad range), because in DevRel personalities shine through. I'd say we don't want to use PR as a tool to weather storms like companies and politicians do: the objective is the awareness to stop them in the first place.&lt;/p&gt;

&lt;p&gt;How does one go about scoping what that looks like? Well, that I would like to discuss: feel free to hit me up!&lt;/p&gt;

&lt;p&gt;Here's hoping for a kinder 2021.&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>career</category>
    </item>
    <item>
      <title>Turbocharged PHP Development with Xdebug, Docker &amp; PHPStorm.</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Thu, 13 Aug 2020 07:48:59 +0000</pubDate>
      <link>https://dev.to/jump24/turbocharged-php-development-with-xdebug-docker-phpstorm-1n6c</link>
      <guid>https://dev.to/jump24/turbocharged-php-development-with-xdebug-docker-phpstorm-1n6c</guid>
      <description>&lt;h3&gt;
  
  
  It all started out with that oh-so-modern cause of a community backlash: the humble tweet.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.jump24.co.uk%2Fuploads%2F2020%2F08%2Ftweet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.jump24.co.uk%2Fuploads%2F2020%2F08%2Ftweet.png" alt="Derick Trolling people"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://twitter.com/derickr/status/1274134192155131905" rel="noopener noreferrer"&gt;https://twitter.com/derickr/status/1274134192155131905&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quite the controversial “hot-take” from Derick, and while it certainly caused quite the stir (that it was probably designed to), it made me think. I thought, &lt;strong&gt;‘Do I need to revisit Xdebug?’&lt;/strong&gt;, and I realised that I’d fallen into Derick’s trap. But think I did.&lt;/p&gt;

&lt;p&gt;Let’s clear up some existing thoughts I had on Xdebug – some readers might nod in agreement or have/had similar experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Like many PHP developers with significant experience: &lt;strong&gt;I know of Xdebug&lt;/strong&gt;. It’s been around years – I started writing PHP professionally in 2016, by which time Xdebug had existed for 14 years. It’s not like it was some obscure or new tool being talked about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;I’d tried Xdebug before at some point&lt;/strong&gt; – I can’t recall when, and had an experience that left me thinking that understanding what you could do with it would take far too much time up for me to learn. Plus, things like custom “bookmark” browser extensions made it feel like you had to jump through a lot of hoops to use it effectively. A lot has changed since I started – I use Jetbrains PHPStorm as my IDE, and develop with Docker. It was a pain trying to set it up manually before, but what about now, where Xdebug runs a server on an IP, but it will be running in Docker?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://devtheatre.net/blog/psysh/" rel="noopener noreferrer"&gt;I’ve previously written an article&lt;/a&gt; on how superb PsySh is as an application’s command line. Given that when used as part of Laravel’s &lt;code&gt;tinker&lt;/code&gt; it boots up the whole app into a REPL environment, does that render something like Xdebug somewhat redundant?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, but most importantly for developers: why bother when you can use &lt;code&gt;var_dump()&lt;/code&gt; or Symfony’s &lt;code&gt;dump()&lt;/code&gt; or Laravel’s &lt;code&gt;dd()&lt;/code&gt;?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These thoughts of mine were also circulated in others’ replies to the tweet, but it was when Tighten’s Matt Stauffer and Twilio’s Gary Hockin stepped in to offer livestreams with Derick to set it up that I took notice – the resulting content is now excellently documented at &lt;a href="https://learnxdebug.com" rel="noopener noreferrer"&gt;https://learnxdebug.com&lt;/a&gt; with others’ contributions.&lt;/p&gt;

&lt;p&gt;So, I thought: why not give it a go again? And so I did, going step by step though Gary and Derick’s video, with the goal to implement it into our development process for our Open Source project &lt;a href="https://awe-der.net" rel="noopener noreferrer"&gt;Awe-der&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How hard can it be?
&lt;/h2&gt;

&lt;p&gt;One of the things that most articles I’d read or tried to follow miss out one core thing that frustrated me: most have the “how”, but not the “why”. That is to say: what is this thing I’m doing and why does it work?&lt;/p&gt;

&lt;p&gt;Bearing that in mind, here is how I implemented the stack, step by step with a little bit more info than just your average set of instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff4x8yoqa5t001wq2khxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff4x8yoqa5t001wq2khxv.png" alt="Logos of tech used, will read now"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MacOS 10.15 (Catalina)&lt;/li&gt;
&lt;li&gt;PHPStorm 2020.1&lt;/li&gt;
&lt;li&gt;PHP 7.4.4 (from official PHP Dockerfile)&lt;/li&gt;
&lt;li&gt;Docker 19.03.8 (engine) 1.25.5 (compose)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step One: Installing Xdebug
&lt;/h3&gt;

&lt;p&gt;Part of what made the installation significantly easier for me was that the project it was being installed on was already using a Dockerfile as part of the stack. So, to install Xdebug, you need to include it with pecl (you can still -only- use pecl for operating system-level dependencies at the time of writing). Our project had this in our Dockerfile to install redis and imagick:&lt;/p&gt;

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

RUN docker-php-source extract &amp;amp;&amp;amp; \
   pecl install redis &amp;amp;&amp;amp; \
   pecl install imagick &amp;amp;&amp;amp; \
   docker-php-ext-enable imagick &amp;amp;&amp;amp; \
   docker-php-ext-enable redis &amp;amp;&amp;amp; \
   docker-php-source delete


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

&lt;/div&gt;

&lt;p&gt;It’s at this point you want to install it with pecl, so add pecl install Xdebug into the run commands for the container:&lt;/p&gt;

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

RUN docker-php-source extract &amp;amp;&amp;amp; \
   pecl install redis &amp;amp;&amp;amp; \
   pecl install xdebug &amp;amp;&amp;amp; \
   pecl install imagick &amp;amp;&amp;amp; \
   docker-php-ext-enable imagick &amp;amp;&amp;amp; \
   docker-php-ext-enable redis &amp;amp;&amp;amp; \
   docker-php-source delete


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

&lt;/div&gt;

&lt;p&gt;You can see the actual live Dockerfile (with the correct install command) at: &lt;a href="https://github.com/awe-der/aweder-core/blob/release/table-ordering/docker/php/Dockerfile" rel="noopener noreferrer"&gt;https://github.com/awe-der/aweder-core/blob/release/table-ordering/docker/php/Dockerfile&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Two: Configuring Xdebug
&lt;/h3&gt;

&lt;p&gt;Before Docker, Xdebug was relatively straightforward to configure on a platform, in that it was a new set of the php.ini parameters – you’d either just edit the existing php.ini, or load in a custom ini or override. Now we’re running PHP and fpm in a container, so we need to inject the configuration in with docker-compose.&lt;/p&gt;

&lt;p&gt;First, create the file to inject and save it in the project root – let’s call it xdebug-local.ini.&lt;/p&gt;

&lt;p&gt;Here’s what to put in it:&lt;/p&gt;

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

zend_extension=xdebug
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_port=9001
xdebug.remote_host=host.docker.internal


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

&lt;/div&gt;

&lt;p&gt;I said this wouldn’t just be a copy and paste article, so: what are these parameters?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Zend_extension&lt;/code&gt; has always been the PHP ini file parameter name for adding in extensions – it hooks the pecl extension (or extensions installed with other tools like PEAR) installed to the runtime, so things like zip, redis, curl and the like use the same parameter to enable them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;xdebug.remote_enable&lt;/code&gt; and &lt;code&gt;xdebug.autostart&lt;/code&gt; are more interesting. Remember me mentioning “bookmarklets” in the browser earlier? You have to use an extension to keep a server connection alive with your Xdebug session – for example, for Firefox:&lt;br&gt;
&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/" rel="noopener noreferrer"&gt;https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sound clunky? You bet. Is it required? Absolutely not. Enable remote triggering of the Xdebug server and set autostart to true when either a breakpoint is hit in the code or you’ve set the break to be at the entry point to your application’s code and: bingo. It triggers your debugging session. Do I wish I’d have known about this years ago? For sure.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Xdebug.remote_port&lt;/code&gt; has an interesting quirk in that if you don’t set the parameter, it defaults to port 9000. I guess it’s an interesting aspect that shows Xdebug’s history in that it was probably chosen as a default port before the CGI adopted replacement php-fpm used port 9000. So, it’s important to set the remote port to 9001 (or whichever free port you wish) to stop clashes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Xdebug.remote_host&lt;/code&gt; is the point at which our Docker configuration starts making the process perhaps a little convoluted. In our case, we develop as a company with Macs, so it’s handy that Docker has a reserved handle (&lt;code&gt;host.docker.internal&lt;/code&gt;) to route into the correct IP. Windows does the same at the time of writing, but Linux distributions might need a bit of research to get the correct address in here to connect into Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Three: Inject Config to Docker
&lt;/h3&gt;

&lt;p&gt;So, using &lt;code&gt;docker-compose&lt;/code&gt;, we now inject the local ini file into the php container’s conf.d directory. The docker-compose file should look something like this:&lt;/p&gt;

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

php:
   container_name: my_container
   build: ./path/to/my/php/dockerfile
   environment:
       PHP_MEMORY_LIMIT: '128M'
       DB_HOST: 'mysql'
       DB_USER: 'root'
       DB_PASSWORD: 'root'
       DB_NAME: 'if_your_app_has_a_db'
       PHP_IDE_CONFIG: 'serverName=myapp.url'
   volumes:
       - ./:/var/www/vhost/:cached
       - ./xdebug-local.ini:/usr/local/etc/php/conf.d/xdebug-local.ini


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

&lt;/div&gt;

&lt;p&gt;There are two things here to point out. Firstly, the docker volumes – it’s this line that’s going to enable Xdebug:&lt;/p&gt;

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

./xdebug-local.ini:/usr/local/etc/php/conf.d/xdebug-local.ini


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

&lt;/div&gt;

&lt;p&gt;The second one was a big gotcha: PHPStorm will need to match the incoming Xdebug server request to the webserver that’s set up in the IDE.&lt;/p&gt;

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

PHP_IDE_CONFIG: 'serverName=myapp.url'


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

&lt;/div&gt;

&lt;p&gt;I hadn’t actually set up the webserver on PHPStorm because I personally find a lot of the CLI and server setups for it extremely complex and hard to understand. But, because this environment variable is used to match to PHPStorm’s webserver setup, it cannot match the file structure without it – but more on that in a bit.&lt;/p&gt;

&lt;p&gt;It’s time to check that Xdebug is working: rebuild your Docker stack&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 build build &amp;amp;&amp;amp; docker-compose up -d

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

&lt;/div&gt;

&lt;p&gt;And to check, debug by throwing phpinfo(); into an entrypoint to your app. Navigate to Xdebug on the page and you should see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6rr484iurlkfyga13bh2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6rr484iurlkfyga13bh2.png" alt="Xdebug config in phpinfo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdt4uk7s9ggozzaiq3fvf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdt4uk7s9ggozzaiq3fvf.png" alt="Xdebug set config values"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Four: Set up PHPStorm
&lt;/h3&gt;

&lt;p&gt;I briefly mentioned that you need to set up your web server on PHPStorm first – so do that first. You can find pretty comprehensive and complete docs from Jetbrains on this here: &lt;a href="https://www.jetbrains.com/help/phpstorm/creating-local-server-configuration.html#example1" rel="noopener noreferrer"&gt;https://www.jetbrains.com/help/phpstorm/creating-local-server-configuration.html#example1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we get PHPStorm to listen to port 9001 which we set in the config. You can change that like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdya8lazptc1msqbxmqb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdya8lazptc1msqbxmqb8.png" alt="PHPStorm Xdebug settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Path mapping is important – PHPStorm has no way from the incoming request of knowing how the application is structured. Here’s an example of the configuration for Awe-der:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9aw73oec5g6pjbv1a5a8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9aw73oec5g6pjbv1a5a8.png" alt="Web server setup in PHPStorm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The absolute path on the server is what you need to change – make sure you change it to the root path served by your Docker stack (in our case, where nginx is serving the root of the application). This is an important step because PHPStorm assumes that the root directory from the incoming request is the public folder (if using either Symfony or Laravel). Make sure you also choose Xdebug as the debugger and use the appropriate HTTP port. Now, set PHPStorm to listen.&lt;/p&gt;

&lt;p&gt;It’s time for the moment of truth: you’re listening for connections, you’re mapped, you’ve setup the Xdebug server: showtime. Add a breakpoint in PHPStorm (preferablly at the entry point of your app, so you know it’ll get hit), fire a request in the browser and IF everything is OK you’ll get an incoming connection from Xdebug in the IDE. Happy days if you did, don’t despair if you don’t: there are a lot of gotchas here. If nothing happens, the other tutorials at &lt;a href="https://learnxdebug.com/" rel="noopener noreferrer"&gt;https://learnxdebug.com/&lt;/a&gt; will probably have the answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  As promised: Turbocharged Development
&lt;/h3&gt;

&lt;p&gt;So, here’s what you actually came here for, right? As with debugging in other interpreted languages, your start point will be a breakpoint (you can actually set PHPStorm to hit a breakpoint whenever a new file entry point is detected as well).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2rhq99j1qie2tovw0t7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2rhq99j1qie2tovw0t7e.png" alt="Code with breakpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s a breakpoint set in our Awe-der project. We’re listening for connections – so, all being well we hit the Controller when loading the page, and hey presto! PHPStorm’s debugging pane appears.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F48qj6qupm2281fb7z5z8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F48qj6qupm2281fb7z5z8.png" alt="Debugging pane in PHPStorm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we’re at a paused moment in the runtime, let’s check out what we can do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Console / Evaluate expression
&lt;/h3&gt;

&lt;p&gt;You get a console that can run executable PHP within the runtime you’re in. That is… absolutely magic. Here’s an example of using the console live within Xdebug that will save you a mountain of &lt;code&gt;var_dump()&lt;/code&gt; calls:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ppexh58aw64wi1yfsah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ppexh58aw64wi1yfsah.png" alt="Console printed code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Putting a variable straight into the console will print it, in exactly the same way that Javascript does it with console.log in a browser console.&lt;/p&gt;

&lt;p&gt;We can change something on any variable at runtime in the console. Take for instance this line:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$orderItem-&amp;gt;fill($apiPayload);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That’s Laravel’s Eloquent ORM. Why not see what happens at runtime when you do something else with it in the console?&lt;/p&gt;

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

$orderItem-&amp;gt;toArray()
‌array (
  'order_id' =&amp;gt; 1,
  'inventory_id' =&amp;gt; 2,
  'variant_id' =&amp;gt; 1,
)

$orderItem-&amp;gt;fill(['order_id' =&amp;gt; 234523523]);

$orderItem-&amp;gt;toArray()
‌array (
  'order_id' =&amp;gt; 3333,
  'inventory_id' =&amp;gt; 2,
  'variant_id' =&amp;gt; 1,
)


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

&lt;/div&gt;

&lt;p&gt;Done. We’ve just messed around with an entity on the fly.&lt;/p&gt;

&lt;p&gt;The console has everything set &amp;amp; booted (assuming you’re using Composer’s autoload) to the point it’s activated – so crucially local scope variables are available. You can also navigate the stack as well via. the frames in the debugger. Laravel has pretty detailed stack traces when you use Blade, but they’re not interactive ones like we can get in the IDE:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz2xuaq0o3dncpmzm32gd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz2xuaq0o3dncpmzm32gd.png" alt="Debugging pane with frames"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is next level debugging. You can navigate the frame pane to the left to view the executed stack. When you select a frame from it, the editor pane will navigate to the function call in the code and the variable pane will update to everything that has been set at that point. For big monolith stacks full of services and function calls all over the place, you’ve now got far more visibility. Pretty neat, huh?&lt;/p&gt;

&lt;h3&gt;
  
  
  Conditional Breakpoints
&lt;/h3&gt;

&lt;p&gt;An underrated feature is the ability to set breakpoints conditionally. For an example, let’s say that we only want to trigger the breakpoint to debug if an incoming request to a controller has a “search” term set.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjwrtk90s8r85l1bf4o5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjwrtk90s8r85l1bf4o5z.png" alt="Code with conditional breakpoint set"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done. Another joy of this in PHPStorm is that the Condition window behaves like any other console window, so you get application-wide autocompletion and local variable autocompletion.&lt;/p&gt;

&lt;p&gt;So, if we hit the URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiedpdi8dd8yzgu3cl8f4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiedpdi8dd8yzgu3cl8f4.png" alt="Awe-der dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Loads as expected, but add the search term in to the URL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://awe-der.net/admin/dashboard?search=test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu6yxx2hxmqnusaeyks8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu6yxx2hxmqnusaeyks8d.png" alt="Hit the breakpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Watchers
&lt;/h3&gt;

&lt;p&gt;Common debugging nightmares include mutable objects being hit -somewhere- in the stack. We have visibility of the stack, but that’s not much help when tracking a specific object. To set a watcher, add an expression in the watcher pane to the left. It will be evaluated with each step you trigger. A good example to see it in action would be the classic C loop:&lt;/p&gt;

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

public function testWatcher(): void
{
   $variableToWatch = 45;

   for ($i = 1; $i &amp;lt; 5; $i++) {
       $variableToWatch = $variableToWatch + rand(0, 200);
   }
}


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

&lt;/div&gt;

&lt;p&gt;Set a watcher on &lt;code&gt;$variableToWatch&lt;/code&gt;, and check out the watcher doing it’s magic just like any Javascript browser watcher as you step over the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9pm5krh0eukb6iketx4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9pm5krh0eukb6iketx4b.png" alt="Active watcher window"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step &amp;amp; Cursor controls:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs0znw0ps9avhlmem6z1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs0znw0ps9avhlmem6z1x.png" alt="Cursor controls in PHPStorm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The five controls are as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step over&lt;/strong&gt;: run to the next line of code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step into&lt;/strong&gt;: run into the next line, moving the cursor if entering a method call&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Force step into&lt;/strong&gt;: same as Step into, but runs with calls into vendor/3rd party code for deeper debugging&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step out&lt;/strong&gt;: complete the current method and stop at the next line after the method that called it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run to cursor&lt;/strong&gt;: For me, this is the most important one, and I’ll tell you why:&lt;/p&gt;

&lt;p&gt;If you’re debugging something quite straightforward in that it’s your own code entirely, or something like the Slim framework with as little code as possible, stepping through the code is pretty logical. However, for those using a big framework – Laravel, Symfony, Cake, WordPress etc. there are calls, pipelines and event handlers all over the app. That magic has got to happen somehow, and if you try and step into it, you can see it in action.&lt;/p&gt;

&lt;p&gt;Don’t want to see all the handlers resolve? Cool. Move the cursor to the next line you want, so you can see the result piped into the variable frame. Hit run to cursor, job done.&lt;br&gt;
Probably the most important: modifying the output&lt;/p&gt;

&lt;p&gt;Modifying the output is, in my opinion, what makes Xdebug so powerful. We’ve looked at the fact that you can change variables and interact with the code at runtime, but what hasn’t been mentioned is that if you instruct the debugger to complete, the output is the changed output. To see it in action, here are two use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Blade templates
&lt;/h3&gt;

&lt;p&gt;We have a variable named &lt;code&gt;$dashboardMetrics&lt;/code&gt; that’s passed into our template for rendering. Here it is rendered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fky5rm4fclg2gvllne4yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fky5rm4fclg2gvllne4yf.png" alt="Dashboard on Aweder displaying the variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, with a breakpoint set in the debugger, here is the payload printed out at the point it’s about to be loaded into the template:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fas8g7p3ojnbwmtoiy0jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fas8g7p3ojnbwmtoiy0jg.png" alt="Breakpoint for debugging the variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I’m going to change “Processing” to 999. Hitting the breakpoint again, I’ll use the console to set it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx97eltkbeh1lo6sv4b5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx97eltkbeh1lo6sv4b5x.png" alt="Console in PHPStorm changing the variable value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the left hand side of the debugger pane you have the a “Resume Program” button. It allows you to complete the incoming request, so hit that and:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fowm63ku9dhnpy98bp1q9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fowm63ku9dhnpy98bp1q9.png" alt="Updated dashboard with modified data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Request completed, you’ve modified runtime to change it.&lt;/p&gt;

&lt;h3&gt;
  
  
  API calls
&lt;/h3&gt;

&lt;p&gt;Exactly the same logic applies to changing the output of an API request. Here I’m using Postman to get an entity via. A UUID:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8x8bpcya464g2ebr4l0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8x8bpcya464g2ebr4l0d.png" alt="Custom request in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the same method as the browser request, we’ll put a breakpoint into the API method and modify the output. Here’s the method response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhjpuxuim6qr1373rsx5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhjpuxuim6qr1373rsx5z.png" alt="API response in codebase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Protip for Laravel – don’t do this, always use Laravel Resources!)&lt;/p&gt;

&lt;p&gt;So, at the breakpoint let’s change the entity making the available_time now instead of the dummy date using the Carbon library:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feq3f2tzjkrsgo7h2ycfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feq3f2tzjkrsgo7h2ycfo.png" alt="Console output after changing dates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resume runtime, and check out the result from Postman:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9b1ynrr28hg5itdph6se.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9b1ynrr28hg5itdph6se.png" alt="Altered API response in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Magic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I came into this with some thoughts and assumptions, so I’ll tie up my new experience with Xdebug in some key points that answer those questions.&lt;br&gt;
Conclusions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Why use Xdebug when you can var_dump()?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Because it allows you to manipulate the runtime. If you use something like var_dump() you need to fire the CLI constantly or hit refresh on a browser over and over to get to the same point. Instead, you now have the chance to dynamically change and modify the stack – which is a big timesaver.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: You mentioned PsySh, why not use that?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Xdebug and PsySh are very different beasts. Whilst PsySh is labelled somewhat of a debugger, I don’t really treat it as such. It’s vital as a booted command line for your app, similar to manage.py for Django, but it’s not a pure debugger like Xdebug is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: This is still hard to set up still, isn’t it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: I’d say it’s probably less of a mystery now that I’ve looked at it, and not as hard as most developers think. Plus the toolset for everyday use is so powerful, it’ll save you or your team a big chunk of valuable time and cognitive load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Are there downsides to using Xdebug?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: The biggest downside I found was execution time. With the configuration in this article, the Xdebug server is always on – for a full PHPUnit test suite to run (if it’s pretty comprehensive) it will take a -big- performance hit. Luckily, there are workarounds for this in Docker, such as running commands with a custom ini to switch the Xdebug server off. If you’re in Production this is a real no-no.&lt;/p&gt;

&lt;p&gt;Overall, I’d say the tradeoff for time was well worth the effort. Something like this should be part of a developers’ tool chain – sure, it’s not always needed. If you’re doing an MVP in Laravel that’s mainly just CRUD operations, there’s probably not much justification for it.&lt;/p&gt;

&lt;p&gt;However, I’ve found that for many modern practises – comprehensive unit tests with large coverage from TDD, interface-based development and well-separated call stacks from considered single-responsibility principle controllers really do mean Xdebug gives you a decent edge.&lt;/p&gt;

&lt;p&gt;If you’re working on a legacy application in Zend Framework 2 or 10,000 line controllers in someone’s 2006 bespoke framework and you’re not using Xdebug, I’d come to the conclusion that you love the punishment, and like it that way, you massochist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What’s the outcome of trying it out?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Development with TDD and Xdebug felt incredibly empowering, so we’re going to look to make it part of the default development environment &amp;amp; process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How much does Xdebug cost?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: It’s free. Although, it depends on what the definition of “free” is – as it’s Derick’s Open Source project, it costs vast amounts of personal development time. If you want to try it out from reading this article (or you want to try it out with a different platform – check &lt;a href="https://learnxdebug.com" rel="noopener noreferrer"&gt;https://learnxdebug.com&lt;/a&gt; for other tutorials) then considering supporting his work:&lt;br&gt;
&lt;a href="https://xdebug.org/support" rel="noopener noreferrer"&gt;https://xdebug.org/support&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy debugging!&lt;/p&gt;

</description>
      <category>php</category>
      <category>docker</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Virtual onboarding during the COVID-19 crisis - time costing</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Sun, 26 Apr 2020 13:49:18 +0000</pubDate>
      <link>https://dev.to/secondej/virtual-onboarding-during-the-covid-19-crisis-time-costing-ff1</link>
      <guid>https://dev.to/secondej/virtual-onboarding-during-the-covid-19-crisis-time-costing-ff1</guid>
      <description>&lt;p&gt;Almost every tech company is facing unprecedented challenges during the COVID-19 crisis, and at Jump24 it’s been no exception. The tech world has been switched to fully virtual overnight, which is bringing some very interesting debates forward (that I will discuss), most notably “how well is your business currently designed to deal with that?”&lt;/p&gt;

&lt;p&gt;I would argue that one of the biggest indicators of how well you’re set up to deal with this is onboarding new staff. As a Developer Advocate that endlessly discusses Developer Experience, what better test could there be for Jump24 than me starting out there?&lt;/p&gt;

&lt;p&gt;It became clear that discussing my experience of onboarding virtually deals with a lot of  hot topics across tech right now with the ongoing COVID-19 crisis, so let’s dive into each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communications
&lt;/h2&gt;

&lt;p&gt;Communications are undoubtedly the first hurdle we face, and inevitably bring in the biggest blocker for remote working across the entire industry: trust.&lt;/p&gt;

&lt;p&gt;Trusting your developers to get on with what they’re doing and balancing hands off vs. micromanagement is absolutely vital. There are two factors that should determine your strategy for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The experience levels of your developers&lt;/li&gt;
&lt;li&gt;Scale of company&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are mentoring new developers, you have to make time for them. I see this time and time again, where product owners and CTOs have the domain knowledge the new developers need, but cannot access. Your new developers won’t succeed without this mentoring, remote or not; only now you have new developers at home unable to do anything as opposed to in the office and unable to do anything. If you’re in a larger organization, you must make sure you have the structure set up to be able to deliver that knowledge and mentorship, and review where the support is coming from.&lt;/p&gt;

&lt;p&gt;Jump24 has made communication rules simple to adhere to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Morning standup&lt;/li&gt;
&lt;li&gt;All movements away from machine communicated on Slack&lt;/li&gt;
&lt;li&gt;Clockify removes the need for micromanagement&lt;/li&gt;
&lt;li&gt;Make time for each other (Skype calls, screenshare debugging)&lt;/li&gt;
&lt;li&gt;Always time for sprint retros &amp;amp; kickoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It seems so simple, doesn’t it? But that’s because it is! Companies such as Automattic have &lt;a href="https://qz.com/694410/automattic-has-figured-out-the-right-tools-for-remote-working/"&gt;absolutely nailed down the way they communicate on Slack&lt;/a&gt; which is to be as explicit and verbal as possible. Providing we all stick to doing that, everything falls into place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent learning Jump24’s Communications strategy: 5 mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project structure
&lt;/h2&gt;

&lt;p&gt;We know we should all be doing Agile, right?&lt;/p&gt;

&lt;p&gt;It seems absolutely absurd that I’m writing this, but many companies still don’t practise Agile as standard. “You know what to do on this project, crack on until the shipping date”.&lt;/p&gt;

&lt;p&gt;If you do not trust your developers to deliver work remotely, you’re presumably desperate to get everyone back into the office again. You might feel like you don't have any visibility of what has been done or is left to do, and it could well be the root problem of why some businesses are struggling with the sudden switch to remote.&lt;/p&gt;

&lt;p&gt;There’s a second part to working with Agile for development that is just as important: &lt;em&gt;well defined, broken down stories&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At Jump24, tasks and stories are broken down into the exact specification to what they should contain with well thought out descriptions, source control is branched and organised accordingly, and thus the flow of work is already in place. Swap out the office to remote and nothing changes. Therefore, the onboarding experience onto a project from my experience went like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log into Jira&lt;/li&gt;
&lt;li&gt;Start working and submit your work for review.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent trying to get up to speed with the new project: 10 mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;If you’ve not taken the time to get to grips with Docker or any sort of environment containerisation, my guess is that the shift to remote work has hit you hardest as you have to get each developer up to speed with a developer environment. I’ve heard arguments that it’s difficult to set up for larger projects, that it requires higher developer skill levels or that only DevOps folks can really do it.&lt;/p&gt;

&lt;p&gt;Like mentoring your inexperienced developers, the real barrier here is &lt;em&gt;investing time&lt;/em&gt;. It is difficult to learn best practises in containerization - nobody should realistically be expected to pick up Kubernetes in 2 days. But, if you do get DevOps to take the time to set up a project’s environment correctly, you get an onboarding experience like mine.&lt;/p&gt;

&lt;p&gt;We’ll get onto standards shortly, but there is also quality control tooling such as &lt;a href="https://github.com/phpro/grumphp"&gt;GrumPHP&lt;/a&gt; that doesn’t allow you to push your code if it sniffs code smells. Combined with Jump24’s TDD, this makes for a pretty supportive new development environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent trying to deploy new project to work on: 10 mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Standards
&lt;/h2&gt;

&lt;p&gt;At Jump24, the work we deliver is key. Priority is given to making sure the code and structure is right. We adhere to PSR standards in our work and, as a &lt;a href="https://laravel.com/partners"&gt;Laravel partner&lt;/a&gt;, Laravel best practises.&lt;/p&gt;

&lt;p&gt;John Woods once wrote “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.”, and I am a fan of this philosophy. Far too many are quick to dismiss this in favour of getting projects delivered on time, ASAP, but let’s be absolutely clear about what benefits having higher standards bring to your company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long term client partnerships&lt;/li&gt;
&lt;li&gt;Ability to quickly scale delivered work&lt;/li&gt;
&lt;li&gt;Levelling up your developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last point is something I hold dear in my heart: if you deliver unchecked work “as long as it works” to a client for speed and money, its development team will not have learned anything. You’re putting those developers’ careers at a disadvantage.&lt;/p&gt;

&lt;p&gt;The impact of remote working with adopted standards is that there’s no change. The developers know what to do. The project managers know what to do. The framework is already there, and the context with which it’s used doesn’t change. There’s no unexpected or confusing behaviour in the existing projects, because of best practices across all the developers, thus avoiding the “what was in this developer's head at the time” problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent trying to understand standards used : 0 mins (I already knew them).&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://medium.com/ft-product-technology/documentation-day-how-the-ft-com-team-improved-our-documentation-to-95-usefulness-in-7-hours-b73d1a7e6f30"&gt;Everything is documented, because it’s the correct thing to do.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What’s that, you’ve not been documenting stuff because you don’t have time? Oof!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent trying to work out undocumented features: 0 mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Self documenting code
&lt;/h2&gt;

&lt;p&gt;Going hand in hand with documentation is the mythical self-documenting code. Many say that this doesn’t exist, but the truth is that it does. Again, it boils down to putting time in to make sure this is the case - alongside standards and documentation at Jump24, debating exact function and variable naming and how interfaces are implemented is important. I’ve not had an onboarding experience as smooth as this because of self-documenting code actually doing what it says on the tin, and as a developer I can tell you it’s a delight. With no meetings to go through the structure of the codebase, it didn’t matter whether I was remote or on site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent trying to work out arbitrary mystery code: 0 mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Review
&lt;/h2&gt;

&lt;p&gt;There’s only one way you can keep the standards high, and that’s through Code reviews, though these are &lt;a href="https://medium.com/@johnsinco/dont-do-code-reviews-109f7d3952de"&gt;notoriously difficult to balance.&lt;/a&gt; In my case, there is the understanding within the team that the purpose of code review is exactly that. It can go hopelessly wrong when you throw &lt;a href="https://twitter.com/skirani/status/1149302828420067328"&gt;egos into the mix&lt;/a&gt;, but the idea to make code review constructive is to understand the company culture&lt;br&gt;
beforehand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent worrying the team are hammering me on code review: 0mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD First
&lt;/h2&gt;

&lt;p&gt;Probably the most worrying part of onboarding onto a new team, especially when doing it remotely, is not having to experience that terrible fear that what you’re about to do is &lt;a href="https://about.gitlab.com/blog/2017/02/01/gitlab-dot-com-database-incident/"&gt;delete production by accident.&lt;/a&gt;&lt;br&gt;
Jump24 is TDD-first, specifically to avoid these kind of problems. There are two results of taking this direction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With other tooling such as Bitbucket Pipelines &amp;amp; GrumPHP: cannot push breaking changes to Production&lt;/li&gt;
&lt;li&gt;Upskilling developers with what should be standard practice industry-wide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a drawback to this: you have to invest the time to write and correctly implement TDD. But - when you do, it naturally falls into the onboarding process nicely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Times I’ve broken Production: 0&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
// &lt;a class="mentioned-user" href="https://dev.to/todo"&gt;@todo&lt;/a&gt; keep eye on this&lt;/p&gt;

&lt;h2&gt;
  
  
  Reputation &amp;amp; Culture
&lt;/h2&gt;

&lt;p&gt;One of the reasons that understanding the culture has taken so little time is, quite frankly, because the work has been put in long beforehand in my case. Jump24 firstly sponsored my community group &lt;a href="https://www.meetup.com/brumphp/"&gt;BrumPHP&lt;/a&gt;, then I handed it over to them - it’s a company that gets how the PHP community works. By the time it came to virtually onboard here, I’d already spent the best part of two years in the Birmingham ecosystem discussing PHP matters with them. For most Developer Relations roles, the onboarding time is usually around a week off site to go through the fine detail of what the role is - by the time I’d started Jump24, I already knew.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent culturally onboarding: 0mins.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s understandably a pretty low score when it comes to time that my company has spent onboarding me, but that’s because the work has been put in place beforehand. We regularly throw out the things we should be doing in software development, but “never have the time”. I think the COVID-19 crisis we all face together as an industry is the final push we need to consider how important all of these things are, and if you're ready and flexible with your staff, the payoff makes a massive difference.&lt;/p&gt;

&lt;p&gt;When times change, and we can come back into the office again: nothing changes in terms of how we work. I’m just looking forward to meeting my colleagues in person!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Time spent enjoying work: All of it.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With thanks to &lt;a href="https://jump24.co.uk/"&gt;Dan Newns&lt;/a&gt;, &lt;a href="https://twitter.com/jenny__anne"&gt;Jen Lambourne&lt;/a&gt; and &lt;a href="https://www.kryogenix.org/"&gt;Stuart Langridge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devrel</category>
      <category>laravel</category>
      <category>productivity</category>
      <category>agile</category>
    </item>
    <item>
      <title>Beginning steps to write a Shopify app with Laravel</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Mon, 24 Feb 2020 12:43:43 +0000</pubDate>
      <link>https://dev.to/secondej/beginning-steps-to-write-a-shopify-app-with-laravel-5953</link>
      <guid>https://dev.to/secondej/beginning-steps-to-write-a-shopify-app-with-laravel-5953</guid>
      <description>&lt;p&gt;The Shopify platform contains a whole host of built in functionality. However, thanks to its fully featured REST and GraphQL API access, it also has a thriving app store with a huge range of plug-ins designed to enhance Shopify store functionality in many ways. I'll talk you through a Shopify app development tutorial to help you get started on making your own Shopify app, using the Laravel PHP framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Shopify App?
&lt;/h2&gt;

&lt;p&gt;A Shopify app is an externally-hosted service that has access to and can manipulate a Shopify store. For the most part, any feature you can see in the admin panel can be accessed and changed via the API - it can modify/create products, view or change orders and so on. Apps are a great way to automate common tasks such as bulk-editing collections or extending your store's functionality, like adding reviews to your products.&lt;br&gt;
The 2 Types of Shopify Apps&lt;/p&gt;

&lt;p&gt;Public apps can be submitted to the app store and used by multiple stores. To create and submit normal apps to the Shopify App Store, you need to own a Shopify Partner account.&lt;/p&gt;

&lt;p&gt;Private apps are usually used by a single store. In this article, we’ll be going through the steps for Shopify private app development, as they can be created by anyone with a Shopify store and require less steps to set up.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to Create a Shopify App Using PHP
&lt;/h2&gt;

&lt;p&gt;To follow this guide, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Shopify store you want to make an app for.&lt;/li&gt;
&lt;li&gt;PHP7.2 or higher and some familiarity with the language (&lt;a href="https://www.php.net/supported-versions.php"&gt;https://www.php.net/supported-versions.php&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Some familiarity with a command line (cmd.exe/Powershell for Windows, bash/zsh/fish for MacOS and unix-like distributions).&lt;/li&gt;
&lt;li&gt;Some familiarity with Composer.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  API Keys
&lt;/h2&gt;

&lt;p&gt;Let’s begin by creating a set of API keys for our app. Head to the Apps panel from the right hand navigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PIyx_Q5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/d765c5714ba23399e80fcc57dd300daf/7a748/-shopify-apps-panel-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PIyx_Q5k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/d765c5714ba23399e80fcc57dd300daf/7a748/-shopify-apps-panel-1.png" alt="Menu" width="188" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wt-SwTSh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/0fd8c34d79b07e723c8123d36c17c346/f71e8/private-apps-menu-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wt-SwTSh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/0fd8c34d79b07e723c8123d36c17c346/f71e8/private-apps-menu-2.png" alt="Private Apps Menu" width="693" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click ‘Create a new private app’ to get the prompt to name your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tnEGc7Th--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/519660e0e378b615cab457eccf5c7430/69344/create-private-app-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tnEGc7Th--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/519660e0e378b615cab457eccf5c7430/69344/create-private-app-3.png" alt="Create Private App" width="700" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll leave the API dropdowns so that the app only has read access to your store.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fXm6PbqO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/13fdc1b8731ff9113e37a870ec776db3/69344/admin-api-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXm6PbqO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devtheatre.net/static/13fdc1b8731ff9113e37a870ec776db3/69344/admin-api-4.png" alt="Admin API" width="700" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make a note of your new credentials. And with that step, it’s time to set up a local Laravel &amp;amp; vue.js app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up a Laravel Skeleton
&lt;/h2&gt;

&lt;p&gt;So, first we’re going to install a fresh Laravel skeleton app. You can do this via the Laravel installer (&lt;a href="https://github.com/laravel/installer"&gt;https://github.com/laravel/installer&lt;/a&gt;), but the quickest route is to use Composer’s create project. Open up your command line and create a new project:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer create-project --prefer-dist laravel/laravel shopifyApp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We’re going to use Twig (&lt;a href="https://twig.symfony.com/"&gt;https://twig.symfony.com/&lt;/a&gt;) instead of Laravel’s built-in Blade templating system for the front end, because the syntax Twig uses is based on Ruby’s Liquid templating system, used by Shopify on its platform. We’re going to be using Rob Crowe’s bridge connector for Laravel. Install Twig, following the instructions on the readme located here - &lt;a href="https://github.com/rcrowe/TwigBridge"&gt;https://github.com/rcrowe/TwigBridge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have Twig, let’s get a page up and running by creating a new route, controller and Twig template. To create a new controller, in the command line run&lt;/p&gt;

&lt;p&gt;&lt;code&gt;php artisan make:controller shopifyController&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to wire up a route, controller and view. Add a new route to &lt;strong&gt;routes/web.php&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Route::get('/index', 'ShopifyController@index');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create the method in your controller, which will now be in&lt;br&gt;
&lt;strong&gt;/app/Http/Controllers/ShopifyController&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;?php

namespace App\Http\Controllers;

class ShopifyController extends Controller
{
  public function index()
 {
     return view('index');
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last part is to create the ‘index’ view - create a new file in: &lt;strong&gt;/resources/views called index.twig&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Eastside Co’s API Wrapper
&lt;/h2&gt;

&lt;p&gt;We now need to use the Eastside Co Shopify API wrapper to bring us back some data to render. Eastside Co have already got a PHP package on packagist - it’s an API code wrapper for common REST API tasks with Shopify. Navigate into the ShopifyApp directory in your command line and install the Eastside Co API:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;composer require esc/shopify&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To enable the installed package, we need to add it to services and install assets. You do this by doing the following:&lt;/p&gt;

&lt;p&gt;Add &lt;strong&gt;\Esc\Shopify\Providers\APIServiceProvider::class&lt;/strong&gt; into the providers array in &lt;strong&gt;/config/app.php&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Run &lt;strong&gt;php artisan vendor:publish&lt;/strong&gt; in the command line to copy the package assets into Laravel.&lt;/p&gt;

&lt;p&gt;We can now input the ShopifyAPI keys. Create a copy of your &lt;strong&gt;.env.dist&lt;/strong&gt; and called it &lt;strong&gt;.env.&lt;/strong&gt; In the .env file, add the keys that the API object will read in when the service is created in Laravel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOPIFY_API_KEY = &amp;lt;API Key&amp;gt;
SHOPIFY_API_SECRET = &amp;lt;Shared Secret&amp;gt;
SHOPIFY_ACCESS_TOKEN = &amp;lt;Password&amp;gt;
SHOPIFY_SHOP_DOMAIN=&amp;lt;my-store-domain.myshopify.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Render
&lt;/h2&gt;

&lt;p&gt;Let’s get the data in the controller and pass it to the index Twig template we created. Change the controller’s index method to look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public function index() {
    $shopifyApi = app(‘ShopifyAPI’);
    $products = $shopifyApi-&amp;gt;call('GET', 'admin/products.json&amp;amp;page=1');
    return view('index', (array) $products);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re now passing the first page of our store’s products to Twig, which we can now render out - open the resource/views/index.twig file we created. You can use a foreach loop in twig which operates the same as the php foreach function:&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;html&amp;gt;
   &amp;lt;p&amp;gt;This is an example Shopify APP page!&amp;lt;/p&amp;gt;
   {% for product in products %}
       This product is called: {{ product.title }}&amp;lt;/br&amp;gt;
   {% endfor %}
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Navigate to your route and the product titles will be rendered out by Twig.&lt;/p&gt;

&lt;p&gt;A repository of this basic scaffolding is available on our Github, at &lt;a href="https://github.com/EastsideCo/blog-basic-laravel"&gt;https://github.com/EastsideCo/blog-basic-laravel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hopefully that helps give you some insight into the process behind creating a private Shopify app. If you have an idea for a private app but need developer support, get in touch - we have a whole team of developers dedicated to creating public and private Shopify apps for a whole range of functionality.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>shopify</category>
    </item>
    <item>
      <title>First steps to caching PostgreSQL queries with Redis</title>
      <dc:creator>James Seconde</dc:creator>
      <pubDate>Tue, 04 Feb 2020 13:10:18 +0000</pubDate>
      <link>https://dev.to/heroku/first-steps-to-caching-postgresql-queries-with-redis-2m71</link>
      <guid>https://dev.to/heroku/first-steps-to-caching-postgresql-queries-with-redis-2m71</guid>
      <description>&lt;p&gt;Is Redis the instant silver bullet to solve all of your app’s performance issues? Yes. &amp;lt;/end&amp;gt;&lt;/p&gt;

&lt;p&gt;Except, of course: it isn’t. Introducing Redis to cache your database layer can certainly boost your performance. But the caveat, like everything we do in development, is that half the battle is in planning your strategy.&lt;/p&gt;

&lt;p&gt;The old joke goes that there are two problems in computer science: cache invalidation and naming things. Like many old jokes, there’s more than a hint of truth there. Caching has the potential to solve bottlenecks and squeeze more performance out of your existing Postgres instance. However, there are some basics that you need to get right.&lt;/p&gt;

&lt;p&gt;Before we dive into the nitty-gritty, let’s have a quick refresher on both PostgreSQL and Redis.&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL: the truth
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1557050543-4d5f4e07ef46%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1489%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1557050543-4d5f4e07ef46%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1489%26q%3D80" alt="a postgres SQL like elephant"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re using Rails, Laravel, or some other web development framework that has its own ORM, it’s easy to forget about the engine behind your data.&lt;/p&gt;

&lt;p&gt;Let’s get this out of the way: PostgreSQL is fast but its primary job is to be right. PostgreSQL is your app’s undeniable source of truth. Whereas some NoSQL databases will serve a stale version of a record if doing so saves time, PostgreSQL only ever gives you the most up-to-date data.&lt;/p&gt;

&lt;p&gt;Where Postgres can become slow is when its power is misused. “Powerful” is often a weasel word when it comes to tech, but in the case of PostgreSQL it’s an accurate description. With Postgres, you can structure and query your data in almost infinite ways. It gives you immense power over your data but with that power comes a hundred and one ways to trip yourself up. &lt;/p&gt;

&lt;p&gt;The two big gotchas are data modelling and query design. Web framework ORMs go to some lengths to optimize both but they also need to be generalists. Once you get to the point of noticing the speed of your Postgres instance, it might be that you’ve hit the limits of how well a generalist ORM can handle your app’s data needs. Or perhaps you already use hand-written queries but they’re not as performant as they should be.&lt;/p&gt;

&lt;p&gt;Either way, introducing caching can help you offset problems brought about by inefficient data models and queries but, unless you fix them, your database will only ever be working against the overall efficiency of your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redis: the accelerator
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1498887960847-2a5e46312788%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D1050%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1498887960847-2a5e46312788%3Fixlib%3Drb-1.2.1%26auto%3Dformat%26fit%3Dcrop%26w%3D1050%26q%3D80" alt="picture of a car dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If PostgreSQL is the truth, then Redis is the speed. You probably know Redis already as an in-memory key-value store. Perhaps you’ve used it to store session data and similar ephemeral data. As it’s primarily in-memory, Redis is ideal for that type of data where speed of access is the most important thing. So, that makes it great for caching, right?&lt;/p&gt;

&lt;p&gt;Yes—and there’s more to Redis. Not only does it give you a bunch of different data types but it also persists to disk.&lt;/p&gt;

&lt;p&gt;So, Redis is the truth, too? It can be if you want it to be. And this is why caching PostgreSQL with Redis can be a bigger discussion than you might expect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to use Redis with PostgreSQL
&lt;/h2&gt;

&lt;p&gt;So, this gives us three different ways to use Redis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read-through:&lt;/strong&gt; off-set reads from Postgres by caching commonly accessed data in Redis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write-back:&lt;/strong&gt; write data to Redis first and then push it out to Postgres later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cut out Postgres entirely:&lt;/strong&gt; some data doesn’t need to be in Postgres at all and, instead, can live only in Redis .&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How do you know which is right and when? &lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing what to cache
&lt;/h2&gt;

&lt;p&gt;There aren’t hard and fast rules to say what you should cache and what you shouldn’t but the following questions can help make the decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Does this query impact user experience?&lt;/strong&gt; If a query blocks rendering of the UI, for example, then it’s likely to be a good candidate for caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does it matter if this data is slightly stale?&lt;/strong&gt; Some data absolutely has to be the very latest; a bank balance, for example. Other data can be somewhat old without any negative effects. If it can be stale, it’s a good candidate for caching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Will this query grow with usage?&lt;/strong&gt; As your app grows, are there queries that will run more and more?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do I need to run complex queries on this data or do I only ever pull it straight back out of the database in the same way it was written?&lt;/strong&gt; If you’re not using the power of PostgreSQL’s querying on the data, then maybe it doesn’t need to be stored there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Could I stand to lose this data?&lt;/strong&gt; Even if you’re using Redis’s persistence, it is still memory-first. So, if there’s data you could stand to lose, perhaps it’s best to write it to Redis first and then, optionally, write it out to Postgres later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is there a specialized tool that would do a better job?&lt;/strong&gt; For example, logs. Logs have high write throughput, which isn’t PostgreSQL’s strong point, and there are specialized logging tools that will do the job better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, don’t forget the one question you should ask before all of these: "could I rewrite the query in such a way that it runs better on PostgreSQL?" That’s not the end of the story, but you should fix fundamental problems before hoping caching will solve them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the cache up to date
&lt;/h2&gt;

&lt;p&gt;That old joke –– the one about cache invalidation –– is so on point because, once you start using a cache, you’ll spend a lot of your time thinking about how to ensure the data in your cache is up to date.&lt;/p&gt;

&lt;p&gt;When you decide to refresh your cache depends on the tradeoff you want to make between the expense of updating the cache versus the risk of serving outdated data.&lt;/p&gt;

&lt;p&gt;There are many &lt;a href="https://en.wikipedia.org/wiki/Cache_replacement_policies" rel="noopener noreferrer"&gt;cache invalidation policies&lt;/a&gt; to choose from but broadly speaking, you’ll be using something that looks like one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time to live:&lt;/strong&gt; you ask Redis to automatically expire an item after a set time period, meaning your data layer will have to go to PostgreSQL to refresh the item.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache on write:&lt;/strong&gt; for data with a high read rate and that changes infrequently, you can simply update the cache each time you write to PostgreSQL; this becomes expensive as write frequency increases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least recently used:&lt;/strong&gt; this eviction method focuses on freeing resources, rather than keeping data fresh, by deleting from the cache data that isn’t getting read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those three are a simplification but offer a glimpse of how to think about keeping your cache fresh.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking the first steps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1529339017023-c2f2ce633d0d%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1051%26q%3D80" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1529339017023-c2f2ce633d0d%3Fixlib%3Drb-1.2.1%26ixid%3DeyJhcHBfaWQiOjEyMDd9%26auto%3Dformat%26fit%3Dcrop%26w%3D1051%26q%3D80" alt="man planning how to implement cool Redis caching"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Getting started with Redis is pretty straightforward. You can tinker on your laptop and there are packages for Rails, Laravel, Django, and most major web frameworks to help you get going. Once you’re ready for production, a hosted solution like &lt;a href="https://heroku.com/redis" rel="noopener noreferrer"&gt;Heroku Redis&lt;/a&gt; can provide a low-ops way to put Redis into production without the overhead of maintaining the server.&lt;/p&gt;

&lt;p&gt;Once you’ve experimented with caching, you’ll find that there’s so much more to Redis. Whether it’s Redis’s support for pub/sub messaging, advanced querying with Lua scripting, or creating a cluster for high availability, Redis can take a first-class position in your app’s data layer.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>redis</category>
      <category>database</category>
      <category>sql</category>
    </item>
  </channel>
</rss>
