matt-goldsworthy.com Open in urlscan Pro
198.211.105.126  Public Scan

Submitted URL: https://www.matt-goldsworthy.com/
Effective URL: https://matt-goldsworthy.com/
Submission: On October 04 via api from US — Scanned from US

Form analysis 0 forms found in the DOM

Text Content


I am a top-performing Senior Software Engineer with extensive expertise in
Laravel and PHP, covering the full software development lifecycle. My skills
span full stack development, where I excel in leveraging Laravel's powerful
features and PHP’s flexibility to build robust, scalable applications. I am
adept at directing cross-functional teams to ensure precise and efficient
software management and integration.

My experience includes collaborating with leadership teams to set and achieve
strategic goals, innovating process improvements to enhance workflows, and
maintaining strong internal controls. I am passionate about driving
organizational growth through technical excellence and continuous optimization.




SECURING DATA IN LARAVEL

Matt Goldsworthy

1 month ago




INTRODUCTION

When working with private information, it’s crucial to encrypt your data. Not
only is it best practice, but in some cases, such as HIPAA regulations, it’s
required by law. In this post, we’ll explore various methods to secure data
using Laravel.


IDENTIFY PRIVATE INFORMATION

The first step is to identify private information, such as SSN or medical
history. Laravel provides a built-in method called Crypt to secure this data. It
uses the APP_KEY specified in your .env file. This key is very important and
should be kept secret—consider using a key manager or other secure software to
maintain it.


ENCRYPTING THE .ENV FILE

In some cases, you might need to encrypt your .env file. While deployment sites
like Forge manage the .env file securely on the server, other environments may
require you to encrypt it and decrypt it during deployment.


CREATING A MODEL IN LARAVEL

To demonstrate data encryption, let’s create a model using the following
command:

php artisan make:model Patient -m


MIGRATION FILE

In the migration file, define the schema for the model:


public function up()
{
    Schema::create('patients', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->text('history')->nullable();
        $table->string('ssn');
        $table->timestamps();
    });
}
            


USING CUSTOM GETTERS AND SETTERS

Within the model, you can use custom getters and setters for attributes like SSN
and history. This method is useful if you use a key outside of the APP_KEY
value.


attributes['_history'] = Crypt::encryptString($value);
    }

    public function getHistoryAttribute($value)
    {
        return Crypt::decryptString($value);
    }

    public function setSsnAttribute($value)
    {
        $this->attributes['ssn'] = Crypt::encryptString($value);
    }

    public function getSsnAttribute($value)
    {
        return Crypt::decryptString($value);
    }
}



USING LARAVEL’S BUILT-IN CASTS

Laravel’s built-in casting functionality simplifies encryption. This method uses
the APP_KEY by default:


 'encrypted',
        'ssn' => 'encrypted',
    ];
}


This approach automatically handles encryption and decryption without needing
custom getters and setters. For more information, check out this article from
Laravel News.


ADDITIONAL SECURITY PRACTICES

 * Key Rotation: Laravel supports key rotation using the APP_PREVIOUS_KEYS
   environment variable. This allows Laravel to use both current and previous
   keys for encryption and decryption.
 * Access Controls: Implement strong access controls using Laravel’s built-in
   functionality. For example, you can use gates and authorization:

   
   public function view(Model $model)
   {
       $this->authorize('view', $model);
       return view('model.show');
   }
                   

 * Logging Access: Log access to sensitive information to keep track of who
   accessed what and when.
 * Data Minimization: Collect only the data you need. Avoid storing unnecessary
   sensitive information.
 * Security Audits: Regularly review and update your security practices.
 * Data Encryption in Transit: Always use HTTPS to securely transmit data.


CONCLUSION

Securing data in Laravel involves using strong encryption, managing keys
carefully, enforcing robust access controls, logging access, minimizing data
collection, and regularly auditing your security practices. By following these
guidelines, you can help ensure that your application’s sensitive data remains
protected.




OPTIMIZING QUERY PERFORMANCE WITH DYNAMIC DATE RANGES IN LARAVEL AND LIVEWIRE

Matt Goldsworthy

1 month ago



In web development, handling dynamic date ranges and optimizing query
performance are essential for delivering fast and responsive applications. If
you're working with Laravel, Livewire, and Eloquent, you have powerful tools at
your disposal to manage these aspects effectively. In this post, we'll explore
how to handle dynamic month ranges in SQL queries and discuss best practices for
optimizing query performance.



HANDLING DYNAMIC DATE RANGES IN SQL QUERIES

When dealing with data that spans over various months or years, crafting SQL
queries that can handle dynamic date ranges becomes crucial. Whether you're
generating reports, displaying user activity, or analyzing data trends, you need
to ensure your queries can adapt to different time periods.

Here's a basic example of how you can handle dynamic month ranges using
Laravel's query builder:

use Illuminate\Support\Facades\DB;

$startDate = '2024-01-01'; // Example start date
$endDate = '2024-12-31';   // Example end date

$data = DB::table('your_table')
    ->whereBetween('date_column', [$startDate, $endDate])
    ->get();


In this example, whereBetween is used to filter records between the $startDate
and $endDate. This method is straightforward but can be adapted to various use
cases, such as fetching records for a specific month or year.



LEVERAGING ELOQUENT FOR DYNAMIC QUERIES

Eloquent, Laravel's ORM, simplifies working with database queries. If you're
using Eloquent models, you can achieve similar results with a more intuitive
syntax:

use App\Models\YourModel;

$data = YourModel::whereBetween('date_column', [$startDate, $endDate])
    ->get();


This approach not only keeps your code clean but also leverages Eloquent's
built-in query-building capabilities.



OPTIMIZING QUERY PERFORMANCE

Performance optimization is a key aspect of working with large datasets or
complex queries. Here are some tips to enhance query performance in Laravel and
Livewire applications:


 * Indexing: Ensure that columns used in WHERE, JOIN, and ORDER BY clauses are
   indexed. Indexes significantly speed up query execution.
   
   
 * Caching: Use caching mechanisms to reduce database load. Laravel's built-in
   caching features, like query caching and result caching, can help:
   
   

   $data = Cache::remember('your_cache_key', $seconds, function () use ($startDate, $endDate) {
       return YourModel::whereBetween('date_column', [$startDate, $endDate])
           ->get();
   });

   
   
 * Eager Loading: Reduce the number of queries by using Eloquent's eager loading
   to fetch related models in a single query:
   
   

   $data = YourModel::with('relatedModel')
       ->whereBetween('date_column', [$startDate, $endDate])
       ->get();

   
   
 * Pagination: For large datasets, consider using pagination to load data in
   chunks rather than all at once:

   $data = YourModel::whereBetween('date_column', [$startDate, $endDate])
       ->paginate(15);

   
   


CONCLUSION

Handling dynamic date ranges and optimizing query performance are critical for
building efficient and scalable applications. With Laravel and Livewire, you
have robust tools to manage these tasks effectively. By implementing best
practices like indexing, caching, eager loading, and pagination, you can ensure
your application performs well even under heavy loads.


Feel free to explore these techniques and adapt them to your specific needs.
Happy coding!




OPTIMIZING WIDGET PERFORMANCE IN FILAMENT: A REAL-WORLD EXAMPLE

Matt Goldsworthy

2 months ago



This week, we encountered significant performance issues with a Filament
dashboard page that used multiple widgets. The memory consumption was high for
each widget, and load times plummeted from milliseconds to several seconds.
Intrigued by this problem, I decided to investigate further using a specific
widget as a case study.


THE PROBLEM

Here’s a snapshot of the widget in question:



The Debugbar output for this widget was revealing:



With 5000 requests and 4148 errors (seeded), the performance was notably poor.
Given that the query in question was relatively simple, it was clear that
something needed to change.


ANALYZING THE CODE

Here’s a look at the code responsible for the inefficiency:



The code employed a while loop to query data for each month, returning models
for each iteration. This approach doesn’t scale well; with larger datasets, such
as 20,000 to 30,000 errors or requests, this method could become increasingly
problematic.


COMMON PITFALLS WITH ELOQUENT

This situation highlights a common pitfall among developers, particularly those
newer to the field. While Eloquent ORM is powerful and convenient, it’s easy to
over-rely on it without considering performance implications. Eloquent might
retrieve more data than necessary if queries are not carefully crafted.


I’ve encountered this myself and have to remind myself to use raw database
queries when Eloquent becomes too cumbersome for complex scenarios.



A BETTER APPROACH

To address the issue, I decided to focus on the essential data: the count of
errors per month. Given that requests are either successful or error-prone (with
errors embedded in a nested result in an XML API), we only need to count errors
by month. Here’s a more efficient SQL query to get the counts:



SELECT
    m.month,
    COALESCE(lrr.request_count, 0) AS request_count
FROM
    (SELECT 2 as month UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8) m
LEFT JOIN (
    SELECT
        MONTH(request_at) AS month,
        COUNT(*) AS request_count
    FROM
        logged_request_responses
    WHERE
        response_status != 200
        AND request_at BETWEEN "2024-02-04 00:00:00" AND "2024-08-04 23:59:59"
    GROUP BY
        MONTH(request_at)
) lrr
ON m.month = lrr.month
ORDER BY
    m.month
            


This query efficiently aggregates the error counts by month and should scale
well even with larger datasets.


THE RESULTS

Although this solution was a quick fix, the performance improvement was
remarkable:



The query now executes in 29ms compared to the previous approach, which involved
6 to 7 separate queries (one for each month).


CONCLUSION

While this optimization significantly improved performance, there’s always room
for further refinement. This experience underscores the importance of balancing
ORM convenience with raw query efficiency to handle large data sets effectively.



© Matt Goldsworty