Today I wired up some functionality to rename & delete types, as well as standard authentication forms to register, login, logout, and change passwords. With that, I expanded upon my generic dialog form so that I could add multiple fields while supporting autocomplete. I got an error in my console stating that a username field should still be included when changing passwords so that password managers can have context as to what account the password is for. I setup one of the input controls to be a hidden type, but I still got the warning. I then went ahead and added a simple hidden input directly to the form.
<input type="hidden" autocomplete="username" value="foo" />
I still had a problem. I tried various things, but in the end, the answer was to set the style to hide the field, rather than the input type, and make sure that hidden fields still “appear” as text fields.
Confirmation

I added a new Dialog control called, DialogControl. It is a wrapper for DialogInputs, except that it doesn’t pass any inputs. You just have the two buttons. I wanted to allow the end-user to press their enter key to submit the default action. Auto Focus is setup on the “OK” button, but I found it wasn’t being focused. I tracked it down to how the MUI Material Dialog control attempts to restore focus. I haven’t looked too deep into it, but if I setup the dialog with <Dialog disableRestoreFocus />, pressing the enter key works. Something seemed off, as if I am overlooking the cause of the problem, and just putting a band-aide to address the symptoms.

Microsoft Designer: Image Creator Prompt
Today, I implemented functionality for renaming and deleting types, added authentication forms, and expanded a dialog form to handle multiple fields with autocomplete. I faced an issue with password manager warnings for hidden username fields and resolved it by using CSS to hide the input properly. I also created a new dialog control, fixed an issue with submitting via the “enter” key, and worked on REST API paths with parameters. I encountered challenges with Apache rewrite rules, particularly with .php extensions and fallback paths, and resolved issues with include paths by using dirname(DIR) to handle relative file references correctly.
The RTK Query is working out well. However, I do have a bit of an issue. Once I delete an item, I invalidate its token. This causes a trip to the server to get the latest data for that item. However, the item doesn’t exist. I am debating if I should be invalidating items when they are deleted. Invalidating the list alone is good enough to trigger the list to get a new subset of ID’s to display.

I worked on the final part of REST API’s by including parameters within the URL path, rather than query string parameters in my GET requests. One of the added benefits is that I can see the ID’s of items being requested in the network traffic paths, rather than having to click each one individually to see what’s different about each ones query string.
For the most part, I’ve been fighting with apache rewrite rules and the Fallback Resource. My goal was to allow exact matches and URLs + “.php” extensions to load the files, and evaluate all other paths in PHP. It seems that no matter what I tried, if I had a rule to append a .php extension to a file, then any sub-path failed.
- /api/fallback.php – processing of unknown paths
- /api/types/get.php – exists
- /api/types/get – has .php extension appended
- /api/types/get/20 – broken, does not go to fallback.php
- /api/types/non-existing – goes to fallback.php
Here is what I’ve got in my .htaccess file.
FallbackResource /api/fallback.php
# Rewrite OPTIONS requests (cors) to a specific handler script or endpoint
RewriteCond %{REQUEST_METHOD} =OPTIONS
RewriteRule ^(.*)$ ../common/options-handler.php [L,QSA]
# Stop rewriting if file exists
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L,QSA]
# append .php extension to existing files
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_FILENAME}\.php -f
# RewriteRule ^(.+)$ $1.php [L,QSA]
I’d still like to figure out where I’ve gone wrong.
The fallback is fairly simple. I’m looking at all of the segments of a path and attempting to append .php at the end. If the file doesn’t exist, I remove the last segment and try again. Once I find a file, I populate the $_GET global with the segments as arguments, so that thy can be accessed later.
<?php
function process_fallback()
{
$segments = explode('/', ltrim($_SERVER['REQUEST_URI'], '/'));
$count = count($segments);
for ($i = $count; $i > 0; $i--) {
$path = implode('/', array_slice($segments, 1, $i - 1));
$path = "./$path.php";
if (file_exists($path)) {
$args = array_slice($segments, $i);
$argString = '';
foreach ($args as $index => $arg) {
$_GET["_arg$index"] = $arg;
$argString .= "_arg$index=$arg";
}
require $path;
return;
}
}
$json = json_encode($parts, JSON_PRETTY_PRINT);
http_response_code(404);
header('Content-Type: application/json');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Content-Length: ' . strlen($json));
echo $json;
}
process_fallback();
I may review the paths later to have a better scheme, such as how to name variables, or following a specific format to translate query string parameters better. For example, anything matching /get/(\d+) can probably be converted to $_GET['id'] = $matches[1]. It would make more sense to programmers viewing the code of get.php to see $id = $_GET['id'] instead of $id = $_GET['_arg0']. I could also setup a naming scheme so that paths appear as /get/id/20 so that I could associate name/value pairs to populate the $_GET global.
One thing I figured out was that as requests are processed in fallback.php, the working folder changes – which messes up all of my require/include requests. I had thought the paths were relative to the file. That’s not the case. They are relative to the working folder. Now that a file potentially had multiple folder entry points, I had to figure out a solution. The fix was to prepend all of my relative paths with dirname(__DIR__)
// Bad require_once "../../common/ErrorHandling.php"; // Good require_once dirname(__DIR__) . "../../common/ErrorHandling.php";


