shahriar_shaon wrote a reply+100 XP
3mos ago
It will work, but it’s not safe or recommended.
Invalidating or regenerating a session changes the application state, and GET requests should be read-only. GET routes are not CSRF-protected and can be triggered unintentionally (by browsers, bots, or malicious sites).
Use a POST route with CSRF protection for logout or session regeneration instead.
Route::post('/logout', function (Request $request) {
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return response()->json(['message' => 'Logged out']);
});
shahriar_shaon wrote a reply+100 XP
4mos ago
shahriar_shaon was awarded Best Answer+1000 XP
4mos ago
You don't have to run this command by hand on your production server: php artisan queue:work. Since you're using Forge, the best way is to set up a Queue Worker (Daemon) so it runs in the background and restarts automatically.
Here’s what you should do on Forge:
- Go to your Server → select your Site.
- Open the Workers (or Daemons) tab.
- Create a new worker with a command like:
php artisan queue:work --tries=3 --timeout=120
- Forge will keep this worker running permanently, restart it if it crashes, and start it again after a reboot
- Make sure your .env queue driver is set properly (e.g., QUEUE_CONNECTION=database or redis).
This is the recommended way of running queue workers in production. If you'd like, you can also run Horizon instead of queue:work.
shahriar_shaon wrote a reply+100 XP
4mos ago
I'm confused about my code structure. Am I on the right track?
I need to know more. When I use PHPStan Max Level, do I have to use annotations in this way?
public function store(StoreUserRequest $request, CreateUser $action): RedirectResponse
{
Gate::authorize('create', User::class);
/** @var array{name: string, email: string, phone: string, is_active: string, password: string|null, avatar: UploadedFile|null, avatar_removed: bool, roles: array<int>, permissions: array<int>} $data */
$data = $request->validated();
shahriar_shaon wrote a reply+100 XP
4mos ago
You don't have to run this command by hand on your production server: php artisan queue:work. Since you're using Forge, the best way is to set up a Queue Worker (Daemon) so it runs in the background and restarts automatically.
Here’s what you should do on Forge:
- Go to your Server → select your Site.
- Open the Workers (or Daemons) tab.
- Create a new worker with a command like:
php artisan queue:work --tries=3 --timeout=120
- Forge will keep this worker running permanently, restart it if it crashes, and start it again after a reboot
- Make sure your .env queue driver is set properly (e.g., QUEUE_CONNECTION=database or redis).
This is the recommended way of running queue workers in production. If you'd like, you can also run Horizon instead of queue:work.
shahriar_shaon wrote a reply+100 XP
4mos ago
shahriar_shaon liked a comment+100 XP
4mos ago
shahriar_shaon wrote a reply+100 XP
4mos ago
shahriar_shaon liked a comment+100 XP
4mos ago
See Nuno and Brent's opinion of Level 9 here https://youtu.be/QFh21mFLH8I?si=gIQOuHwnJDUX0-UR
shahriar_shaon wrote a reply+100 XP
4mos ago
Yes, thank you so much, it's work
I want to know how I can handle that section
public function store(StoreAccountTypeRequest $request, CreateType $action): RedirectResponse
{
Gate::authorize('create', AccountType::class);
/** @var array{code: string, name: string, normal_balance_debit: bool, is_active: string, description: string|null} $data */
$data = $request->validated();
You see, I have to write a lot of heavy annotations just to satisfy PHPStan. cause FormRequest returns me mixed value
shahriar_shaon wrote a reply+100 XP
4mos ago
I actually ran into the same problem recently on a shared hosting environment. Even though my database credentials were correct, the connection kept failing.
What I learned is that on shared hosting, DB_HOST=127.0.0.1 usually doesn’t work. In most cases, you have to use
DB_HOST=localhost
Some providers even give you a custom hostname, something like:
DB_HOST=mysql.yourdomain.com
You can find the correct value in cPanel under MySQL Databases -> Hostname.
Another thing to watch out for is the MySQL port. Some hosts use a different port (like 3307), and if the port doesn’t match, you’ll still get the same “Access denied” error even with the right credentials.
shahriar_shaon wrote a reply+100 XP
4mos ago
I intentionally use final on classes. If a class is not intended to be extended, marking it as final provides an explicit indicator of that intent. It prevents accidental inheritance, keeps the architecture predictable, and encourages composition over unnecessary subclassing.
It also contributes to ease of codebase maintenance, as those classes cannot have their behavior changed through inheritance, thus avoiding any unexpected side effects in the future.
shahriar_shaon started a new conversation+100 XP
4mos ago
My confusion: I’m using PHPStan at the maximum level, which means I have to write a lot of heavy annotations just to satisfy PHPStan. Also, I’ve never used DTOs before — this is my first project using them — so I’m not even sure if I’m following the correct approach.
What’s troubling me the most is that after validating the data, when I pass it into the DTO, PHPStan keeps giving warnings because of mixed values.
I’m sharing my project’s GitHub link below. If anyone kind-hearted could take a look at my code, point out where I’m going wrong, and guide me toward the proper way to structure things, I would really appreciate it.
github.com/shahriarshaon1993/myfinance
My DTO: RoleDto.php
final readonly class AccountTypeDto
{
public function __construct(
public string $code,
public string $name,
public bool $normalBalanceDebit,
public string $isActive,
public ?string $description = null,
) {
//
}
/**
* @param array{code: string, name: string, normal_balance_debit: bool, is_active: string, description: string|null} $data
*/
public static function fromArray(array $data): self
{
return new self(
code: $data['code'],
name: $data['name'],
normalBalanceDebit: (bool) $data['normal_balance_debit'],
isActive: $data['is_active'],
description: $data['description'] ?? null,
);
}
/**
* @return array{code: string, name: string, normal_balance_debit: bool, is_active: string, description: string|null}
*/
public function toArray(): array
{
return [
'code' => $this->code,
'name' => $this->name,
'normal_balance_debit' => $this->normalBalanceDebit,
'is_active' => $this->isActive,
'description' => $this->description,
];
}
}
Request validation: StoreAccountTypeRequest.php
public function rules(): array
{
return [
'code' => ['required', 'string', 'min:2', 'max:50', 'regex:/^[A-Z_]+$/', 'unique:account_types,code'],
'name' => ['required', 'string', 'min:2', 'max:50'],
'description' => ['nullable', 'string', 'min:2', 'max:500'],
'normal_balance_debit' => ['required', 'boolean'],
'is_active' => [Rule::enum(ActiveStatus::class)],
];
}
/**
* @return string[]
*/
public function messages(): array
{
return [
'code.regex' => 'The code may only contain uppercase letters and underscores.',
];
}
Controller is: AccountTypeController.php
public function store(StoreAccountTypeRequest $request, CreateType $action): RedirectResponse
{
Gate::authorize('create', AccountType::class);
/** @var array{code: string, name: string, normal_balance_debit: bool, is_active: string, description: string|null} $data */
$data = $request->validated();
$action->handle(AccountTypeDto::fromArray($data));
return to_route('accounting.types.index')
->with('success', 'Account type created successfully.');
}
Store action class: CreateAccountType.php
public function handle(AccountTypeDto $type): AccountType
{
return AccountType::create($type->toArray());
}
shahriar_shaon liked a comment+100 XP
4mos ago
shahriar_shaon wrote a reply+100 XP
4mos ago
shahriar_shaon wrote a reply+100 XP
4mos ago
Yes, you can set a cookie when returning an Inertia.js response. Inertia responses are still just normal HTTP responses from your backend framework, so you set cookies the same way you normally would. Inertia does not provide its own cookie API.
use Inertia\Inertia;
use Illuminate\Support\Facades\Cookie;
public function index()
{
Cookie::queue('my_cookie', 'some value', 60); // 60 minutes
return Inertia::render('Dashboard', [
'example' => 'data',
]);
}
shahriar_shaon wrote a reply+100 XP
4mos ago
The issue happens because the router is creating a new Pinia store instance when you call useUserStore() inside the router guard. This latest instance does not contain the authenticated user, so isAuthorized always shows false.
router/index.js
import { useUserStore } from '@/store/user'
import pinia from '@/store'
router.beforeEach((to, from, next) => {
const userStore = useUserStore(pinia)
if ((to.name === 'login' || to.name === 'register') && userStore.isAuthorized) {
return next('/')
}
next()
})
shahriar_shaon started a new conversation+100 XP
4mos ago
I’m extremely confused about my code structure and I’m hoping a senior developer can help me out.
My confusion: I’m using PHPStan at the maximum level, which means I have to write a lot of heavy annotations just to satisfy PHPStan. Also, I’ve never used DTOs before — this is my first project using them — so I’m not even sure if I’m following the correct approach.
What’s troubling me the most is that after validating the data, when I pass it into the DTO, PHPStan keeps giving warnings because of mixed values.
I’m sharing my project’s GitHub link below. If anyone kind-hearted could take a look at my code, point out where I’m going wrong, and guide me toward the proper way to structure things, I would really appreciate it.
github.com/shahriarshaon1993/myfinance