earmsby wrote a reply+100 XP
3d ago
earmsby started a new conversation+100 XP
4d ago
I just created a new Laravel app via the command laravel new smc-sandbox. All appeared to go well and I opened my new blank app in my IDE. Next step was to install Filament so I ran the command: composer require filament/filament:"^4.0" as I have done before. However, I got this error:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires filament/filament 4.0 (exact version match: 4.0, 4.0.0 or 4.0.0.0), found filament/filament[v4.0.0] but these were not loaded, because they are affected by security advisories ("PKSA-yb9k-ykqx-p2zw"). Go to https://packagist.org/security-advisories/ to find advisory details. To ignore the advisories, add them to the audit "ignore" config. To turn the feature off entirely, you can set "block-insecure" to false in your "audit" config.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
I don't totally understand the error or how to resolve it. Any advice?
earmsby wrote a reply+100 XP
4w ago
earmsby wrote a reply+100 XP
1mo ago
earmsby started a new conversation+100 XP
1mo ago
FWIW, I tried asking AI (both Larry AI and Google) for the answer to this but the given solutions were either incomplete or just didn't work.
This seems like it should be pretty simple. On a filament 4.x dashboard I want to change the page heading () from the generic "Dashboard" to something else (in this case "Home").
Several AI models suggested to: Create a new file at app/Filament/Pages/Dashboard.php and add the following code to override the title.
But when I do that, there is now a second item in the side nav. The new one says "Home" and the original "Dashboard" is still there. The page heading is still "Dashboard."
I tried creating a file: app\Filament\Pages\Dashboard.php with this code:
namespace App\Filament\Pages;
use Filament\Pages\Dashboard as BaseDashboard;
class Dashboard extends BaseDashboard
{
protected static ?string $title = 'Home';
protected ?string $heading = 'Home';
}
This renders two "home" links in the side nav that both go to the same URL and the page heading remains "Dashboard."
I really thought changing this page heading would be pretty simple given all the ways to customize Filament dashboard and their components. But I'm getting nowhere.
earmsby started a new conversation+100 XP
1mo ago
I have a Model: Account and a Model: AccountNote. Account has a relationship:
public function accountNotes(): HasMany
{
return $this->hasMany(AccountNote::class);
}
And AccountNote has this relationship:
public function account(): BelongsTo
{
return $this->belongsTo(Account::class);
}
In my filament resource for Account, I have a relation manager for AccountNotes. The table and view work fine but when I try to add a new AccountNote from the relation manager, I'm getting a SQl error:
ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (Connection: mysql, SQL: insert into `account_notes` (`note_text`, `added_by`, `note_date`, `account_id`, `updated_at`, `created_at`) values (Here is another note, 1, 2026-03-26 15:41:07, 48, 2026-03-26 15:41:07, 2026-03-26 15:41:07)) {"userId":1,"exception":"[object] (Illuminate\\Database\\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (Connection: mysql, SQL: insert into `account_notes` (`note_text`, `added_by`, `note_date`, `account_id`, `updated_at`, `created_at`) values (Here is another note, 1, 2026-03-26 15:41:07, 48, 2026-03-26 15:41:07, 2026-03-26 15:41:07))
The table for AccountNotes does not have the usual timestamp fields because they aren't necessary. Am I understanding the error correctly that Filament is expecting these fields to exist anyway? Is there a way to solve this without adding unnecessary fields to the table?
earmsby was awarded Best Answer+1000 XP
1mo ago
earmsby wrote a reply+100 XP
1mo ago
earmsby wrote a reply+100 XP
1mo ago
earmsby started a new conversation+100 XP
1mo ago
I have a relationship that has this table:
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('note_date')
->defaultSort('note_date', 'desc')
->columns([
TextColumn::make('note_date')
->label('Date')
->date(),
TextColumn::make('note_text')
->label('Note')
->limit(50),
TextColumn::make('addedBy.name')
->label('Added By')
->badge()
])
[... snipped ...]
->recordActions([
EditAction::make(),
ViewAction::make(),
DeleteAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
and this infolist:
public function infolist(Schema $schema): Schema
{
return $schema
->components([
TextEntry::make('note_text')
->label('Note')
->columnSpan(2),
TextEntry::make('note_date')
->label('Date'),
TextEntry::make('addedBy.name')
->label('Added by'),
]);
}
When I click on a record from the table, the title at the top of the view shows "View 2026-03-26" I realize that's correct and expected. But is there a way to omit the word "view" and just show the record title attribute itself as the page heading?
earmsby wrote a reply+100 XP
1mo ago
Ok, I found a solution.
First, I went back to returning the data as an array:
$dates = array_column($widget_data, 'step_date');
array_multisort($dates, SORT_ASC, $widget_data);
return $widget_data;
Then I added an element to my custom data for the number of weeks old each record was:
$step_date = Carbon::parse($pub_last_step[0]['StepDate']);
...
'weeks_old' => round($step_date->diffInWeeks(Carbon::now())),
Then in my iconcolumn, I used this:
IconColumn::make('weeks_old')
->label('Age')
->icon(function (array $record){
if($record['weeks_old'] >= 6){
return Heroicon::ExclamationTriangle;
}elseif ($record['weeks_old'] >= 4) {
return Heroicon::ExclamationCircle;
}else{
return Heroicon::CheckCircle;
}
})
->color(function (array $record){
if($record['weeks_old'] >= 6){
return 'danger';
}elseif ($record['weeks_old'] >= 4) {
return 'warning';
}else{
return 'success';
}
}),
It seems like it was possible to stick with returning an array from the ->records() method. The key was to tell the closure to expect an array with ->icon(function (array $record){...]
It's working perfectly now. I might experiment with not adding the extra "weeks_old" array element and just calculate it directly in the iconcolumn. But for now, I'm going to leave it as is.
earmsby wrote a reply+100 XP
1mo ago
When I add the code to convert $widget_date to objects:
// map arrays to objects
return collect($widget_data)
->map(function ($item) {
return (object) $item;
});
As given in step 1, I get this error:
Filament\Widgets\TableWidget::Filament\Tables\Concerns\{closure}(): Argument #1 ($record) must be of type Illuminate\Database\Eloquent\Model|array, stdClass given, called in C:\Users\earms\Herd\hildegard-dashboard-v2\vendor\laravel\framework\src\Illuminate\Collections\Arr.php on line 847
This is before I even attempt to add the iconColumn. I'm not sure I understand the error, but it looks like Filament doesn't like an object an array. What to try now?
earmsby started a new conversation+100 XP
1mo ago
I have a widget with this code:
namespace App\Filament\Widgets;
use Filament\Actions\BulkActionGroup;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget;
use App\Models\Publication;
class PendingPrintJobs extends TableWidget
{
protected static ?int $sort = 2;
public function table(Table $table): Table
{
return $table
->recordUrl(function ($record) {
return route('filament.admin.resources.publications.view',['record'=>$record['publication_id']]);
})
->records(function (): array {
$widget_data = array();
$completed_status = array('Printing Completed', 'Reprint Printed', 'Invoiced by Printer');
$all_pubs = Publication::with('productionSteps')->get();
foreach ($all_pubs as $pub) {
if (count($pub->productionSteps) > 0) {
$pub_last_step = $pub->lastStep();
if (!in_array($pub_last_step[0]['StepName'], $completed_status)) {
$data = [
'last_step' => $pub_last_step[0]['StepName'],
'step_date' => $pub_last_step[0]['StepDate'],
'catalog_number' => $pub->catalog_number,
'publication_id' => $pub->id,
];
array_push($widget_data, $data);
}
}
}
//sort the data by date ASC
$dates = array_column($widget_data, 'step_date');
array_multisort($dates, SORT_ASC, $widget_data);
return $widget_data;
})
->columns([
TextColumn::make('catalog_number')
->label('Catalog Number'),
TextColumn::make('last_step')
->label('Step'),
TextColumn::make('step_date')
->label('Date'),
])
->filters([
//
])
->headerActions([
//
])
->recordActions([
//
])
->toolbarActions([
BulkActionGroup::make([
//
]),
]);
}
}
I want to add an icon column to the table. The icon column is not tied to a field in the data. Instead if the step_date is more than 6 weeks in the past, the icon should be Heroicon::ExclamationCircle, otherwise, it should be Heroicon::Check.
When I attempted to do something like:
IconColumn::make('Status Icon')
->label('Status')
->icon(function ($record) {
ray($record);
}
I don't get anything in ray, so it seems like it's just skipping the whole ->icon() method. I do get the column label.
I must be doing something wrong, but can't seem to crack it.
earmsby wrote a reply+100 XP
1mo ago
earmsby started a new conversation+100 XP
1mo ago
I have this model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AltWorkId extends Model
{
protected $fillable = [
'work_id',
'alt_work_entity_id',
'alt_id_number'
];
public function work(): BelongsTo
{
return $this->belongsTo(Work::class);
}
public function altWorkEntity(): BelongsTo
{
return $this->belongsTo(AltWorkIdEntity::class);
}
}
My Work model has this:
public function altWorkIds(): HasMany
{
return $this->hasMany(AltWorkId::class);
}
I'm trying to create a relation manager on my WorkResource. When I try to create it via php artisan:
php artisan make:filament-relation-manager WorkResource
It asks me for the relationship, the related model and the title attribute, but then comes back saying:
ErrorException
class_parents(): Class AltWorkId does not exist and could not be loaded
I don't understand why it thinks the AltWorkId model doesn't exist. It's definitely there in the Models directory where it should be. Any ideas?
earmsby wrote a reply+100 XP
2mos ago
Aha!
I had reached out to support at Forge. Many hours later, I got this:
We had a brief platform issue earlier that was affecting some deployments on Forge. It was resolved shortly after, so when you pushed that small change and retried, the underlying issue had already been fixed on our side.
Your edit likely wasn’t the real cause of it starting to work again, just good timing.
Really appreciate you following up, and glad everything is deploying normally now. If you see anything odd again, just let us know.
That makes a lot more sense!
earmsby wrote a reply+100 XP
2mos ago
Ok, weird.
I had an older migration that had added fields but failed for some reason a while back. After creating other migrations, I couldn't run them because this older migration would try to run, find that the fields were already created and then fail, blocking the newer migrations from running. So, I simply deleted the file, figuring it would be marked as a deleted file in my next commit. Instead, the commit that I was trying to deploy labelled my deleted file as having renamed to one of the newer migrations I had created after deleting it. I didn't think that would cause the deployment to fail.
But just as a test, I just added a random comment to the migration that was committed as a renamed file instead of a new file. Then I committed that edited migration. Ran the deployment again and this time it ran without a hitch.
Now, I have no idea if that solved the issue or if there was something else going on with Forge or Vultr. But... my last real changes (not just the added comment) were deployed. So, who knows.
earmsby wrote a reply+100 XP
2mos ago
-
There was one small change I had recently made to the deployment script:
$FORGE_PHP artisan queue:restart. I commented that out and tried to rerun the deployment. It failed again. -
The log for the failed deployments only shows this:
Mon Feb 23 05:57:31 PM UTC 2026
=> Deployment failed: An unexpected error occurred during deployment.
- I am able to SSH to the server.
- I ran the commands to check disk space and memory and they do not seem to be a problem. This is quite a small application that only a few people are using for testing right now.
- Here is my current deployment script:
cd /home/forge/mysite.on-forge.com
git pull origin $FORGE_SITE_BRANCH
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
# Prevent concurrent php-fpm reloads...
touch /tmp/fpmlock 2>/dev/null || true
( flock -w 10 9 || exit 1
echo 'Reloading PHP FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9</tmp/fpmlock
npm ci && npm run build
This is the same script that has been working fine for months.
- The hosting from Vultr. There no outages that I can detect. (And the front end of the app is working fine)
- I'm not sure I understand what #7 involves or does.
- I have re-run the deployment several times in Forge. How would I attempt to deploy it manually?
earmsby started a new conversation+100 XP
2mos ago
I'm trying to deploy some very minor changes on a Forge site that I've deployed to at least 50 times over the past year or two. Today when I tried to deploy these couple of changes, I got this error"
Tunnel exited with a non-zero code [1].
Error output:
Mon Feb 23 05:40:20 PM UTC 2026
Any suggestions on how to figure out what the problem might be?
earmsby wrote a reply+100 XP
2mos ago
earmsby started a new conversation+100 XP
2mos ago
I'm trying to implement two separate importers on the same model (Contract). I want one to create new records only and the other update existing records only. I know you can combine these, but the client I'm building for needs these to be separated.
What is the best approach for this? FWIW, I've already fully built the importer to create new records. Now I'm looking to build a second importer which only updates Contracts.
earmsby wrote a reply+100 XP
2mos ago
earmsby liked a comment+100 XP
2mos ago
Certainly! The issue here is that you're using a relative path as the file URL, so Filament is treating it as relative to the current page (which is at /contracts/55), resulting in a link like /contracts/contract_pdfs/....
Instead, you should generate an absolute URL to your file. The best practice is to use Laravel's Storage::url() method, which will produce a URL relative to your public disk and will honor your storage:link configuration.
Here’s how you can fix your code:
use Illuminate\Support\Facades\Storage;
// ...
TextEntry::make('contract_pdf')
->url(fn ($record) => $record->contract_pdf
? Storage::disk('public')->url($record->contract_pdf)
: null)
->openUrlInNewTab()
->inlineLabel(),
Explanation:
Storage::disk('public')->url($record->contract_pdf)will generate a URL like/storage/contract_pdfs/filename.pdf, which is correct if you’re storing in thepublicdisk and used the default storage symlink setup.- The check for
? $record->contract_pdf : nullensures you don't get a URL if there's no file.
Bonus: If, for any reason, you want to display just the file name (not the path), you can use:
TextEntry::make('contract_pdf')
->label('Contract PDF')
->url(fn ($record) => $record->contract_pdf
? Storage::disk('public')->url($record->contract_pdf)
: null)
->display(fn ($record) => basename($record->contract_pdf))
->openUrlInNewTab()
->inlineLabel(),
Summary:
Always use Storage::url() to generate file URLs for files managed by Laravel's storage system. This guarantees you get the right, absolute URL every time.
Let me know if you have further questions!
earmsby started a new conversation+100 XP
2mos ago
I have a Filament form with this upload field:
FileUpload::make('contract_pdf')
->disk('public')
->directory('contract_pdfs')
->maxSize(200000)
->visibility('public')
I set up the symlink using php artisan storage:link and that seems to be working just fine.
My infolist for this field is:
TextEntry::make('contract_pdf')
->url(fn ($record)=> $record->contract_pdf)
->openUrlInNewTab()
->inlineLabel(),
The link is mostly correct and opens in a new tab as expected but the link is: http://myURL/contracts/contract_pdfs/01KHS8DGGNZP2J6MV7C38012AK.pdf instead of: http://myURL/contract_pdfs/01KHS8DGGNZP2J6MV7C38012AK.pdf
If I manually change the url and take out the "contracts", I can view the file.
The url of the infolist is: http://myURL/contracts/55 So, I can see that it's using a relative link instead of an absolute one. Is there a way to set this?
earmsby wrote a reply+100 XP
2mos ago
earmsby started a new conversation+100 XP
2mos ago
I am banging my head trying to figure what the problem is with my importer.
I have a csv file like this:
"contract_description","default_copyright_holder","contract_type","date_executed"
"Contract 1","Subito Music Corp.","Publishing","11/14/18"
"Contract 2","Subito Music Corp.","Publishing","12/13/17"
The field "contract_type" is the name of a ContractType model so I have to find the id from the name supplied. I'm using the castStateUsing method like so:
ImportColumn::make('contract_type')
->castStateUsing(function (?string $state) {
Log::debug('Contract Type from CSV: ' . $state);
if (blank($state)) {
return null;
}
//query the ContractRights table to get the ID
$type = ContractType::where('contract_type_name', 'like', '%' . $state . '%')
->first();
if (empty($type)) {
return null;
}
return $type->id;
})
->requiredMapping()
->numeric()
->rules(['required', 'integer']),
As you can see I added a Log statement to try to troubleshoot why this kept failing. The log shows $state as 0. I've doublechecked that the values in the csv as the strings shown above but the $state is always zero. Why? I must be missing something dumb, but I just can't spot it.
earmsby started a new conversation+100 XP
2mos ago
I have a bunch of different sites deployed on Forge. In one or two, I'm using Filament importing and exporting and thus I have a Queue Worker process running.
I noticed a difference between the deployment scripts for more recently created sites and older sites. One thing is that on the newer sites, there is this in the deployment script:
$RESTART_QUEUES()
On an older site where I'd also like to restart the queue when I deploy changes, I don't have that. I tried adding this line to the deployment script but it caused the deployment to fail. I'm guessing that's because the whole deployment process is different between the two sites.
Could I just copy the whole script (editing as needed to pertain to the site) from the newer site to the older one or are other steps needed to accomplish this? Alternatively, is there a difference command to use that would restart the queue and also work in the older style deployment script?
For reference, here is the entire script for the older site:
cd /home/forge/my-site.on-forge.com
git pull origin $FORGE_SITE_BRANCH
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
# Prevent concurrent php-fpm reloads...
touch /tmp/fpmlock 2>/dev/null || true
( flock -w 10 9 || exit 1
echo 'Reloading PHP FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9</tmp/fpmlock
npm ci && npm run build
And here's the whole script for the newer site:
$CREATE_RELEASE()
cd $FORGE_RELEASE_DIRECTORY
$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader
$FORGE_PHP artisan optimize
$FORGE_PHP artisan storage:link
$FORGE_PHP artisan migrate --force
npm ci || npm install && npm run build
$ACTIVATE_RELEASE()
$RESTART_QUEUES()
earmsby wrote a reply+100 XP
2mos ago
earmsby liked a comment+100 XP
2mos ago
You shouldn't touch your server's timezone. What if you have another system to communicate with - are you going to change your server settings again? This is not way to go.
You should send correct timestamps to WooCommerce instead.
If WooCommerce can accept timestamps with timezone - prepare timestamps with timezone:
$today_start = (new \DateTimeImmutable('today 00:00:00'))->format(DATE_ATOM);
$today_end = (new \DateTimeImmutable('today 23:59:59'))->format(DATE_ATOM);
// assuming your time zone is +5 it gives you:
// start: 2026-01-31 00:00:00+05:00
// end: 2026-01-31 23:59:59+05:00
If it can't accept timezones - know which time zone WooCommerce operates in and tune timestamps with that time zone implicitly:
// assuming WooCommerce timezone is UTC:
$today_start = (new \DateTimeImmutable('today 00:00:00'))->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
$today_end = (new \DateTimeImmutable('today 23:59:59'))->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i:s');
// start: 2026-01-30 19:00:00
// end: 2026-01-31 18:59:59
As a general rule, a timestamp (a value referring to a point in time) must always exist with timezone explicitly defined, to prevent bugs like you have now.
This is bad as it refers to different point in time depending on where the value is interpreted:
2026-01-31 11:22:33
Good, explicit and solid value:
2026-01-31 11:22:33+05:00
Another general rule: always operate with dates using libraries provided by PHP and Laravel: DateTime, DateTimeImmutable, Carbon. They are really made for purpose. Don't rely on simple string manipulation.
earmsby liked a comment+100 XP
2mos ago
Great question! You're running into a classic timezone trap when integrating two different systems.
Short answer:
Yes, it is usually safe to change your server's timezone to match your WooCommerce site's timezone, especially given your use case (private dashboard, no critical DB timestamps, no cron jobs, etc.). This will likely solve your immediate issue with "today's" dates aligning between your servers.
However... There are a few broader things to consider:
1. Laravel and Timezones
Laravel (and PHP) handle timezones in three places:
- PHP's default timezone (
php.ini, or viadate_default_timezone_set), - The "app" timezone (
config/app.php→timezone), and - The database timezone (typically UTC).
Best practice is often to keep your server in UTC and adjust the app timezone for display or calculations. This prevents surprises if you ever add new team members, automate backups, run scheduled tasks, or log events shared with others in different regions.
2. Direct Date Usage and API Filtering
Your code directly uses PHP’s date() function. By default, this is based on the server's timezone. If the server drifts into "tomorrow" earlier than your WooCommerce site, your queries won’t align — exactly as you're seeing.
3. The Real Fix: Make Timezone Explicit
Rather than rely on the server’s system timezone, it's safer to set your PHP/Laravel app and date calculations to use your desired timezone explicitly.
Change the timezone in PHP or Laravel, not on the server's system itself.
If you use Laravel
Set the app's timezone to match your WooCommerce site:
// config/app.php
'timezone' => 'America/Los_Angeles', // or whatever your shop uses
Then, generate your dates using Carbon:
$today = Carbon\Carbon::now()->startOfDay();
$tomorrow = Carbon\Carbon::now()->endOfDay();
$params = [
'after' => $today->format('Y-m-d\TH:i:s'), // T00:00:00
'before' => $tomorrow->format('Y-m-d\TH:i:s'), // T23:59:59
'status' => 'processing,completed',
];
$orders_today = $woocommerceClient->get('orders', $params);
If you just use PHP
Set the default timezone at the top of your script:
date_default_timezone_set('America/Los_Angeles'); // Or your WooCommerce timezone
$today_start = date('Y-m-d') . 'T00:00:00';
$today_end = date('Y-m-d') . 'T23:59:59';
$params = [
'after' => $today_start,
'before' => $today_end,
'status' => 'processing,completed',
];
$orders_today = $woocommerceClient->get('orders', $params);
Summary
- Yes, you can safely change your server timezone given your low-risk scenario.
- But, it's usually better to control the timezone from your PHP/Laravel app layer!
- This avoids surprises if something changes on the server, or if you deploy to another host in the future.
If changing the timezone in your code isn’t feasible, then updating the server is fine for your case. But if you want maximum portability and future-proofing: do it in your application layer!
If you need help with this in Laravel or PHP, let me know!
earmsby started a new conversation+100 XP
2mos ago
I have a filament app on a forge server which has a widget to fetch my WooCommerce orders for today. The WooCommerce site is on a completely different server and I use the API to interact with it on my filament app.
I fetch orders like this:
//get today's orders
$today_start = date('Y-m-d') . 'T00:00:00';
$today_end = date('Y-m-d') . 'T23:59:59';
$params=[
'after'=>$today_start,
'before'=>$today_end,
'status' => 'processing,completed'
];
$orders_today=$woocommerceClient->get('orders',$params);
... etc.
The trouble is when it fetches orders later in the day, the server thinks it's already tomorrow and shows zero orders. It seemed to me that simply changing the server's timezone to my own and the same as the WooCommerce site, that would solve this problem.
FWIW, I don't have any chron jobs on this server. Also, no high stakes date fields in my database. In addition, this is not a public-facing site - just a dashboard only I use to manage some things.
Are there reasons not to change the timezone?
earmsby wrote a reply+100 XP
2mos ago
earmsby liked a comment+100 XP
2mos ago
Create an accessor with get function returning masked value:
fn($value) => Str::mask($value, 0, -4);
https://laravel.com/docs/12.x/eloquent-mutators#defining-an-accessor
https://laravel.com/docs/12.x/strings#method-str-mask
Update: but I don't recommend you go this way as you may need to have unmasked value in some parts of your app. I'd better apply Str::mask only in places where dangerous value can be seen by a user, like in views.
earmsby started a new conversation+100 XP
2mos ago
I have a model Account with various fields:
class Account extends Model implements Auditable
{
use HasFactory;
use \OwenIt\Auditing\Auditable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'account_number',
'account_type',
'name_title',
'first_name',
'middle_name',
'last_name',
[... more fields]
'tax_id',
];
protected function casts(): array
{
return [
'id' => 'integer',
'is_deceased' => 'boolean',
'has_login' => 'boolean',
'is_archived' => 'boolean',
'account_type' => AccountType::class,
'added_by' => 'integer',
'last_mod_by' => 'integer',
];
}
I've just added that last 'tax_id' and I'm creating the migration to add the new field to the database.
I'm hoping to store the tax_id field hashed (like passwords in the Users table) but then will need to show something like this in the view for the account info:
Tax ID: *--1234
I'm sure this is fairly common, but would appreciate guidance on how to set up the model, the migration and the view.
Thanks for any suggestions on best approach.
earmsby wrote a reply+100 XP
2mos ago
earmsby wrote a reply+100 XP
2mos ago
earmsby wrote a reply+100 XP
3mos ago
I just noticed something subtle in the error message that I didn't notice at first:
TypeError: Cannot assign __PHP_Incomplete_Class to property Filament\Actions\Exports\Jobs\PrepareCsvExport::$exporter of type Filament\Actions\Exports\Exporter in /home/forge/hildegard-dashboard.on-forge.com
The error seems to be referring to my project on the production server: "/home/forge/hildegard-dashboard.on-forge.com" even though I'm testing this exporter on my local Herd site.
Why would it be doing that?
earmsby wrote a reply+100 XP
3mos ago
Unfortunately, none of that solved the issue.
- I doubled-checked the namespace and the exporter exists on the server and the namespace is correct.
- I ran all four clearing commands
- I ran queue:restart and then queue:work to restart the worker
I still got the same error in the failed_jobs table.
I am only running this on my localhost at the moment (using Herd). The env file is set to: QUEUE_CONNECTION=database I am running the queue worker manually via the command line with queue:work.
Anything else to try?
earmsby started a new conversation+100 XP
3mos ago
I have created this exporter:
namespace App\Filament\Exports;
use App\Models\Publication;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
use Illuminate\Support\Number;
class PublicationExporter extends Exporter
{
protected static ?string $model = Publication::class;
public static function getColumns(): array
{
return [
ExportColumn::make('id')
->label('ID'),
ExportColumn::make('catalog_number'),
ExportColumn::make('is_digital_publication'),
ExportColumn::make('title'),
ExportColumn::make('price'),
ExportColumn::make('upc_code'),
[... other columns ...]
ExportColumn::make('created_at')
->enabledByDefault(false),
ExportColumn::make('updated_at')
->enabledByDefault(false),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your publication export has completed and ' . Number::format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . Number::format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}
The queue worker is running and, in fact, I have a second exporter on a different model that is working fine. When I try to run the above export, it fails (no notification though). In the failed jobs table, I can see the exception:
TypeError: Cannot assign __PHP_Incomplete_Class to property Filament\Actions\Exports\Jobs\PrepareCsvExport::$exporter of type Filament\Actions\Exports\Exporter in /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/SerializesModels.php:96
Stack trace:
#0 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/SerializesModels.php(96): ReflectionProperty->setValue()
#1 [internal function]: Filament\Actions\Exports\Jobs\PrepareCsvExport->__unserialize()
#2 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(95): unserialize()
#3 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(62): Illuminate\Queue\CallQueuedHandler->getCommand()
#4 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(102): Illuminate\Queue\CallQueuedHandler->call()
#5 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(485): Illuminate\Queue\Jobs\Job->fire()
#6 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(435): Illuminate\Queue\Worker->process()
#7 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(201): Illuminate\Queue\Worker->runJob()
#8 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(148): Illuminate\Queue\Worker->daemon()
#9 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(131): Illuminate\Queue\Console\WorkCommand->runWorker()
#10 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\Queue\Console\WorkCommand->handle()
#11 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Container/Util.php(43): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#12 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(96): Illuminate\Container\Util::unwrapIfClosure()
#13 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\Container\BoundMethod::callBoundMethod()
#14 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Container/Container.php(799): Illuminate\Container\BoundMethod::call()
#15 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\Container\Container->call()
#16 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/symfony/console/Command/Command.php(341): Illuminate\Console\Command->execute()
#17 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Console/Command.php(180): Symfony\Component\Console\Command\Command->run()
#18 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/symfony/console/Application.php(1102): Illuminate\Console\Command->run()
#19 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/symfony/console/Application.php(356): Symfony\Component\Console\Application->doRunCommand()
#20 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/symfony/console/Application.php(195): Symfony\Component\Console\Application->doRun()
#21 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(198): Symfony\Component\Console\Application->run()
#22 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1235): Illuminate\Foundation\Console\Kernel->handle()
#23 /home/forge/hildegard-dashboard.on-forge.com/releases/62766940/artisan(16): Illuminate\Foundation\Application->handleCommand()
#24 {main}
I can't quite figure out from this what the problem is. FWIW, I have restarted the queue multiple times and cleared the cache.
earmsby liked a comment+100 XP
3mos ago
Despite the hype around AI coding tools, which are indeed very helpful, we still need a solid understanding of fundamentals such as relationships, queues and jobs, DDD, TDD, REST APIs, models, broadcasting, and more. We are in charge of AI, not the other way around. That’s why we still need to learn and truly understand programming concepts, languages, and paradigms, and in this particular case, the Laravel ecosystem. For this reason, platforms like Laracasts remain extremely valuable.
earmsby wrote a comment+100 XP
3mos ago
When I saw the title of this episode, I was really worried that you were going to shut down Laracasts. So glad you are not. I really value this platform a great deal. That said, I'm checking out the new series on AI coding next. I've mostly ignored AI until now, but you make a really good case that, as developers, we really can't afford to do that.
earmsby liked a comment+100 XP
3mos ago
I'd love to see a snippet on here showing the code Claude generated you for those two features... yes it works but heres why it sucks and why I changed it. I'd love more lessons on the thought process behind things with real world examples. I know theres the whole AI course that I'll definetly checkout, but real work examples are so useful the more the better tbh. I'm glad to hear your getting through the tough waters as someone that's just signed up I really enjoy the teaching style :)
earmsby wrote a reply+100 XP
3mos ago
earmsby started a new conversation+100 XP
3mos ago
When testing out some functions on my local machine, I connect to the live DB on my Forge server via SSH like so:
ssh -L 3307:127.0.0.1:3306 [email protected]
My env file for this is:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=my_db
DB_USERNAME=forge
DB_PASSWORD=my_password
This has been working fine for months. But just today when I opened the app on local after SSHing to the DB with the above command, I get a message: Access denied for user 'forge'@'localhost'
I'm a bit confused why I'm getting that. For what it's worth another forge site is working just fine.
earmsby started a new conversation+100 XP
3mos ago
This is probably a dumb question:
I have a Filament table with a column like this:
ImageColumn::make('head_shot')
->label('')
->disk('public')
->visibility('public')
->defaultImageUrl(url('storage/authors/default_avatar.png'))
->circular(),
On my local server (Herd), I just added the file default_avatar.png to the storage/authors directory and all is working. Now I'm ready to push my new column to the app on my Forge server. Of course, the storage directory is ignored by version control in my IDE. So, how do I get the default_avatar.png file to the storage/authors directory on Forge? Can I just upload it via SFTP or something?
earmsby wrote a reply+100 XP
3mos ago
FWIW, while I don't know the exact cause of this, I decided there was probably something off-kilter with my project in general and therefore in the git repo. So, I started over from scratch and created a brand new project which I successfully deployed to the Forge server. Now, I'm just building back the data and functions in my app but so far, deployment has been working fine.
earmsby wrote a reply+100 XP
3mos ago
I'm still stuck on this.
- I changed the deployment script to what is shown by Larry AI (changing the domain, of course).
- When I ran the deployment again, the error is:
fatal: not a git repository (or any of the parent directories): .git
=> Deployment failed: An unexpected error occurred during deployment.
- I SSHed into the version checked the versions of node and npm: node=v.22.13.0 & npm=10.9.2
Not sure if I should try step #4. My app has nothing to do with Python, so I imagine step 5 is not applicable. Also not sure if I should try #6 and I don't understand #7 at all.
I've deleted the site and retried it several times and it always fails in the same way. I really don't understand why the deploy script says "not a git repository."
At this point, I'm wondering if the problem is with the Git repo itself...
earmsby wrote a reply+100 XP
3mos ago
I'm not sure how I can check the deployment script before I create a new site. Isn't the script set up after you create the site?
Also, I cannot do step 2 "2. Review the Deployment Output." In the deployments tab it just says no deployments yet. So, I feel like I'm kind of stuck.
Perhaps I'll try creating a whole new app/repo and copying over most of my work to a new version.
earmsby started a new conversation+100 XP
3mos ago