imrandevbd was awarded Best Answer+1000 XP
3d ago
Yeah, this is perfectly normal and expected behavior.
When you call $request->session()->invalidate(), Laravel flushes the current session data and immediately regenerates a fresh session ID for security (preventing session fixation attacks). Since the user is now logged out, that new session belongs to a guest which is why you see the new record with a null (or empty string) user_id.
The reason your old session record (user_id = 1) is still sitting in the database is because Laravel handles database session cleanup via a lottery-based garbage collection process under the hood (config('session.lottery')). It doesn't always run a hard DELETE query on the old row at the exact millisecond of logout. In a testing environment, that garbage collection lifecycle rarely triggers.
Don't assert against the raw database row count for sessions because of framework quirks like this. Your $this->assertGuest() check is already the correct and most reliable way to test that the logout was successful.
imrandevbd wrote a reply+100 XP
3d ago
This is Google's security policy at play. They explicitly block OAuth requests coming from embedded WebViews which in-app browsers like Facebook, Instagram, and LinkedIn use to prevent man-in-the-middle attacks. There is no Laravel Socialite or server-side configuration that can bypass this, because Google blocks the request on their end based on the User-Agent.
imrandevbd wrote a reply+100 XP
3d ago
Yeah, this is perfectly normal and expected behavior.
When you call $request->session()->invalidate(), Laravel flushes the current session data and immediately regenerates a fresh session ID for security (preventing session fixation attacks). Since the user is now logged out, that new session belongs to a guest which is why you see the new record with a null (or empty string) user_id.
The reason your old session record (user_id = 1) is still sitting in the database is because Laravel handles database session cleanup via a lottery-based garbage collection process under the hood (config('session.lottery')). It doesn't always run a hard DELETE query on the old row at the exact millisecond of logout. In a testing environment, that garbage collection lifecycle rarely triggers.
Don't assert against the raw database row count for sessions because of framework quirks like this. Your $this->assertGuest() check is already the correct and most reliable way to test that the logout was successful.
imrandevbd wrote a reply+100 XP
3d ago
update your FormRequest to strictly require the field then if you want to manually trigger validation on an untouched input via a button click, you need to pull in the touch method from the slot props and mark the field as touched right before validating.
<template>
<Form method="post" action="/" #default="{ errors, validate, touch }">
<input name="email" value="123">
<p>{{ errors.email }}</p>
<a href="#" @click.prevent="touch('email'); validate('email')">Validate</a><br>
<button type="submit">Submit</button>
</Form>
</template>
imrandevbd wrote a reply+100 XP
3d ago
Don't build this from scratch on top of a basic file host. If UIshare doesn't support signed HLS or DRM natively, you are fighting a losing battle. Look into Bunny Stream (Bunny.net), Mux, or VdoCipher. They handle the DRM (Widevine/FairPlay), HLS encryption, and signed URLs out of the box via simple API SDKs. Re-inventing a bulletproof video security architecture will cost you way more in dev hours and leaked revenue than a managed service ever will.
imrandevbd wrote a reply+100 XP
6d ago
you're testing this by visiting the endpoint directly in your browser, the browser is sending an Accept: text/html header by default instead of application/json
imrandevbd wrote a reply+100 XP
6d ago
imrandevbd liked a comment+100 XP
6d ago
Hello Jeff and colleagues.
I'm watching the 'AI Field Guide' course, and I've noticed that the lessons I've already watched aren't marking as complete.
Thank you. A hug from Argentina
imrandevbd wrote a reply+100 XP
1w ago
Writing to the DB on every single request will definitely crush your database once you start seeing real traffic.
JS sessionStorage won't work if you actually need the server to know their status (for example, to show an "online" badge to other users or for backend analytics), since it only lives in the client's browser.
imrandevbd wrote a reply+100 XP
1w ago
When Laravel sees this, it tells the framework: "Hey, look for a dedicated log channel named deprecations inside the channels array, and route it based on the env variable." But because you don't actually have a channel named deprecations defined inside your channels array, the driver look-up crashes and defaults to falling back into your standard app log. Setting it to null doesn't stop the framework from trying to find the missing channel configuration block.
To fix this and completely silence deprecations without things blowing up, you just need to explicitly define the deprecations channel as a null driver inside your channels array.
Open config/logging.php and update your channels list
imrandevbd wrote a reply+100 XP
1w ago
If you look at how Spark is designed, the static config file (config/spark.php) only holds the configuration and the Paddle Price IDs. It doesn't store the actual price values because those are fetched dynamically from Paddle's API to ensure currency localization and tax/VAT calculations are accurate based on the user's IP.
As Martin pointed out above, Spark uses Cashier::previewPrices() under the hood to fetch these values dynamically.
imrandevbd wrote a reply+100 XP
1w ago
Yeah, LaryAI completely missed the mark on how Filament v3's Importer architecture actually works. You shouldn't be hijacking resolveRecord to handle relationship logic, nor should you return a Work model if this specific CSV row represents a pivot link rather than a new Work record.
Since you're using Filament's native Import action, you have two clean ways to handle this depending on how you want to structure it.
Create a dedicated "Author Import" instead
If your CSV is strictly mapping relationships, it’s much cleaner to map the importer to the pivot table itself, or treat the assignment as the primary record.
However, since account_work_authors is a pivot, you can create a pivot model or just use an ImportColumn hook. The cleanest way inside a Filament Importer class is to use the after() hook on a column or the life-cycle hooks of the importer.
imrandevbd wrote a reply+100 XP
2w ago
Your roadmap is solid, but if you’re on a tight schedule with an existing database, you need to optimize for speed.
imrandevbd wrote a reply+100 XP
3w ago
The issue here is that Vite treats assets as ES modules by default, whereas your current legacy setup relies on strict, sequential concatenation (mix.babel) where jQuery, Angular, and all those plugins register themselves globally on the window object. If Vite processes them, they run in their own module scopes, breaking dependencies like angular or siteApp because jQuery plugins can't find jQuery, and Angular plugins can't find angular.
Since you have a massive list of legacy jQuery and AngularJS v1/v2 vendors, trying to import them properly via ES modules will be an endless rabbit hole of configuration headaches.
The cleanest solution is to let Vite handle your modern code (like your Sass/CSS), but use Vite's build.rollupOptions to keep bundling these legacy assets into flat files, while forcing them to remain global scripts.
imrandevbd wrote a reply+100 XP
3w ago
Since Livewire 4 SFCs use an anonymous class format, listeners need to be defined inside the class definition, typically using the #[On] attribute. If you are dispatching from Blade via wire:click="$dispatch('your-event')" or $this->dispatch(), the receiving SFC needs to look like this
imrandevbd wrote a reply+100 XP
4w ago
Yes, it absolutely applies to aspiring developers. In fact, it’s one of the best ways to break the "need experience to get experience" loop. When you don't have a formal work history, open-source contributions serve as your proof of competence. It shows a hiring manager that you can actually collaborate, handle feedback in code reviews, and navigate a massive, existing architecture things a solo portfolio project rarely demonstrates.
imrandevbd wrote a reply+100 XP
4w ago
If you dig deeper and realize it's the second one? Absolutely move on. Finding out an idea doesn't have a desperate market before you write a single line of code isn't a failure, it's the entire point of doing the UX research to begin with.
imrandevbd wrote a reply+100 XP
4w ago
To answer your first question directly: Yes, your current setup will fire additional queries.
To use the eager-loaded data in memory, you need to access it as a property instead of a method:
public function actualTrainer() {
return $this->mesocycle?->macrocycle?->user?->actualTrainer;
}
As for your second question about architecture: yes, it absolutely makes sense to define these helpers. It actually aligns perfectly with the Law of Demeter. Wrapping deep traversals in a helper keeps your views and controllers clean and prevents you from repeating massive chains all over your codebase.
That said, if you find yourself needing to actually query against this deep relationship (e.g., filtering Microcycle records by a specific trainer), standard helper methods won't work. For that, you should check out Staudenmeir's eloquent-has-many-deep package. It lets you define native Eloquent relationships across unlimited intermediate tables so you can eager load and query them directly.
imrandevbd wrote a reply+100 XP
4w ago
Yes, absolutely possible. Honestly, having actual merged PRs in public repositories often carries more weight than a degree because it proves you know how to read someone else's codebase, use Git properly, and handle code reviews
imrandevbd wrote a reply+100 XP
4w ago
Yes, metrics like latency, throughput, error rates, and response times are absolutely web dev KPIs.
Your NFR might state: The API must have a response time of under 200ms under normal load.
Your KPI is the actual live metric you track in your APM to prove to management or clients that the app is performing as promised.
imrandevbd wrote a reply+100 XP
1mo ago
Honestly, I wouldn't worry too much about it. This is a super common headache with Go-based binaries on Windows. Because Go compiles everything down into a single, packed executable, lazy AV heuristics constantly flag them as generic trojans or ransomware, especially when the binary isn't code-signed
imrandevbd wrote a reply+100 XP
1mo ago
Yeah, deleting package-lock.json on an older project is almost always a trap. It pulls in the latest minor/patch versions of all your nested dependencies (like postcss, sass-loader, terser), which practically guarantees something else will break in a legacy codebase.
Stick to your old working production package-lock.json, and just target the specific package you need to update so it only modifies that specific tree:
npm install laravel-mix@^6.0.49 --save-dev
That will fix the SizeFormatHelpers Webpack issue while keeping the rest of your legacy dependency tree safely locked in place.
imrandevbd wrote a reply+100 XP
1mo ago
Ran into this exact headache mixing containerized and native envs on a team. Don't try to manage multiple AGENTS.md files or conditional AI guidelines per developer it's a maintenance nightmare.
Keep your shared AI guidelines completely standard: let the AI assume everyone uses standard php artisan, composer, and npm.
imrandevbd wrote a reply+100 XP
1mo ago
I've been dealing with PDF generation in Laravel for years, and the waitUntilNetworkIdle() + arbitrary sleep() combo is a universal ticking time bomb. It always works perfectly locally and randomly flakes on production queues when a single webfont or third-party script takes 200ms too long to load.
Inverting the control to window.CANIO_READY is 100% the right call for complex documents (Chart.js, async data). It turns a race condition into a deterministic state. I've had to hack together similar window flags in raw Puppeteer scripts in the past just to stop the bleeding, so having it natively handled by a package is a massive win.
imrandevbd wrote a reply+100 XP
1mo ago
Webpack removed SizeFormatHelpers in v5.76.0. Your project probably pulled in the newer webpack automatically, which breaks the BuildOutputPlugin in older Mix releases.
Just bump laravel-mix to ^6.0.49 in your package.json. Jeffrey patched this exact issue a while back so you don't need to downgrade Webpack like the AI suggested.
Wipe your node_modules and package-lock.json, run npm install, and you should be good to go.
imrandevbd wrote a reply+100 XP
1mo ago
Snapey's presence channel idea is solid, but if you want to avoid the overhead of Reverb/websockets, you can handle this reliably using a Redis cache lock combined with a JS heartbeat. I've used this exact pattern in production for high-stakes exam platforms.
Backend Lock: In that controller, store the lock in Redis: Cache::put("test_lock_{$test->id}user{$user->id}", $tab_id, 10);. The 10-second TTL is the magic number here.
Enforcement: On the actual test attempt route (and on subsequent test submissions), check this cache key. If the key exists AND the value doesn't match the current request's tab_id, throw your "already active" error.
imrandevbd was awarded Best Answer+1000 XP
1mo ago
That error is popping up because you're adding a manual error to the validator without a numeric key. Laravel Excel expects the attribute name to follow a specific pattern (like row_number.column) so it can parse the row index. When you just pass 'Green Bean', strtok fails to find a numeric row index, passing a string to the Failure constructor instead.
Also, your current logic for checking the bean in the collection method won't work for validation because rules() and withValidator() run before the collection() method even touches the data.
namespace App\Imports;
use Maatwebsite\Excel\Concerns\ToCollection; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Concerns\WithValidation; use Illuminate\Support\Collection;
class RoastImport implements ToCollection, WithHeadingRow, WithValidation { public function collection(Collection $rows) { // Your import logic here }
public function rules(): array
{
return [
// 'beans' matches the slugified header 'Beans'
'beans' => ['required', 'exists:green_beans,name'],
// 'out_g' matches 'Out (g)'
'out_g' => ['required', 'numeric'],
];
}
public function customValidationMessages()
{
return [
'beans.exists' => 'The selected Green Bean is invalid.',
'out_g.required' => 'The Out (g) column cannot be empty.',
];
}
}
imrandevbd wrote a reply+100 XP
1mo ago
Hey man, been there. A 403 Forbidden on the broadcasting/auth route almost always means your frontend is successfully hitting the endpoint, but Laravel is explicitly rejecting the authorization for that specific private channel.
imrandevbd wrote a reply+100 XP
1mo ago
Hey motinska94, I hear you loud and clear.
First off, keep your head up. Being an unemployed student is a tough grind, but the fact that you are actively seeking out high-quality resources to learn Laravel shows you have the exact right mindset for this industry.
I completely understand why that comment stung. When you live and work in the US or Western Europe, $15 truly is just the cost of a quick lunch. But you are 100% right the global economy doesn't run on the USD. In many parts of the world, including Turkey, $15 is a significant chunk of change. Your Spotify comparison is spot on and really puts things into perspective.
imrandevbd wrote a reply+100 XP
1mo ago
Jussi is spot on about mixing npm/yarn and the missing SCSS file. Stick to npm run dev since you already built your node_modules with npm install. For that missing admin.scss file, double check your .gitignore it’s very common for custom asset directories to accidentally get ignored, meaning it never actually made it to your Github repo in the first place.
Regarding the "Firefox can't connect" error, that's entirely a local DNS/WAMP issue, not a Laravel bug. Your OS simply doesn't know where to route mysite.local
imrandevbd wrote a reply+100 XP
1mo ago
This happens because the starter kits (Breeze/Jetstream) wrap that verification route in the auth middleware by default. When you open the link in a different browser, you're a "guest," so the middleware intercepts the request and redirects you to the login page before the verification logic even runs.
To fix this, you need to allow guests to hit that endpoint and manually find the user since $request->user() won't be available.
First, in routes/auth.php, move the route outside the auth middleware group, Then, you'll need to tweak the VerifyEmailController. Since you aren't using the auth middleware anymore,
imrandevbd wrote a reply+100 XP
1mo ago
You already hit the nail on the head observers only fire on database operations, and time passing isn't a database operation.
Like the others mentioned, a scheduled command running everyMinute(). Instead of adding a published_processed_at timestamp though, I usually just rely on a status column (e.g., switching it from scheduled to published). Grab records where published_at <= now() and status === 'scheduled', fire your service, and update the status.
imrandevbd wrote a reply+100 XP
1mo ago
Since the login and public pages are hitting, Nginx is likely configured correctly. This usually boils down to Filament’s own authorization layer or basic directory permissions on the AWS instance.
please check this one, This is the most common culprit. In production, Filament restricts access by default. Ensure your User model implements the FilamentUser interface and that the canAccessPanel method is actually returning true for your account.
another check in file permission, sudo chown -R www-data:www-data storage bootstrap/cache sudo chmod -R 775 storage bootstrap/cache
imrandevbd wrote a reply+100 XP
1mo ago
That MGET strategy for BelongsTo is definitely the right call saves a ton of overhead compared to standard query caching.
I’m curious about the hydration side of things. When you're pulling a large collection and stitching all those normalized models back together, have you noticed much of a CPU hit on the PHP side? Reconstructing Eloquent models in a loop can get pricey if the collection is huge.
Also, how are you handling count() or exists()? Do those get their own entries in the query map, or are they just bypassing the cache for now?
imrandevbd wrote a reply+100 XP
1mo ago
Hey Kai, really solid concept here. Dealing with Redis memory bloat from duplicate query collections is a massive headache, especially on some of the larger Laravel apps I manage where tables easily hit 60M+ records. Bringing the Redux/Apollo normalized store pattern to Eloquent is a brilliant approach to solving that.
Quick question on the architecture: how are you handling eager loaded relationships (with())? Does the package normalize the nested models and just store their IDs on the parent, or are they embedded directly within the parent model's cached payload?
imrandevbd liked a comment+100 XP
1mo ago
Hey everyone 👋
Over the past few months, I’ve been working on a small open-source package called laravel-normcache.
It actually started from a problem I kept running into across a few different projects. I found myself repeatedly building the same kind of caching layer to avoid redundant Eloquent data sitting everywhere in Redis, so eventually I thought: why not turn it into a reusable package.
A lot of the ideas are inspired by patterns used in things like Redux/Apollo normalized stores, and I’ve been experimenting and refining things as I use it across real projects.
The main idea behind laravel-normcache is normalizing cached Eloquent results instead of storing entire query collections repeatedly. It stores individual models and query ID maps separately, so when one model changes, every cached query containing that model automatically reflects the update.
Query cache → "posts where active=1, page 2" → [4, 7, 12]
Model cache → post:4 → { id:4, title:..., body:... }
→ post:7 → { id:7, title:..., body:... }
→ post:12 → { id:12, title:..., body:... }
Some things it currently does:
- Automatic caching + invalidation with just a single trait
- Avoids storing duplicate model data across query caches
- Instant consistency across cached query results
- O(1) invalidation using versioned cache keys
- Uses dramatically less Redis memory compared to traditional query caching approaches
There’s still plenty I want to improve and optimize over time, but I felt it was finally in a good enough place to share with the community.
Here’s a quick benchmark comparing direct DB queries vs laravel-model-cache for reference:

I’d love to hear feedback from the Laravel community — especially around architecture, performance, edge cases, and where this could fit into real-world applications. Contributions, issues, benchmarks, and criticism are all very welcome.
Repository: https://github.com/kai-init/laravel-normcache
Thanks for reading 🙏
imrandevbd wrote a reply+100 XP
1mo ago
That error is popping up because you're adding a manual error to the validator without a numeric key. Laravel Excel expects the attribute name to follow a specific pattern (like row_number.column) so it can parse the row index. When you just pass 'Green Bean', strtok fails to find a numeric row index, passing a string to the Failure constructor instead.
Also, your current logic for checking the bean in the collection method won't work for validation because rules() and withValidator() run before the collection() method even touches the data.
namespace App\Imports;
use Maatwebsite\Excel\Concerns\ToCollection; use Maatwebsite\Excel\Concerns\WithHeadingRow; use Maatwebsite\Excel\Concerns\WithValidation; use Illuminate\Support\Collection;
class RoastImport implements ToCollection, WithHeadingRow, WithValidation { public function collection(Collection $rows) { // Your import logic here }
public function rules(): array
{
return [
// 'beans' matches the slugified header 'Beans'
'beans' => ['required', 'exists:green_beans,name'],
// 'out_g' matches 'Out (g)'
'out_g' => ['required', 'numeric'],
];
}
public function customValidationMessages()
{
return [
'beans.exists' => 'The selected Green Bean is invalid.',
'out_g.required' => 'The Out (g) column cannot be empty.',
];
}
}
imrandevbd wrote a reply+100 XP
1mo ago
Since you're running a payment gateway, daily dumps are nowhere near enough. You’re dealing with high-stakes transactional data where even 5 minutes of data loss could be a reconciliation nightmare.
In your position, you need to think about RPO (Recovery Point Objective). If the DB blows up at 11:59 PM, and your last dump was 12:00 AM, can you afford to lose 23 hours of transactions? Probably not.
imrandevbd wrote a reply+100 XP
1mo ago
Yeah, laravel-ide-helper is almost certainly your culprit. It generates those massive stub files that end up clashing with Intelephense’s own indexing. When you see update() asking for 4 params, it's usually because the LSP is getting confused between the real Eloquent source and the helper's generated stubs.
Honestly, for Laravel 13, you can kill the ide-helper entirely. The official Laravel extension combined with a paid Intelephense license handles almost everything natively now.
imrandevbd wrote a reply+100 XP
1mo ago
Assuming you're on v3, Livewire::listen is for events, not lifecycle hooks. You need to use Livewire::hook.
For global property updates, you should hook into commit:
use Livewire\Livewire;
public function boot(): void
{
Livewire::hook('commit', function ($component, $commit) {
// You can inspect $commit->updates for specific property changes.
});
}
If you specifically need to run logic before the component finishes its cycle, commit is the standard way to intercept that in v3.
imrandevbd wrote a reply+100 XP
1mo ago
Since you're moving to an S3-compatible bucket on Cloud, the cleanest way to handle 10GB is using rclone directly from your Forge server. Install rclone: sudo apt install rclone
imrandevbd wrote a reply+100 XP
1mo ago
16 reqs/second is actually quite low for a modern SQL database. You should be able to hit 500+ reqs/s on a single instance without breaking a sweat, provided your indexing is solid. You might be over-engineering a bit early.
That said, if you want to move forward with replication for reports and metrics, that’s exactly the right use case for it. To handle the integrity/delay concern you mentioned, Laravel has a sticky option in the database config.
'sticky' => true, When sticky is enabled, if you perform a write during a request cycle, Laravel will immediately switch to using the write connection for any subsequent reads within that same request. This solves the "read-your-own-writes" problem where a user saves data but doesn't see it on the next line of code because the replica hasn't synced yet.
imrandevbd wrote a reply+100 XP
1mo ago
I've been through this exact "extension bloat" cycle. If you're on PHP 8.5 and Laravel 13, you definitely have some redundancy fighting for CPU cycles.
My recommended "Lean" Stack: Intelephense, Laravel, Laravel Pint, PHPStan,
imrandevbd wrote a reply+100 XP
1mo ago
I have to respectfully disagree with the suggestion to use traits here. Moving code into traits just to make a file shorter is an anti-pattern it sweeps the mess under the rug but doesn't fix the underlying architectural issue.
Right now, your ActivityService is turning into a God Class because it violates the Single Responsibility Principle. It's handling activity creation, activity deletion, and notification management across multiple distinct domain
imrandevbd wrote a reply+100 XP
1mo ago
My bad you're right, I crossed the streams with the package syntax there.
In native Laravel 13, you need to use the Relation class within your resource's relationships() method. Instead of just returning a string or a simple callable, you return a relation object, which actually has the meta() method built-in.
Try this structure:
use Illuminate\Http\Resources\JsonApi\Relation;
public function relationships(Request $request): array
{
return [
'items' => Relation::toMany('items')
->meta(fn ($item) => [
'pivot_data' => $item->pivot->your_column,
]),
];
}
imrandevbd wrote a reply+100 XP
1mo ago
Honestly, ignore the AI on this one. What you’ve written is a solid, clean Action class. It’s readable, it handles the transaction properly, and it gets the job done.
EDA is fantastic for decoupling, but it’s absolute overkill for a simple stock adjustment. You only really need to go down that road if a stock change needs to trigger a bunch of unrelated side effects like hitting a third-party API, sending emails, or clearing remote caches and you don't want to bloat your main logic.
imrandevbd wrote a reply+100 XP
1mo ago
Profiling basically means "measuring" your code while it runs to see exactly which part is taking the most time. It stops the guessing game.
Since you're seeing this locally too, that’s actually a win it means you can fix it without touching the production server.
The quickest way to do this in Laravel is to install Laravel Debugbar. Run this in your terminal:
composer require barryvdh/laravel-debugbar --dev
Once installed, refresh your slow page. A bar will appear at the bottom. Check these two tabs:
Timeline: This shows you the "execution" flow. If you see a massive gap/block, that’s your bottleneck.
Queries: This shows every database call. If one query is taking 2 seconds or you have 500 duplicate queries (N+1 issue), you’ll see it here instantly.
imrandevbd wrote a reply+100 XP
1mo ago
I'm completely with @martinbean on this one. Over the last decade building large-scale SaaS and ERP systems, every time my team tried to force a strict DDD or custom modular folder structure, we ended up fighting the framework.
Laravel's default structure is incredibly scalable if you just lean into sub-namespaces.
For interfaces, sticking to app/Contracts works perfectly. If a feature has multiple implementations (like different payment gateways or SMS providers), build a Manager class. It mimics how Laravel handles its own core components and makes swapping implementations painless.
imrandevbd wrote a reply+100 XP
1mo ago
The v13 native JSON:API implementation is solid, but the docs are definitely a bit light on the deeper relationship customizations right now.
You can chain the meta() method directly onto your relationship definition. Since you're dealing with pivot values, you can pass a closure to meta() which receives the related model, allowing you to pull those pivot fields dynamically.
imrandevbd wrote a reply+100 XP
1mo ago
Honestly, obfuscation in the PHP world is always a bit of a trade-off. If you’re dead set on it, IonCube or SourceGuardian are really your only professional options, but be prepared for some debugging headaches since Laravel's reflection and dependency injection can get grumpy when the source is mangled.