<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Self Modifying Code - Medium]]></title>
        <description><![CDATA[A place for code snippets and tutorials that make a programmer’s life easier. - Medium]]></description>
        <link>https://medium.com/self-modifying-code?source=rss----a66001474fea---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Self Modifying Code - Medium</title>
            <link>https://medium.com/self-modifying-code?source=rss----a66001474fea---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 17 May 2026 03:17:11 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/self-modifying-code" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Increment Build Numbers in XCode with 3 lines of code!]]></title>
            <link>https://medium.com/self-modifying-code/increment-build-numbers-in-xcode-with-3-lines-of-code-9e59f826e47d?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/9e59f826e47d</guid>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[shell-script]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Thu, 14 Jan 2021 17:32:24 GMT</pubDate>
            <atom:updated>2021-01-14T18:20:25.516Z</atom:updated>
            <content:encoded><![CDATA[<h3>Automatic Build Numbers in XCode with 3 lines of code!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fxHhOauh0daInwpzytWS3w.jpeg" /></figure><p>Here is how to automatically increment your project’s build number using only 3 lines of code!</p><ol><li>Go to <strong><em>Targets</em></strong> &gt; <strong><em>MyFunApp</em></strong> and click on the<em> </em><strong><em>Build Phases</em></strong> tab</li></ol><p>2. Click the <strong>+</strong> button in the top left corner of the Build Phases area, select <strong><em>New Run Script Phase</em></strong></p><p>3. We want this to run after <strong><em>Link Binary with Libraries</em></strong>, so drag <strong><em>Run Script</em></strong> below <strong><em>Link Binary with Libraries</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/697/1*jD7H8jvpHzjAOSqFLnTleQ.gif" /><figcaption>Add new Run Script to Build Phases</figcaption></figure><p>4. Change Shell to <strong><em>/bin/bash </em></strong>and paste the below code in the script area as show in <strong><em>Example 2</em></strong>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d46b59799892b975a1a5ccf38e3bd108/href">https://medium.com/media/d46b59799892b975a1a5ccf38e3bd108/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*sNpLwSyVvpVFJW2aJWoK7A.gif" /></figure><p>5. That’s it. Now when you <strong><em>Build</em></strong> your project, the build number will auto increment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*zXi5ysboHpCJBuV_RwCDXw.gif" /><figcaption>Auto-incrementing Build number</figcaption></figure><p><strong>How to debug issues</strong></p><p>For some of you this process will work out of the box and for some of you this process will not work. So what’s going on?</p><p>We can open the <strong><em>Report Navigator. </em></strong>On the left you’ll see your most recent build event. Click on it and scroll down to <strong>Run Script</strong> and click the <strong>More…</strong> link.</p><p>You can see that there was a <strong><em>Syntax Error</em></strong> for the token <strong>CURRENT_PROJECT_VERSION. </strong>This is the most common issue you’ll run into.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*Owtu70VmzArWlFENBLWPfA.gif" /><figcaption>Report Navigator</figcaption></figure><p>The process we are using to increment the build number reads your project’s <strong><em>Info.plist</em></strong>. If we open, <strong><em>Info.plist</em></strong>, you will see in the Bundle Version key a value of <strong>`$(CURRENT_PROJECT_VERSION)`</strong></p><p>If you have ever manually entered a bundle version on the <strong><em>General</em></strong> tab of your Target, then XCode will place <strong>`$(CURRENT_PROJECT_VERSION)` </strong>in the <strong>Info.plist. </strong>Replace the entire value to the number you want your <strong><em>Build Number</em></strong> to start at and press <strong><em>Enter</em></strong>. Next time you build, the <strong><em>Build Number </em></strong>will increment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*OwFSC4fbFnE33u5mGdDncQ.gif" /></figure><p>That’s it. This is just another tool to add to your toolkit. This is Part 1 in this series. In Part 2, I’ll show you how to change other key/values in your project.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e59f826e47d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/increment-build-numbers-in-xcode-with-3-lines-of-code-9e59f826e47d">Increment Build Numbers in XCode with 3 lines of code!</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why you should be using rsync to copy files remotely]]></title>
            <link>https://medium.com/self-modifying-code/why-you-should-be-using-rsync-to-copy-files-remotely-37f53061e22c?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/37f53061e22c</guid>
            <category><![CDATA[rsync]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[filesystem]]></category>
            <category><![CDATA[command-line]]></category>
            <category><![CDATA[ssh]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Tue, 17 Mar 2020 20:10:05 GMT</pubDate>
            <atom:updated>2020-03-11T15:16:01.054Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FeDZXkfBGku8vWbYMFSwaw.jpeg" /></figure><p>I recently wrote about using scp to copy files, while that is still perfectly valid, scp had a few limitations. So let’s look at rsync for copying files to a remote computer. Depending upon your use case, you can decide which one works for you.</p><p>rsync compares the data you are sending and receiving so it doesn’t have to resend data that was already previously sent, saving you extra time and bandwidth.</p><p>If you are copying files to remote machine regularly, use the rsync command. Depending on your need, it’s probably a good idea to just use rsyncfor all file moves inter-system.</p><p>Syntax: rsync [options] &lt;source&gt; &lt;destination&gt;</p><p><strong>An example:</strong></p><p>rsync -av /path/to/folder/ remote_computer:/remote/path/to/folder/</p><p>The beauty of rsync is that it will synchronize a local directory with a remote directory!</p><p>If you run the same command a second time, the contents of the local directory (which have not changed) will not be transferred! This is way more efficient than running scp and copying everything every time the command is run.</p><p>The rsync options that I use the most frequently are:</p><p>-a : Archive mode (includes default common options like preserving symlinks)<br> -v : Verbose mode show files as they are being moved<br> -P : Show progress of the files as they are being transferred. Notice that’s a capital ‘<em>P’</em>.</p><p>— delete : Delete files from the destination folder that are not in the local folder. This is useful to keep the remote folders cleaned up and better in sync. If it’s not in the local folder, it’s getting deleted on the remote folder.</p><p><strong>An example using options:</strong></p><p>rsync -Pav --delete /path/to/folder/ remote_computer:/remote/path/to/folder/</p><p>For more options check out the rsync manual page: <a href="https://linux.die.net/man/1/rsync">https://linux.die.net/man/1/rsync</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=37f53061e22c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/why-you-should-be-using-rsync-to-copy-files-remotely-37f53061e22c">Why you should be using rsync to copy files remotely</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing Your Android Project Using Gradle Properties]]></title>
            <link>https://medium.com/self-modifying-code/managing-your-android-project-using-gradle-properties-ab5a363351e6?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/ab5a363351e6</guid>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[gradle]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Mon, 16 Mar 2020 18:23:09 GMT</pubDate>
            <atom:updated>2020-03-16T18:23:09.382Z</atom:updated>
            <content:encoded><![CDATA[<p>You probably have some static file <strong><em>AppConfig.java</em></strong> that contains some constants for your Android application. Maybe you’re using a strings resource file or just hard coding your various API keys, URLs and other settings in your Android app. In this tutorial, I will show you how to use Gradle property files to modularize your configuration. These properties will then be compiled into the <strong><em>BuildConfig.java</em></strong> file. Instead of typing out every key and value into your buildConfig section, we can do it dynamically.</p><p>The <strong><em>build.gradle</em></strong> file is used as a “template” to generate your <strong><em>BuildConfig.java</em></strong> file behind the scenes.</p><h4>Let’s start with a simple example.</h4><p>Switch to the <strong>Project View </strong>(mostly likely you’re in the <strong>Android View</strong>), of Android Studio.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/358/1*O1XBakvxWGbAIyi8UBNswg.png" /><figcaption>Switched to Project View</figcaption></figure><p>Right-click your application’s root project folder and select <em>New &gt; File</em>. Name it <strong><em>demo.properties</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/1*GvvjmzzTJJCc38ud_i8G2w.png" /></figure><p>Open that file and add</p><p>MY_CUSTOM_URL=<a href="http://www.google.com">http://www.google.com</a></p><p>Now open the <strong><em>build.gradle</em></strong> file, scroll to the bottom and start by defining the name of our file.</p><p>def propFile = new File(‘demo.properties’)</p><p>We will be reading in the properties file and line-by-line and adding those properties to the build config section.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82b58a6ea92df64348179cd0f3a04e75/href">https://medium.com/media/82b58a6ea92df64348179cd0f3a04e75/href</a></iframe><p>You should see the Gradle message letting you know that the Gradle file has changed and needs to be re-synced. Click the Sync Now button.</p><p>After syncing, you can test if everything worked by opening one of your Activities or Fragments and adding the line:</p><p>Log.v(“MyActivity”, BuildConfig.MY_CUSTOM_URL);</p><p>You can also click the <strong><em>BuildConfig</em></strong> class name and press CMD+B(or CTRL+B on Windows) to open that file. You should see your key/values have been added. The <strong><em>BuildConfig.java</em></strong> class and its fields can be accessed by our activities directly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/701/1*K6hDzkJmf2XrcIE5EnKz_w.png" /><figcaption>MY_CUSTOM_URL is now included in the BuildConfig</figcaption></figure><p>Now you’re ready to start adding in your own keys and values!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab5a363351e6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/managing-your-android-project-using-gradle-properties-ab5a363351e6">Managing Your Android Project Using Gradle Properties</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create a Global GitIgnore Step-by-Step for MacOS and Windows]]></title>
            <link>https://medium.com/self-modifying-code/create-a-global-gitignore-step-by-step-for-macos-and-windows-31a765291409?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/31a765291409</guid>
            <category><![CDATA[productivity]]></category>
            <category><![CDATA[automation]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Tue, 10 Mar 2020 15:31:01 GMT</pubDate>
            <atom:updated>2020-03-10T15:31:01.070Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AMWD5OKi-HK2XEV_E3FmgA.jpeg" /></figure><p>Make your life easier with a Global GitIgnore.</p><h4><strong>Why?</strong></h4><p>I got tired of copying and pasting the same set of ignore files for every project I created. Now, I keep all my OS and IDE specific files in a global gitignore and keep project specific files in the project’s gitignore.</p><h4>What files go in a global gitignore file?</h4><p>Operating system files should go in a global gitignore. This might include things like your IDEs settings, or temp files, metadata files, icon cache files etc..</p><p>Files you want to ignore in your project, should go into the project’s .gitignore.<br>Things like vendor packages, composer packages, cocoa-pods, Python virtual environments, Gradle files, basically any 3rd-party library. If you use some sort of package management system, then those packages should be in the <em>.gitignore</em>. Provided of course, you keep the definition file in your project that allows you to re-download those libraries.</p><h4><strong>On MacOS</strong></h4><p>Open Terminal and run the below command to create a new file. You don’t have to name it .gitignore_global you could name it .gitignore I appended <em>_global</em> so future me will remember what the file is used for.</p><p>touch ~/.gitignore_global</p><p>Now, let’s configure Git to use the exclude file ~/.gitignore_global for all Git repositories.</p><p>git config --global core.excludesfile ~/.gitignore_global</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/568/1*BlxEicGLP4wbrdx6mMX5Ww.png" /></figure><p>Finally, open your new <em>gitignore_global</em> in Notepad or TextEdit and fill it with your computer/IDE level exclusions.</p><h4><strong>On Windows</strong></h4><p>Open Git Bash.</p><p>Navigate to the root folder of your user profile usually at C:\Users\{myusername}\and create a <em>.gitignore_global</em> file.</p><p>Then run</p><pre>git config --global core.excludesfile &quot;%USERPROFILE%\.gitignore&quot;</pre><h4><strong>Using Windows PowerShell?</strong></h4><p>Run:git config --global core.excludesfile &quot;$Env:USERPROFILE\.gitignore&quot;</p><h3><strong>Verify it</strong></h3><p>Not every system is setup the same. So you can verify your <strong>MacOS, Windows</strong> or <strong>Windows PowerShell</strong> config file is correct by running:</p><pre>git config --global core.excludesfile</pre><p>The output should be the full path to your file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/436/1*clKt7B74ozuQqvmrbnevlg.png" /><figcaption>If you see <strong><em>%USERPROFILE%</em></strong> then you have a problem.</figcaption></figure><p>If you see $HOME/.gitignore_global or %USERPROFILE%\.gitignore then something has gone wrong.</p><p>On Windows, if you can’t get it to work using the %USERPROFILE% variable, you can just run from the bash prompt</p><p>git config — global core.excludesfile ~/.gitignore_global</p><p>Then, navigate into that folder and open the .gitconfig file (it’s hidden) and manually edit the excludesfile <em>path</em> to to reflect the location of your .gitignore_global</p><p>It might looks something like this:</p><p>[core]<br> excludesfile = C:\Users\adammcelhaney\.gitignore_global</p><h4>Special Note</h4><p>Git will <strong><em>not</em></strong> ignore a file that was already tracked before a rule was added to this file to ignore it. If you find you have checked in a file that you need to be un-tracked, you can run:</p><pre>git rm --cached filename</pre><h4><strong>Need suggestions on what to add to your Global GitIgnore?</strong></h4><p>Be sure to check Github’s own repo of suggested ignore files: <a href="https://github.com/github/gitignore">https://github.com/github/gitignore</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=31a765291409" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/create-a-global-gitignore-step-by-step-for-macos-and-windows-31a765291409">Create a Global GitIgnore Step-by-Step for MacOS and Windows</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Copy Files To A Remote Computer Using The Command Line]]></title>
            <link>https://medium.com/self-modifying-code/copy-files-to-a-remote-computer-using-the-command-line-e5097fad1d05?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/e5097fad1d05</guid>
            <category><![CDATA[linux-tutorial]]></category>
            <category><![CDATA[command-line]]></category>
            <category><![CDATA[ssh]]></category>
            <category><![CDATA[remote-working]]></category>
            <category><![CDATA[linux]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Mon, 09 Mar 2020 15:16:01 GMT</pubDate>
            <atom:updated>2020-03-09T15:16:00.786Z</atom:updated>
            <content:encoded><![CDATA[<h3>Copy Files to a Remote Computer Using the SCP Command</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IQ9avh36tcuZG0hG5HyGLw.jpeg" /></figure><p>You don’t have to be logged in with SSH to copy files from your local machine to a remote computer. When you use scp on your local computer, the scp process will log you into the remote server, copy the file, then log you out again all in one go.</p><p><strong>Syntax</strong>: scp &lt;source&gt; &lt;destination&gt;</p><p>To copy a file from your <em>Local</em> computer to a <em>Remote</em> computer:</p><p>scp /path/to/file username@remote:/path/to/destination</p><p>To copy a file from <em>Remote</em> to <em>Local </em>while logged in to Remote:</p><p>scp username@remote:/path/to/file /path/to/destination</p><p>If you want to preserve the file’s metadata (modification times, modes, etc..) use the -p option after the scp command.<br>scp -p &lt;source&gt; &lt;destination&gt;</p><p>If you want to copy all the folders recursively</p><p>scp -r &lt;source&gt; &lt;destination&gt;</p><blockquote>Note: Keep in mind that this won’t preserve symlinks</blockquote><p>It’s considered a good practice to use -rp when coping files.</p><p>An example:</p><p>scp -rp /My/Local/Folder/File.ext root@192.168.1.101:/my/remote/folder/</p><p>Some caveats with SCP</p><ul><li>You <strong>can’t</strong> move files between two remote computers. Either the source or destination must be a file hosted locally <strong>relative</strong> to the machine you are logged into. However, if you log in to a remote machine with ssh, you can then copy files from that computer to another remote computer from machine you are remotely logged into command-line.</li><li>You can only scp to a folder on a remote computer that you have permission to.</li><li>The order of options is important! Switching from -rp to -pr, won’t copy the folders but <em>only</em> their contents to the target directory.</li></ul><p>For more options check the scp man page <a href="https://linux.die.net/man/1/scp">https://linux.die.net/man/1/scp</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e5097fad1d05" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/copy-files-to-a-remote-computer-using-the-command-line-e5097fad1d05">Copy Files To A Remote Computer Using The Command Line</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using ReCaptcha V3 and Laravel in 2020]]></title>
            <link>https://medium.com/self-modifying-code/using-recaptcha-v3-and-laravel-in-2020-645e5ffec6c9?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/645e5ffec6c9</guid>
            <category><![CDATA[recaptcha]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Mon, 09 Mar 2020 12:42:21 GMT</pubDate>
            <atom:updated>2020-11-03T16:53:21.569Z</atom:updated>
            <content:encoded><![CDATA[<h3>ReCaptcha V3 and Laravel in 2020: A step-by-step guide.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OxNuWRZieRd9PqsXHX4X4g.jpeg" /></figure><p>While this tutorial applies mostly to Laravel, the validation and client side examples can be applied to any project. Your implementation may be a little different than mine, so I have tried to generalize this enough that you should be able to massage this example into any of your own projects.</p><h4><strong>Create ReCaptcha Account</strong></h4><p>Start by heading over to <a href="http://www.google.com/recaptcha">www.google.com/recaptcha</a> and add a new site.</p><p>Enter the domain name where your form lives and give it an identifying label. It can be anything you want since it’s just for your reference.</p><p>If you want to test from your local computer (and not from your site directly), I recommend creating another separate site in the admin console and add <em>localhost</em> and <em>127.0.0.1</em> to the list of domains and use those keys for development while using the keys for your domain in production.</p><blockquote>Technically, can you just add <em>localhost</em> and <em>127.0.0.1</em> to the same list as the one with your domain on it, but that’s not really a good practice.</blockquote><p>When you <strong>Save</strong>, you’ll be taken to a screen that contains your <strong><em>public</em></strong> and <strong><em>private</em></strong> keys. Copy those down making sure you know which one is public and which is private.</p><p>In your Laravel project, open your <em>.</em><strong><em>env</em></strong> file and add two new key/values to the bottom of your .<strong><em>env</em></strong> file. You can name them whatever you like, but I chose the below format. Paste the keys you just copied from the Google ReCaptcha site.</p><p>GOOGLE_CAPTCHA_PUBLIC_KEY=6LMt06UdrMt06UhiUAAAAAN3IRTYMd6NOKfdadc<br> GOOGLE_CAPTCHA_PRIVATE_KEY=4pzo1dJefhkbcIC1qjo1dJeeevxFTer5UHGmrt</p><h4><strong>Add Composer Package</strong></h4><p>Update <strong>composer.json</strong> and add <em>google/recaptcha</em> to the <strong><em>require</em></strong> object and use the most recent version.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/284/1*aIs1hJr0M9Luwqxgj7muVg.png" /></figure><p>Note: If you get the error during installation:</p><blockquote>Composer update: The requested PHP extension ext-http missing</blockquote><p>Look in your<strong> composer.json</strong> <em>require</em> object to see if it contains <strong>“ext-http”: “*” </strong>If so, remove it. PHPStorm and some other IDEs will add key/value to remove any lint and other code warnings.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/277/1*flfbSBzMP2Aw60dlkp13Eg.png" /><figcaption>Only remove “ext-http” if you get the error.</figcaption></figure><p>Once composer has installed the ReCaptcha package, you’re now ready to move on.</p><h4><strong>Update the Blade File</strong></h4><p><em>Note: This section can apply to any project, not just a Laravel project. </em><br>Open the blade file that holds the form you want to protect with ReCaptcha.</p><p>Find the start of your <em>form</em> tag and add a hidden input field called <em>recaptcha_token</em>. I added mine directly after the <strong>@csrf</strong> directive.</p><pre>&lt;input type=’hidden’ name=’recaptcha_token’ id=’recaptcha_token’&gt;</pre><p>In a moment, we will be creating a Rule class to handle validation. Depending on how you handle errors, you may want to show any ReCaptcha error messages on the form. We can do this by:</p><pre>{{ — Show the user the recaptcha_token error. — }}<br>@if($errors-&gt;has(‘recaptcha_token’))<br>    {{$errors-&gt;first(‘recaptcha_token’)}}<br>@endif</pre><p>Next, we need to link to the Google ReCaptcha Service and pass in the our public <strong><em>env</em></strong> key.</p><p>Add the below JavaScript to the <em>scripts</em> section of your Blade, html file or however you handle JavaScript.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c9b6872dfa6bcd85196128d8def1da4/href">https://medium.com/media/5c9b6872dfa6bcd85196128d8def1da4/href</a></iframe><h4><em>Creating the Rule</em></h4><p>Run the <em>artisan</em> command to make a new rule.</p><pre>php artisan make:rule ReCaptchaRule</pre><p>When that command has finished, open up the new file so we can edit it. It is stored in the <strong><em>app/Rules</em></strong> folder.</p><p>Add the statement <em>use ReCaptcha\ReCaptcha;</em> a the top of the class. I also would like to be able to customize the returned error message based upon the response from Google, so I’ll add a private <strong><em>$error_msg</em></strong> property to the top of the ReCaptchaRule class that will be returned in the rule’s <em>message()</em> function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/1*iviHeQCxcS474jBZfQPqLg.png" /><figcaption>Use statement and error_msg property</figcaption></figure><p>In the <em>passes() </em>function, let’s check to very that the <strong>$value</strong> is not empty, if so, set the error message to show that the field is required.</p><pre>if (empty($value)) {<br>   $this-&gt;error_msg = &#39;:attribute field is required.&#39;;<br>   <br>   return false;<br>}</pre><p>Next, you’ll create a new ReCaptcha object and pass in your private <em>.</em><strong><em>env</em></strong> key.</p><pre>$recaptcha = new ReCaptcha(env(&#39;GOOGLE_CAPTCHA_PRIVATE_KEY&#39;));</pre><p>ReCaptcha requires some configuration before it validates the passed token.</p><p>Set the hostname to your <em>SERVER_NAME. </em>This should match the domain you listed in the Google ReCaptcha admin console.</p><p>Next, you’ll need to set your <em>Score Threshold</em>. This is will be a value between 0 and 1. The threshold really depends on your sites needs. The higher the threshold the more strict ReCaptcha is in trying to determine if a user is a bot or not.</p><p>Start with 0.5 and work your way up to fit your needs.</p><p>Finally, we will verify the passed token from the form field and the user’s IP address storing the <em>response</em> in a variable.</p><pre>$resp      = $recaptcha-&gt;setExpectedHostname($_SERVER[&#39;SERVER_NAME&#39;])<br>                  -&gt;setScoreThreshold(0.5)<br>                  -&gt;verify($value, $_SERVER[&#39;REMOTE_ADDR&#39;]);</pre><p>Luckily, the ReCaptcha package we installed with <em>composer</em> has some nice functions to use against the response.</p><p>If the response is <strong>NOT</strong> successful, we can set various error messages depending on the response. If the returned score is less than our threshold, we will let the user know they failed the ReCaptcha test.</p><p>Otherwise, they have passed the ReCaptcha test so we need to <strong>return true</strong> to finish out the rule.</p><pre>if (!$resp-&gt;isSuccess()) {<br>   $this-&gt;error_msg = &#39;ReCaptcha field is required.&#39;;<br>   <br>   return false;<br>}<br><br>if ($resp-&gt;getScore() &lt; 0.5) {<br>   $this-&gt;error_msg = &#39;Failed to validate captcha.&#39;;<br>   <br>   return false;<br>}<br><br><br>return true;</pre><p>My finished Rule class looks like this:</p><pre>class ReCaptchaRule implements Rule<br>{<br>   <br>   private $error_msg = &#39;&#39;;<br><br>   public function __construct()<br>   {}<br>   <br>   public function passes($attribute, $value)<br>   {<br>      if (empty($value)) {<br>         $this-&gt;error_msg = &#39;:attribute field is required.&#39;;<br>         <br>         return false;<br>      }<br>      <br>      $recaptcha = new ReCaptcha(env(&#39;GOOGLE_CAPTCHA_PRIVATE_KEY&#39;));<br>      $resp      =   $recaptcha-&gt;setExpectedHostname($_SERVER[&#39;SERVER_NAME&#39;])<br>                        -&gt;setScoreThreshold(0.5)<br>                        -&gt;verify($value, $_SERVER[&#39;REMOTE_ADDR&#39;]);<br>      <br>      if (!$resp-&gt;isSuccess()) {<br>         $this-&gt;error_msg = &#39;ReCaptcha field is required.&#39;;<br>         <br>         return false;<br>      }<br>      <br>      if ($resp-&gt;getScore() &lt; 0.5) {<br>         $this-&gt;error_msg = &#39;Failed to validate captcha.&#39;;<br>         <br>         return false;<br>      }<br>      <br>      <br>      return true;<br>      <br>   }<br>   <br>   public function message()<br>   {<br>      return $this-&gt;error_msg;<br>   }<br>}</pre><h4>Update your FormRequest</h4><p>If you’re submitting a form, chances are you’re using a FormRequest (and you should). In my example my <em>FormRequest </em>class is called <em>ContactUsFormRequest</em>.</p><p>In <em>rules()</em> method, where you add all the the fields validation rules, you’ll want to add another rule to the <strong><em>rules</em></strong> array for your new ReCaptcha field you added in your blade file.</p><pre>‘recaptcha_token’ =&gt; [‘required’, new   ReCaptchaRule($this-&gt;recaptcha_token)]</pre><p>The key name ‘<em>recaptcha_token</em>’ is the <strong>name</strong> of that hidden field we added to the form earlier. I chose to make it required and then pass the form field’s value to the ReCaptcha rule as a parameter.</p><p>So my <em>ContactUsFormRequest</em> looks something like this now.</p><pre>public function rules()<br>{<br> $rules = [‘name’ =&gt; [‘required’, ‘min:3’, ‘max:25’,<br> ‘email’ =&gt; [‘required’, ‘email’],<br> ‘message’ =&gt; [‘min:10’],<br> ‘recaptcha_token’ =&gt; [‘required’, new   ReCaptchaRule($this-&gt;recaptcha_token)]<br> ];<br> <br> return $rules;<br>}</pre><blockquote>Note: I don’t have to add any extra error messages the <strong>ContactUsFormRequest</strong>’s <em>messages()</em> function, since that is now handled by the Rule class we created.</blockquote><p>That’s it.</p><p>Now you’re ready to protect your form using ReCaptcha V3!</p><h4><strong>BONUS ROUND</strong></h4><p><strong>To remove the “ReCaptcha logo” from your site:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/68/1*HUGF2SV5ZKWxuC0aGb7pLw.png" /><figcaption>This might be lurking the corner of your site.</figcaption></figure><p>You are allowed to hide the badge as long as you include the ReCaptcha branding visibly on your form. <br>See <a href="https://developers.google.com/recaptcha/docs/faq">https://developers.google.com/recaptcha/docs/faq</a> for more on what you’re allowed to do.</p><p>To hide the badge simply add the CSS style</p><p>.grecaptcha-badge { visibility: hidden; }</p><p>Next include the ReCaptcha branding text, by adding</p><p>This site is protected by ReCaptcha and the Google<br> &lt;a href=”https://policies.google.com/privacy&quot;&gt;Privacy Policy&lt;/a&gt; and<br> &lt;a href=”https://policies.google.com/terms&quot;&gt;Terms of Service&lt;/a&gt; apply.</p><p>For example:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/586/1*8GDMIAgHE_ADFXGiqUgrUA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=645e5ffec6c9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/using-recaptcha-v3-and-laravel-in-2020-645e5ffec6c9">Using ReCaptcha V3 and Laravel in 2020</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Break-up Very Long LogCat Message]]></title>
            <link>https://medium.com/self-modifying-code/break-up-very-long-logcat-message-7c15d9491faa?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/7c15d9491faa</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Fri, 06 Mar 2020 16:16:01 GMT</pubDate>
            <atom:updated>2020-03-06T16:16:01.360Z</atom:updated>
            <content:encoded><![CDATA[<h3>Break-up Very Long LogCat Messages</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E6mYJ-x3YiluZVujmwEVMQ.jpeg" /></figure><p>I recently was working with some large JSON objects and needed to output the contents to the console. The JSON was well over 2,000 characters long and wouldn’t fit in Android Studio’s LogCat console window cleanly.</p><p>So I created this function that would take any string break it into smaller chunks for better output. Enjoy!</p><h3><strong>Java</strong></h3><pre>public final class DebugUtilis {<br><br>    public static int <em>_charLimit </em>= 2000;<br><br>    public static int v(String tag, String message) {<br><br>        // If the message is less than the limit just show<br>        if (message.length() &lt; <em>_charLimit</em>) {<br>            return Log.<em>v</em>(tag, message);<br>        }<br>        int sections = message.length() / <em>_charLimit</em>;<br>        for (int i = 0; i &lt;= sections; i++) {<br>            int max = <em>_charLimit</em> * (i + 1);<br>            if (max &gt;= message.length()) {<br>                Log.<em>v</em>(tag, message.substring(<em>_charLimit </em>* i));<br>            } else {<br>                Log.<em>v</em>(tag, message.substring(<em>_charLimit </em>* i, max));<br>            }<br>        }<br>        return 1;<br>    }<br>}</pre><h3>Kotlin</h3><pre>object DebugUtilis {<br>    var _charLimit = 2000<br>    @JvmStatic<br>    fun v(tag: String?, message: String): Int { <br>        // If the message is less than the limit just show<br>        if (message.length &lt; _charLimit) {<br>            return Log.v(tag, message)<br>        }<br>        val sections = message.length / _charLimit<br>        for (i in 0..sections) {<br>            val max = <em>_charLimit</em> * (i + 1)<br>            if (max &gt;= message.length) {<br>                Log.v(tag, message.<em>substring</em>(_charLimit * i))<br>            } else {<br>                Log.v(tag, message.<em>substring</em>(_charLimit * i, max))<br>            }<br>        }<br>        return 1<br>    }<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c15d9491faa" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/break-up-very-long-logcat-message-7c15d9491faa">Break-up Very Long LogCat Message</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Finding Your Android App’s Fingerprint in 2020]]></title>
            <link>https://medium.com/self-modifying-code/finding-your-android-apps-fingerprint-in-2020-826243c99eb6?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/826243c99eb6</guid>
            <category><![CDATA[android-studio]]></category>
            <category><![CDATA[play-store]]></category>
            <category><![CDATA[certification]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[android-app-development]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Wed, 26 Feb 2020 20:29:23 GMT</pubDate>
            <atom:updated>2020-02-12T19:33:27.396Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eozR87r1Is2O9Y8ErdlOAA.png" /></figure><p>No, I’m not talking bio-metric security. I am talking about about app authority and security.</p><h3>What is it?</h3><p>The short answer is — it is a method of authenticating your app. The long answer is — the fingerprint is used to sign certificates, sign data that gets sent over the Internet, and validate information it may receive from 3rd-parties.</p><h3><strong>What is is used for?</strong></h3><p>Many services require your app’s fingerprint as a method for verification to use their service. Services such as Square and Google Maps use your app’s fingerprint during their certificate signing. This helps to thwart would-be imitators from impersonating your application to access their platform.</p><p>Your app generally has two fingerprints — a debug version and a release version. Which one you supply to whatever service you are using that requires it, will depend upon what environment you’re working in. Obviously, if you are tinkering around in a sandbox, you’ll use the debug version and when you’re ready to go live, the release version.</p><p>It sometimes goes by other names that you have probably searched for as well:</p><ul><li>Signed Certificate Fingerprint</li><li>Android SHA-1 Certificate</li><li>Android SHA-256 Certificate</li></ul><h3>The Command Line</h3><p>Open your Terminal (Mac) or Command Prompt (Mac)</p><p>The general formula goes something like this:</p><pre>keytool [options] -keystore PATH_TO_KEYSTORE  -alias ALIAS_NAME</pre><p><strong>keytool</strong> is the command line program used to access and manipulate the <em>keystore</em> file.</p><p><strong>PATH_TO_KEYSTORE</strong> is the full path to where your Android Apps <em>keystore</em> is. Typically stored in safe place outside of your app project. I keep mine in a secure storage, since I only use it to sign my apps when it is time to deploy or publish a new version. Never store your <em>keystore</em> file in the cloud! If someone gets it, they can create new apps and sign them as if they are yours.</p><p><strong>ALIAS_NAME</strong> is a unique identifier that helps you locate the specific key your looking for, usually the name of your app. If a <em>keystore</em> is a phone book, then <em>ALIAS_NAME</em> would be the person you are looking up and the fingerprint would be the phone number. Aliases are case-insensitive; so <em>MyGreatApp</em> and <em>mygreatapp</em> would refer to the same entry.</p><h3>Finding Your Production Fingerprint</h3><p>An example if the key store was located on my desktop:</p><pre>keytool -list -v -keystore /Users/adammcelhaney/Desktop/adams.keystore  -alias MyGreatApp_Alias_Production</pre><p>You’ll be asked to enter the password you used when you generated the <em>keystore</em>, so have it handy.</p><pre>(adammcelhaney):&gt; ~/Desktop/GitHub/MyGreatApp: keytool -list -v -keystore /Users/adammcelhaney/Desktop/adams.keystore  -alias MyGreatApp_Alias_Production</pre><pre>Enter keystore password:</pre><pre>Alias name: MyGreatApp_Alias_Production<br>Creation date: Jan 22, 2020<br>Entry type: PrivateKeyEntry<br>Certificate chain length: 1<br>Certificate[1]:<br>Owner:  CN=Adam McElhaney, OU=&quot;MyCompany, Inc&quot;, O=&quot;MyCompany, Inc&quot;, L=New York City, ST=New York, C=US<br>Issuer: CN=Adam McElhaney, OU=&quot;MyCompany, Inc&quot;, O=&quot;MyCompany, Inc&quot;, L=New York City, ST=New York, C=US<br>Serial number: 4f393733<br>Valid from: Mon Jan 22 08:15:00 EST 2020 until: Fri Jul 01 11:59:59 EDT 2040<br><strong>Certificate fingerprints</strong>:<br> <strong>MD5</strong>:  <em> AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99</em><br> <strong>SHA1</strong>:  <em>99:88:77:66:55:44:33:22:11:00:FF:EE:DD:CC:BB:AA:99:88:77</em>  <br> <strong>HA256</strong>: <em>00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22</em><br>    Signature algorithm name: SHA1withRSA<br>    Version: 3</pre><p>Depending upon what level of encryption is needed by the service requiring your app’s fingerprint, you’ll see usually three different fingerprints. MD5, SHA1 and HA256.</p><p>The hex code looking value is what you’re after. 99% of the time it’s the SHA1.</p><h4><strong>Debug Fingerprint</strong></h4><p>Same idea as above, though Android Studio will automatically generate a debug version of your fingerprint for you. Usually stored in ~/.android\debug.keystoreif you’re on a Mac and C:\Users\USERNAME\.android\debug.keystore if you’re on Windows.</p><pre>keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android</pre><h3>Using Android Studio</h3><p>Another way, is to use the <em>Gradle</em> task in <strong>Android Studio</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*Mt24VoeEtQuM-VJD7cryfA.png" /></figure><p>From within <strong>Android Studio</strong>, on the right side of the IDE click the <em>Gradle</em> button along the side — <em>Gradle</em> is in vertical lettering. This will show the Gradle tasks pane. Under your MyGreateApplication &gt; Tasks &gt; android you will see a <strong><em>signingReport</em></strong> task. Right-click it and select <strong>Run</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/781/1*Lf6qXFtz0YTQk2eIQutBuQ.png" /><figcaption>All your fingerprints</figcaption></figure><p>This will show you all your fingerprints. Take note of the <em>Variant</em> value when you go to copy keys.</p><p>Enjoy!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=826243c99eb6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/finding-your-android-apps-fingerprint-in-2020-826243c99eb6">Finding Your Android App’s Fingerprint in 2020</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Quick tip: Take High Resolution Full Page Screenshots]]></title>
            <link>https://medium.com/self-modifying-code/quick-tip-take-high-resolution-full-page-screenshots-2268a61656c3?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/2268a61656c3</guid>
            <category><![CDATA[screenshots]]></category>
            <category><![CDATA[quick-tip-tuesday]]></category>
            <category><![CDATA[design-process]]></category>
            <category><![CDATA[high-resolution]]></category>
            <category><![CDATA[print]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Tue, 28 Jan 2020 16:16:01 GMT</pubDate>
            <atom:updated>2020-01-28T16:16:01.168Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sqOk_f6xjuZVCsWYK9ihEQ.png" /><figcaption>Let’s go from blurry partial page screenshots to high-res, full-page in less than 30 seconds.</figcaption></figure><p>I sometimes need to take a high resolution screenshot of an entire website for a print publication.</p><p>I am using <strong>Firefox</strong> for this example. I’m sure it could be adapted for other browsers.</p><p>From within <strong>Firefox</strong>, from the main menu, click <em>Tools &gt; Web Developer &gt; Style Editor</em> (or Shift + F7).</p><p>This will open a new section with a bunch of CSS code. Make sure the first CSS file is selected (it will be different based upon your site) and at the top of the file paste:</p><pre>body {<br>  zoom: 4;  /* zoom factor */<br>  -moz-transform: scale(4);  /* same zoom factor */<br>  -moz-transform-origin: 0 0;<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NvpK5zopwTg8n0yt0p7A3A.png" /></figure><p>I am using <strong>4</strong> as the zoom factor which translates to 400%. Typically, a screenshot is at 72dpi. This zoom level puts us closer to 288dpi —much closer to the standard 300dpi for print or other applications.</p><p>Next, click the <strong>Console</strong> tab in the same window and at the prompt type the below command. That’s two dashes (-) in front of the word fullpage.</p><pre>:screenshot --fullpage</pre><p>Give it a moment and you’ll see a message telling you where your new screenshot is.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*408Z2Qes1MSihjedyWdeoQ.png" /></figure><p>Enjoy your new high-resolution screenshot. You can either refresh the page or delete the CSS code we added to go back to normal.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2268a61656c3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/quick-tip-take-high-resolution-full-page-screenshots-2268a61656c3">Quick tip: Take High Resolution Full Page Screenshots</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sending Email In Laravel 6]]></title>
            <link>https://medium.com/self-modifying-code/sending-email-in-laravel-6-3ae11e01b61c?source=rss----a66001474fea---4</link>
            <guid isPermaLink="false">https://medium.com/p/3ae11e01b61c</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Adam M]]></dc:creator>
            <pubDate>Mon, 27 Jan 2020 16:16:02 GMT</pubDate>
            <atom:updated>2020-01-27T16:16:02.488Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YD9zs8cISOWlQSyZAzP__A.png" /></figure><p>I’m going to show you how to use the Mailable class that was first introduced in Laravel 5.3. To help keep this tutorial clean, I am going to omit any comments, namespaces, or any top level use statements generated by Laravel.</p><h4>Prerequisites</h4><p>You will need:<br> 1. A Laravel 6 project setup<br> 2. Your email provider credentials in your .env file or other configuration file.</p><p>We want to send a welcome email to a user thanking them for signing up. This is only an example how I am calling the <strong>Mailable</strong>, you can call it from wherever you need to.</p><p>In my NewUserController, after my user is created, I am going to send the welcome email. I am also want to pass the User object to Mailable, since it has the new user’s name, email address and many other properties that I might want to include in the email.</p><pre>public function store(){<br> $user = User::create($request);<br> <br> // Send email here <br>}</pre><h4>Creating the Blade view files</h4><p>It is best practice to create two files for email, a plain text version and an <em>html</em> version. The plain text ensures that your email is readable everywhere by most helper services, like <strong><em>Apple Watch</em></strong> or other preview panes. The <em>html</em> version is what most people will see when the open the email to read it.</p><p>Inside your resources &gt; views folder, create a new file called <strong><em>welcome_email</em></strong> and <strong><em>welcome_email_plain</em></strong>.</p><p>Open <strong><em>welcome_email_plain</em></strong> first. I find it easier to focus on just the content and layout in the plain text first so I can organize the information like I want. Afterward opening the <em>html</em> version and just apply styling. I am going to show the creation of the plain text version. Just assume that I have copied and pasted from the plain version to <em>html</em> version.</p><p>$data is the name of the public property we will create in the <strong><em>WelcomeMailable</em></strong> class in a moment. It will be filled with the $user object from inside the controllers store() method. My user model has a <em>first_name</em>, <em>last_name</em>, <em>email_address</em>, <em>user_name </em>and the timestamps.</p><pre>Hello, {{$data-&gt;first_name}} {{$data-&gt;first_name}}</pre><pre>You signed up on {{$data-&gt;created_at}}.</pre><pre>Your login id is {{$data-&gt;email_address}}</pre><pre>Thank you!</pre><blockquote>Now would be the time to copy your plain text email and then paste and style it in your <em>html</em> file.</blockquote><h4>Creating the Mailable class</h4><p>Open <strong>Terminal</strong> and use the make command</p><pre>php artisan make:mail WelcomeMailable</pre><p>This will place the a new file in your \App\Mail folder.</p><p>Open it up so we can begin editing it. From before we know we are going to be passing a User object to this class so we can fill the email with information. Start by add public property called $data. Add $data to the constructor and set the class’s data property.</p><pre>class WelcomeMailable extends Mailable<br>{<br> use Queueable, SerializesModels;<br> public $data;</pre><pre> public function __construct($data){<br>      $this-&gt;data = $data;<br> }</pre><pre> public function build(){<br>   return $this-&gt;from(‘<a href="mailto:welcome@mysite.com">welcome@mysite.com</a>’)<br>               -&gt;bcc(‘<a href="mailto:me@site.com">me@site.com</a>’)<br>               -&gt;subject(‘Welcome To Our Site’);<br>               -&gt;view(‘welcome_email’)<br>               -&gt;text(‘welcome_email_plain’)<br>               -&gt;with($this-&gt;data);<br> }<br>}</pre><p>In the build() method, I am overriding the Mail class’s default <em>from</em> by chaining from() and passing in an email address that I want the email to have appeared to come from. <em>This is completely optional. </em>I have noticed a lot of sites use emails like ‘<a href="mailto:welcome@site.com"><em>welcome@site.com</em></a>’ and ‘<a href="mailto:support@site.com"><em>support@site.com</em></a>’. They usually come with the disclaimer “<em>Please do not reply to this email address, as it is an unattended mailbox.</em>”. This is usually a reason why.</p><p>I also want to be notified when a new user is created, so I just blind carbon-copy bcc() myself and set the subject line.</p><p>I then supply the view() with the name of the <em>html</em> blade version of our email file created. And the text() takes the <em>plain</em> version. I am using with() to pass in our $dataproperty that will populate the email.</p><p>Returning to the store() method (or whatever controller you are using) and add use Illuminate\Support\Facades\Mail; at the top so the class can have access to the <em>Mail</em> facade.</p><p>Jump to the store() function and below the new user creation line, let’s call add the call to our new <strong>Mailable</strong> class and pass in the $user object.</p><pre>public function store(){<br> $user = User::create($request);<br> <br> // Send email here <br> Mail::to($user-&gt;email_address)-&gt;send(new WelcomeMailable($user));</pre><pre>}</pre><p>That’s all there is to it! Next time you have a new user created they will be sent a welcome email and you will be notified also.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3ae11e01b61c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/self-modifying-code/sending-email-in-laravel-6-3ae11e01b61c">Sending Email In Laravel 6</a> was originally published in <a href="https://medium.com/self-modifying-code">Self Modifying Code</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>