Supercharge Your Laravel Development and Get AI to Understand Your Models
Hey there, Laravel enthusiasts! Today, I’m diving into a nifty trick that’ll make getting AI to understand your Laravel model structures a breeze. We’ll harness the power of bash scripting and AI to analyze our migrations quickly and efficiently. Let’s get started!
The Problem: Getting AI to Return Code For your Project Setup Easily
As our Laravel projects grow, so does the complexity of our database structures. Migrations pile up, relationships intertwine, and before you know it, you’re drowning in a sea of Schema::create
 and up
 functions. Wouldn’t it be great to get a bird’s-eye view of our models without manually sifting through dozens of files? What if you could get AI to understand your Laravel project without adding every file to the chat window?
The Solution: Bash + AI = Developer’s Best Friend
Here’s where our dynamic duo comes in a clever bash one-liner and your favorite AI chat tool (like ChatGPT or Claude). We’ll use bash to extract the relevant parts of our migrations and then feed that information to an AI for analysis and insights.
Step 1: The Magical Bash One-Liner
Here’s the one-liner code to copy and paste:
for file in *.php; do echo -e "\n\`\`\`\n${file%.*}:\n\`\`\`\n"; sed -n '/Schema::create/,/^ }/p' "$file"; echo -e "\n\`\`\`"; sed -n '/public function up/,/^ }/p' "$file" | sed '1d;$d'; echo -e "\`\`\`\n"; done
First, let’s break down our bash sorcery to understand what’s going on in an easier-to-read format:
for file in *.php; do
echo -e "\n\`\`\`\n${file%.*}:\n\`\`\`\n"
sed -n '/Schema::create/,/^ }/p' "$file"
echo -e "\n\`\`\`"
sed -n '/public function up/,/^ }/p' "$file" | sed '1d;$d'
echo -e "\`\`\`\n"
done
Just add | pbcopy to have it copied directly to your clipboard on Mac:
for file in *.php; do echo -e "\n\`\`\`\n${file%.*}:\n\`\`\`\n"; sed -n '/Schema::create/,/^ }/p' "$file"; echo -e "\n\`\`\`"; sed -n '/public function up/,/^ }/p' "$file" | sed '1d;$d'; echo -e "\`\`\`\n"; done | pbcopy
This command does the following:
- Loops through all PHP files in the current directory
- Extracts the
Schema::create
function contents - Extracts the
up
function contents (minus the function declaration) - Formats the output with the filename and proper Markdown code blocks
Step 2: Running the Command
- Open your terminal and navigate to your Laravel project’s migrations directory.
- Copy the bash one-liner above.
- Paste it into your terminal and hit Enter.
- Watch as it generates a nicely formatted output of your migrations!
Step 3: Feeding the Output to AI
Please copy the entire output from your terminal and paste it into your AI chat of choice with your preferred prompt. I usually start with this prompt:
"Analyze these Laravel migrations and understand the database and model structure, including relationships. For all conversations in this chat, refer to these migrations:"
{output here}
Generate a diagram
Here are some additional prompts you can optionally pair with the output to extract valuable insights and improvements:
- “Identify any potential relationships between these models based on the migrations.”
- “Suggest improvements or potential issues in this database design.”
- “Take this example of JSON output and generate the code to create the [model name] with its relations.”
The Benefits: Why This Approach Rocks
- Time-saver: No more manual searching through migration files or copying content manually or individually.
- Comprehensive view: Get a complete picture of your database structure in one go.
- AI-powered insights: Leverage AI to spot patterns, suggest optimizations, explain complex relationships, and generate code faster.
- Learning tool: Great for understanding legacy projects or onboarding new team members.
Wrapping Up
There you have it, folks! With this simple bash one-liner and the power of AI, you can transform how you analyze and understand your Laravel database structures and output code. Give it a try on your next project, and watch your productivity soar!
Remember, tools like these are meant to augment your skills, not replace them. Always review AI suggestions critically and trust your developer instincts.
How to Take Ownership of Files and Folders Using PowerShell
Ever had to take ownership of a bunch of files and folders? It’s a pain, right? Well, not anymore!
The Problem
Picture this: You’ve just gotten an external hard drive from a dead computer and need to access the files. But wait! You don’t have the correct permissions. I had to do this, and setting the file permissions through Explorer was failing randomly. It appears that the folders all had different permissions, and the propagation was failing.
The Solution
I’ve got a PowerShell script that’ll save you time. It does two things:
- Takes ownership of a folder and all its subdirectories and files (recursively) and sets the owner to the current logged-in user
- Adds the current user to the permissions with full control
The Script
First, here’s the script. Don’t worry, I’ll break it down for you:
# Ensure the script is running with administrator privileges
if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Write-Warning "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
Break
}
# Get the current user
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
# Function to take ownership and set permissions
function Set-OwnershipAndPermissions {
param (
[string]$path
)
try {
# Take ownership
$acl = Get-Acl $path
$owner = New-Object System.Security.Principal.NTAccount($currentUser)
$acl.SetOwner($owner)
Set-Acl -Path $path -AclObject $acl -ErrorAction Stop
# Set permissions
$acl = Get-Acl $path
if (Test-Path -Path $path -PathType Container) {
# It's a directory
$permission = $currentUser, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
} else {
# It's a file
$permission = $currentUser, "FullControl", "None", "None", "Allow"
}
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission
$acl.SetAccessRule($accessRule)
Set-Acl -Path $path -AclObject $acl -ErrorAction Stop
Write-Host "Successfully processed: $path"
}
catch {
Write-Warning "Failed to process $path. Error: $_"
}
# Process subdirectories and files if it's a directory
if (Test-Path -Path $path -PathType Container) {
try {
Get-ChildItem $path -Force -ErrorAction Stop | ForEach-Object {
Set-OwnershipAndPermissions $_.FullName
}
}
catch {
Write-Warning "Failed to access contents of $path. Error: $_"
}
}
}
# Prompt for the folder path
$folderPath = Read-Host "Enter the full path of the folder"
# Check if the folder exists
if (Test-Path $folderPath) {
# Run the function
Set-OwnershipAndPermissions $folderPath
Write-Host "Process completed for $folderPath and all accessible contents."
} else {
Write-Host "The specified folder does not exist."
}
How to Use It
- Copy this script and save it as a
.ps1
file (liketake_ownership.ps1
). - Right-click on PowerShell and select “Run as administrator” (this is crucial!).
- Navigate to where you saved the script.
- Run it by typing
.\take_ownership.ps1
. - When prompted, enter the full path of the folder you want to process.
What’s Going On Here?
Let’s break this down a bit:
- Admin Check: The script starts by ensuring you run it as an admin. No admin rights? No dice.
- Current User: It grabs the current user’s name. This is who’s going to own everything.
- The Magic Function:
Set-OwnershipAndPermissions
is where the real magic happens. It:- Takes ownership of the item (file or folder)
- Sets the current user as the owner
- Gives the current user full control
- If it’s a folder, it does all this recursively for everything inside
- Error Handling: The script’s got your back with some neat error handling. It’ll let you know if it can’t process something and keep on truckin’.
- File vs. Folder: It’s smart enough to know the difference between files and folders and set the right permissions for each.
Why This is Awesome
- Time Saver: Imagine doing all this manually. Yikes!
- Consistency: It applies the same permissions everywhere, no mistakes.
- Flexibility: Works on any folder you point it to.
Wrapping Up
There you have it, folks! A powerful little script to take control of your files and folders. No more permission headaches, no more “access denied” nightmares — just pure, unadulterated file access bliss.
Got questions? Hit me up in the comments. And don’t forget to share this with your IT buddies – they’ll thank you later!
Happy scripting!
How to Automatically Login into Laravel App in Your Local Dev Environment
I often find myself spinning up Laravel projects for prototypes and idea testing and then letting them sit until I can pick them back up. Logging in whenever I start work gets annoying, and there’s no point in manually logging in to my local instance since my account is the admin. Fortunately, there are a few solutions to automate this process in Laravel. I’ll delve into the various methods to automatically log in to your Laravel app in your local development environment, enhancing your workflow and boosting productivity.
Utilizing session-based auto-login:
One approach to automating the login process for the Laravel application is session-based auto-login. This method involves setting up a mechanism that automatically logs in a predefined user whenever the application is accessed in the local development environment.
Each solution below assumes you’ve seeded or registered a local user account in your database.
1. Creating a custom route for auto-login:
You can create a custom route in your Laravel routes file (routes/web.php
) that triggers the auto-login functionality.
// routes/web.php
Route::get('/auto-login', function () {
$user = App\Models\User::find(1); // Fetch the user you want to auto-login
Auth::login($user);
return redirect('/dashboard'); // Redirect to a specific page after login
});
2. Implementing auto-login logic:
When you access the /auto-login
route in your local development environment, Laravel will automatically log in the specified user, redirecting them to the desired page (in this case, /dashboard
).
Leveraging custom middleware for auto-login:
Another method to automate your Laravel application’s login process is leveraging custom middleware designed for auto-login functionality. This approach provides more flexibility and control over the auto-login process, allowing you to define custom logic and conditions for authentication.
1. Creating a custom middleware for auto-login:
Generate a new middleware using the Artisan command make:middleware
.
php artisan make:middleware AutoLoginMiddleware
2. Registering the middleware in Laravel:
Register the custom middleware in the HTTP kernel (app/Http/Kernel.php
) to apply it to the desired routes or groups of routes.
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
// Other middleware...
\App\Http\Middleware\AutoLoginMiddleware::class,
],
];
Registering in the Boot method in AppServiceProvider:
This method allows you to log in automatically as soon as you load the application, and it is the method I use most often. I added a check to ensure that the environment is local.
if ($this->app->environment(‘local’)) {
$user = User::first();
if (isset($user)) {
$this->app[‘auth’]->setUser(User::first());
}
}
7-22-2024 – Update for the Boot method in AppService Provider
If you don’t have the user table seeded with a user, the above code will cause an error when running the seeders. I tweaked the code to check for the table’s existence to avoid the error when running seeders.
if ($this->app->environment('local') && \Illuminate\Support\Facades\Schema::hasTable('users')) {
$user = User::first();
if (isset($user)) {
$this->app['auth']->setUser(User::first());
}
}
Bonus: Generating a seeder for the Users table
Sometimes, you might want to seed your database with an admin user for testing purposes. Here’s how you can do it:
A. Creating a UserSeeder class:
Generate a new seeder class using the Artisan command make:seeder
.
php artisan make:seeder UserSeeder
B. Seeding the database with an admin user:
Within the generated UserSeeder
class, define the logic to create an admin user.
// database/seeders/UserSeeder.php
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
class UserSeeder extends Seeder
{
public function run()
{
User::create([
'name' => 'Admin',
'email' => 'admin@example.com',
'password' => Hash::make('password'), // Change this to something more secure
// Additional user data...
]);
}
}
Finally, run the seeder using the Artisan command db:seed
.
php artisan db:seed --class=UserSeeder
Following these steps, you can seamlessly integrate auto-login functionality into your Laravel application’s local development environment, reducing the time and effort spent on repetitive login tasks. Additionally, seeding your database with an admin user ensures that you have a user account available for testing and development purposes.
Installing font awesome pro with bun
After recently switching to bun.sh, I was trying to install Font Awesome Pro. It uses a private registry but their docs have not been updated to support non-npm package managers and bun does not yet support .npmrc files.
You can configure a private registry using an organization scope. First, you must get your auth token from your paid Font Awesome account by going to your account page, scrolling down to the Tokens section, and copying the token.
Copy and paste this string, and replace YOUR_TOKEN_HERE with the token you copied above:
[install.scopes]
"@fortawesome" = { token="YOUR_TOKEN_HERE" , url =
"https://npm.fontawesome.com/"}
Open the terminal and enter these commands:
touch $HOME/.bunfig.toml
nano $HOME/.bunfig.toml
Paste in the config above with your token and then hit CTRL+X to quit, and Y to save when prompted. Now you should be able to run
bun add @fortawesome/fontawesome-pro
Using Laravel Vite with MAMP
As seen in other posts, I use MAMP quite a bit for my web development environment. I know I can run docker, or any of the other platforms out there but they use more memory and resources that I’d prefer to devote to my dev tools.
I started a new Laravel project and wanted to use MAMP but Vite was throwing errors due to the SSL not matching out of the box.
When adding
@vite('resources/js/app.js')
to my blade file, I’d get errors including:
This request has been blocked; the content must be served over HTTPS.
I found articles saying to add –https or –host to my package json command but then I got this error:
net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Load MAMP Pro, add your host and generate your SSL certificates. For this example, we’ll use set the host name to my-app.test, and assume you’re storing the SSL keys in the default location.
Open vite.config.js and add the following 2 lines:
import fs from 'fs'; const host = 'my-app.test';
Then add this to defineConfig section:
server: { host, hmr: { host }, https: { key: fs.readFileSync(`/Applications/MAMP/Library/OpenSSL/certs/${host}.key`), cert: fs.readFileSync(`/Applications/MAMP/Library/OpenSSL/certs/${host}.crt`), }, },
You should now be able to run npm run dev and have no issues.
Sample full vite.config.js file for easy reference:
import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import fs from 'fs'; const host = 'my-app.text'; export default defineConfig({ server: { host, hmr: { host }, https: { key: fs.readFileSync(`/Applications/MAMP/Library/OpenSSL/certs/${host}.key`), cert: fs.readFileSync(`/Applications/MAMP/Library/OpenSSL/certs/${host}.crt`), }, }, plugins: [ laravel([ 'resources/sass/app.scss', 'resources/js/app.js', ]), ], });
Add GTM to Gatsby using Helmet
One of my devs needed to add Google Tag Manager (GTM) to an older Gatsby project we built and he was running into issues implementing the GTM code provided by Google since the react-google-tag-manager package required a newer version of Gatsby and its dependencies.
The issue turned out to be that the strings needed to be escaped for Helmet/React to process it correctly. If you’re using an older version of Gatsby, the snippet below should help you add GTM and call your events as needed. Just add it to your main template file.
const googleAnalyticsId = 'your-google-id-here'
<Helmet>
<script async src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`}></script>
<script>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', "${googleAnalyticsId}");
`}
</script>
</Helmet>
How to deploy a React app to Amazon S3 using Gitlab CI/CD
I’ve been trying to build more CI/CD scripts using Gitlab to automate pipeline deployments for work. Here’s a useful one for building and deploying a React app to Amazon S3.
You’ll need to add a variable called S3_BUCKET_NAME to your repo or replace the variable with your bucket path.
stages:
- build
- deploy
build react-app:
#I'm using node:latest, but be sure to test or change to a version you know works. Sometimes node updates break the npm script.
image: node:latest
stage: build
only:
- master
script:
# Set PATH
- export PATH=$PATH:/usr/bin/npm
# Install dependencies
- npm install
# Build App
- CI=false npm run build
artifacts:
paths:
# Build folder
- build/
expire_in: 1 hour
deploy master:
image: python:latest
stage: deploy
only:
- master
script:
- pip3 install awscli
- aws s3 sync ./build s3://$S3_BUCKET_NAME --acl public-read
How to use Backblaze B2 with Laravel
I am working on a Laravel project and decided to use a Backblaze bucket as it’s cheaper for storage when compared to AWS S3. I couldn’t find a tutorial on how to get it working from scratch and I tested a bunch of Laravel B2 libraries that didn’t end up working. The good news is that you don’t need a special B2 plugin and instead can use the S3 package recommended by the Laravel docs.
If you haven’t added the flysystem-aws-s3 package, add it to your project using composer:
composer require league/flysystem-aws-s3-v3
Login to your B2 account and create your bucket with your required settings. Once created, you’ll want to create a new application key with the permissions you need for your app. You should get a confirmation once it’s generated:
Open your .env file and locate the settings for AWS. You’ll need to add one key that’s not there by default:
AWS_ENDPOINT=
Match the settings in your .env from the application key to the values below.
AWS_ACCESS_KEY_ID=keyID
AWS_SECRET_ACCESS_KEY=applicationKey
AWS_DEFAULT_REGION=us-west-000
AWS_BUCKET=bucket-name
AWS_ENDPOINT=S3 Endpoint
Now you should be able to call the Laravel storage system like normal:
\Storage::disk('s3')->put('test.txt', 'test');
How to Setup a CI/CD Pipeline for Storybook.js using Gitlab
I just spent a few hours setting up a Gitlab pipeline to deploy a Storybook.js site. Of course the end result ended up being much simpler than I made it out to be. Like everything else on my blog, I’m sharing in case anyone else can use the information to save time.
Just put this in your gitlab-ci.yml and it’ll take care of caching the node modules and building your static version of Storybook to deploy.
image: node:latest
cache:
paths:
- node_modules/
stages:
- build
- deploy
build:
stage: build
script:
- npm install
- npm run build-storybook -- -o storybook-static
artifacts:
paths:
- storybook-static
only:
- qa
- develop
- master
deploy:
stage: deploy_to_aws
# add your deploy code here
How to Automate Sending Emails through Outlook interop using C#
I was tasked with a tricky issue in sending emails. Due to security concerns, the client’s IT team was not willing to share SMTP information for their mail settings and was only willing to set up an account in Outlook directly on a dedicated machine without sharing the password with us to send the emails. The client’s ask was to send emails through Outlook without letting users see the emails or Outlook itself.
Installing Office Interop for Outlook
Sending emails through Outlook can be done using Microsoft.Office.Interop.Outlook but the documentation is really lacking. If you need to do the same, I hope this will save you the hours of time it took me to figure out what ends up not being complex code.
Create a new desktop application project in Visual Studio. Install the Microsoft Office Interop for Outlook. I used the NuGet package manager to install it since it wasn’t present on my system:
Install-Package Microsoft.Office.Interop.Outlook
Automating E-mails using C#
I created a static class to send the email through Outlook. Note that my error handling code was replaced with Debug.Writeline. Remember to modify it to handle errors or implement logging so it doesn’t fail silently.
Email.cs:
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Outlook;
using Exception = System.Exception;
namespace Email.classes
{
public class Email
{
public static void SendWithEmbeddedImages(string to, string subject, string htmlMessage)
{
var missing = Type.Missing;
Application oOutlook = null;
NameSpace oNS = null;
Folder oCtFolder = null;
Items oCts = null;
MailItem msg = null;
var sHeaderPath = Path.Combine(Environment.CurrentDirectory, "emails", "header.jpg");
var sLogoPath = Path.Combine(Environment.CurrentDirectory, "emails", "logo.jpg");
try
{
// Create an Outlook application.
oOutlook = new Application();
// Get the namespace.
oNS = oOutlook.GetNamespace("MAPI");
//Assumes MAPI profile name is Outlook
oNS.Logon("Outlook", missing, false, true);
msg = (MailItem) oOutlook.CreateItem(OlItemType.olMailItem);
var attachHeader = msg.Attachments.Add(sHeaderPath, OlAttachmentType.olEmbeddeditem);
var attachLogo = msg.Attachments.Add(sLogoPath, OlAttachmentType.olEmbeddeditem);
attachLogo.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", "logo");
attachHeader.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E",
"header");
msg.Subject = subject;
msg.To = to;
msg.BodyFormat = OlBodyFormat.olFormatHTML;
msg.HTMLBody = htmlMessage;
//Show email
msg.Display();
//Send email
//((Outlook._MailItem)msg).Send();
oNS.Logoff();
}
catch (Exception ex)
{
Debug.WriteLine("Automate Outlook throws the error: {0}", ex.Message);
}
finally
{
// Manually clean up the explicit unmanaged Outlook COM resources by
// calling Marshal.FinalReleaseComObject on all accessor objects.
// See http://support.microsoft.com/kb/317109.
if (msg != null)
{
Marshal.FinalReleaseComObject(msg);
msg = null;
}
if (oCts != null)
{
Marshal.FinalReleaseComObject(oCts);
oCts = null;
}
if (oCtFolder != null)
{
Marshal.FinalReleaseComObject(oCtFolder);
oCtFolder = null;
}
if (oNS != null)
{
Marshal.FinalReleaseComObject(oNS);
oNS = null;
}
if (oOutlook != null)
{
Marshal.FinalReleaseComObject(oOutlook);
oOutlook = null;
}
}
}
}
}
Example on how to call the class:
var sEmailPath = Path.Combine(Environment.CurrentDirectory, "emails", "single.html");
var htmlMessage = "";
if (File.Exists(sEmailPath))
{
//Load HTML from file
htmlMessage = File.ReadAllText(sEmailPath);
}
Email.SendWithEmbeddedImages("toaddress@test.com", "Outlook Automation Test", htmlMessage);
email.html:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
<table width="600" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td><img src="cid:header"></td>
</tr>
<tr>
<td>
Hello world!
</td>
</tr>
<tr>
<td><img src="cid:logo"></td>
</tr>
</table>
</body>
</html>
Important Notes and Gotchas
- CIDs need to be unique. I’ve seen them on all other posts with the format “file.extension@{random #}” but keeping it simple like in the code above worked for me with no issues with Outlook 2016. I did not test on older versions of Outlook to confirm as I no longer have access to them.
- Outlook ignores font rules in the HTML/CSS you code in the email and defaults to Times New Roman. I know Outlook uses the Word renderer but I have no idea why and the only solution I found was to update the default font in Microsoft Word. Yes, to change the font in Outlook, you’ll need to update the default font in Word. Here’s how to set it:
- Open Word
Go to Options -> Advanced -> Web Options
Change the default font in the Fonts tab
- Open Word
- Outlook only supports a subset of HTML so don’t forget to test and verify everything as most CSS formatting won’t work in Outlook.