Derek MacDonald

Posts Tagged “Laravel”

Running Laravel Dusk tests in Firefox

Posted Jun 3, 2020 at 12:31pm GMT-0500

PHP package Laravel Dusk (initially released in April 2018) allows Laravel Framework applications to run browser tests with minimal configuration. The target browser can be configured but out-of-the-box it is setup to run tests in Google Chrome via Chromedriver. Well what about other web browsers?

Attempting to escape the far-reaching tentacles of surveillance capital, last year I uninstalled Chrome and replaced it with Mozilla Firefox and DuckDuckGo. But I still wished to locally run browsers tests on Laravel apps. Thankfully W3C’s WebDriver recommendation in June 2018 provided a clear path for other browsers to add automated testing. Geckodriver for Gecko-based browsers (including Firefox) has been stable since late 2019 so a Laravel Dusk integration is actually very easy now.

Read the rest of this entry »

Conditionally Suppressing Laravel Event Listeners

Posted Feb 7, 2019 at 08:17pm GMT-0500

Watching David Heinemeier Hansson’s “On Writing Software Well” series awhile back, I took note of episode 2 showing Ruby on Rails active record callbacks being conditionally suppressed. “Heavy callback scenarios” (see timestamp 19:20) require preventing queue worker jobs and extra database queries that sometimes are not required.

I mainly work with PHP framework Laravel which as of version 7.x doesn’t offer transactional event listener callbacks although there have been community discussions about Eloquent events aware of database transactions. Here I’ll cover some app-level solutions that somewhat mirror DHH’s code.

Read the rest of this entry »

Allow Laravel FormRequest to handle XML

Posted Dec 19, 2018 at 07:56pm GMT-0500

If you’ve been cornered into creating API endpoints consuming a XML request body, you would see Laravel doesn’t have framework support. There is a $request->json() method for JSON content but you must write app-level code to make validation work on inbound XML. There are StackOverflow posts floating around that suggest simplexml_load_string() through json_encode() -> json_decode() will form a PHP associative array. However this solution incorrectly handles CDATA nodes.

So I’ve created a HasXmlContentType trait that can be placed in any FormRequest class. This makes $request->input($key), $request->all(), etc. a PHP array payload so Laravel’s request validation “just works”.

Read the rest of this entry »

Sanitizing Laravel Request Inputs

Posted Mar 15, 2018 at 08:34pm GMT-0500

Generally, web applications shouldn’t need to sanitize input. Validate the data and either accept or reject it and give the user feedback on why it was rejected. However sometimes there is a grey area where you wish to make the dataset more consistent (email addresses, postal codes, phone numbers) without negatively affecting the user. The input is OK but it requires some reformatting.

In Laravel this can be done in Eloquent model attribute set mutators after validation and before the database query is run. But sometimes that cleanup has to be done before validation.

Laravel 5.0 pre-release had a short-lived FormRequest@sanitize() method to cleanup inputs before validation but a fully-featured sanitizer never it into an official release. Laravel 5.4 later added web middleware TrimStrings and ConvertEmptyStringsToNull to normalize database blank strings. They both use a parent TransformsRequest class that walks through each input in query parameters and the HTTP request body. Well your userland code can re-use that class too!

Read the rest of this entry »

Laravel 5.4 Eloquent update timestamps option

Posted Jun 28, 2017 at 11:35am GMT-0500

Apparently Laravel’s Eloquent update(['timestamps' => false]) option never worked in all cases so it was silently removed without any sort of deprecation notice or upgrade guide bullet point. It’s a good thing I pay close attention to every core pull request and also had an app-level integration test that confirmed the framework works as intended across each minor version upgrade.

Of course, I’m lying.

Read the rest of this entry »

Eager Loading Laravel Polymorphic Relations

Posted Jun 5, 2017 at 01:30am GMT-0500

Illuminate\Database\Eloquent\Collection@loadMorph() is now part of the Laravel framework starting in 5.6.13.

Improving database query performance of polymorphic relations is a rarely-documented edge case in Laravel development but I’ve solved some N+1 problems it presents. A new Collection macro can be introduced, inspired by Illuminate\Database\Eloquent\Collection method load() (L38) that calls Illuminate\Database\Eloquent\Builder method eagerLoadRelations() (L466).

Read the rest of this entry »

Can’t mock Laravel CacheManager store()

Posted May 18, 2017 at 03:35am GMT-0500

Testing stateful API endpoints in Laravel, you may come across this exception message:

BadMethodCallException: Method Mockery_1_Illuminate_Cache_CacheManager::store() does not exist on this mock object

In the official documentation, the facade service mock example covers Cache::shouldReceive() but there are potential limitations. Generally APIs are stateless, so developers are less likely to hit this roadblock. Here’s a solution to it anyhow!

Read the rest of this entry »

Higher-order PHP function optional()

Posted May 2, 2017 at 04:35am GMT-0500

optional() is now a helper function built into the Laravel 5.5 core.

A recent Laravel 5.4 addition inspired me to discover an expressive approach to handling PHP objects that may be null. When higher-order tap() appeared in Laravel’s commit history last week (see Taylor Otwell’s explanation), I immediately connected it to transform() that I proposed for conditionally changing primitive values.

I want to eliminate these goofy conditionals, fluff greyed out:

  • if (Auth::check() && Auth::user()->phone) {
  • {{ old(‘address_uuid’, $company->primaryAddress ?
        $company->primaryAddress->uuid : null) }}
  • return $this->latestDraft && $this->latestDraft->isPending();

The goals I have in mind are:

  • Reduce repetition of variables, property names, and class methods that make conditionals more resistant to change. For requirement adjustments, think of it as avoiding a programmer’s death by 1,000 cuts.
  • Allow expression of requirements in left-to-right statements of natural English, eliminating bleep-blorp speak.

So using a higher-order wrapper class, I came up with global helper function optional(). It’s a fluid and more succinct approach of calling an object method or accessing its properties when that instance may be null.

Here are some common examples in Laravel applications.

Read the rest of this entry »

Laravel Requests, PHP Truthiness, and Other Lies

Posted Apr 20, 2017 at 03:20am GMT-0500

blank(), present() (renamed to filled()), and transform() are now helper functions built into the Laravel 5.5 core.

Developing a RESTful API in Laravel, internal quirks require request handling customization to fill in the framework’s gaps. Before getting to the database layer, each codebase needs custom boilerplate for transforming and filtering inputs. Up to version 5.3, HTTP PATCH endpoints have been better implemented by using Request macros for a reliable parameter “picker” method. Michael Dyrynda’s partial model updates post does a good job of covering some of those edge cases.

Starting in Laravel 5.4, the core framework has moved toward better standardization of validation rules through sanitized inputs. New TrimStrings and ConvertEmptyStringsToNull middleware allow databases to keep a clean state while also avoiding cluttered controllers and FormRequest classes.

There are still some form handling and API endpoint problems popping up but there is a path going forward.

Read the rest of this entry »

Laravel tap()

Posted Feb 16, 2017 at 10:48pm GMT-0500

As yet undocumented, Laravel 5.3 quietly added a new tap() global helper function, improving the framework’s declarative capabilities. It’s a subtle idiom picked up from Ruby and Lodash that allows you to “tap” into a chain.

You will not use this function often. It does take control of stodgy imperative solutions with right-to-left assignments souring solutions in an unpleasant direction. The end result will be saving 2 or 3 lines on each use while making that code read top-down, left-to-right.

Read the rest of this entry »

Derek MacDonald

Derek

Toronto, ON

Web application developer.



© Copyright Derek MacDonald. All rights reserved.