What do you mean by “rich possibilities of PHP classes”?
All your Laravel classes are PHP classes. Any ‘rich possibilities’ available in PHP classes that you want to use, just… use them.
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hello, Last years I work with laravel and I have a few opportunities to work with php classes. I suppose I created custom classes for services(with implementation of Interface defined). I wonder in which way I can use rich possibilities of classes of PHP inside of laravel app. And as example SOLID rules like written here?
https://medium.com/prod-io/solid-principles-takeaways-ec0825a07247 Please refs to similar examples, tutorials...
Thanks!
What do you mean by “rich possibilities of PHP classes”?
All your Laravel classes are PHP classes. Any ‘rich possibilities’ available in PHP classes that you want to use, just… use them.
@mstdmstd Laravel is a PHP framework written in an object-oriented way. It’s difficult to work with Laravel without using classes.
I mean using My custom classes with soild rules. I want practical skills in it. I requested them on interview when searching for job
@mstdmstd SOLID principles are just guidelines. Shoe-horning them into code doesn’t magically make your code “better”. It’s entirely possible to over-engineer your code and make it more complicated.
If you want to learn SOLID principles then maybe watch some of the videos on the topic on Laracasts. Because you’ve been on this site for literally years now but yet have only completed a mere 4 lessons.
There is no reason why you can't just use those principles in a laravel app. Just force yourself to follow those principles in a new project. Maybe write a few service classes or similar that use interfaces and stick to solid
There is also a solid course https://laracasts.com/series/solid-principles-in-php
I make review one of my last app when in thin control I call method from service class :
<?php
public function update(Request $request, $id)
{
$loggedUser = Auth::user();
$requestData = $request->all();
if (empty($requestData['creator_id'])) {
$requestData['creator_id'] = $loggedUser->id;
}
return $this->pageMethodsService->update(
id : $id,
requestData : $requestData,
pageUploadedImageFile: $request->file('image'),
pageUploadedDocumentFile: $request->file('document'),
makeValidation : true
);
}
...
public function update(
array $requestData,
UploadedFile|string $pageUploadedImageFile = null,
UploadedFile|string $pageUploadedDocumentFile = null,
int $id,
bool $makeValidation = false
): \Illuminate\Http\JsonResponse | \Illuminate\Support\MessageBag {
$page = Page::find($id);
if ( ! $page) {
return response()->json('Page # ' . $id . ' not found', HTTP_RESPONSE_NOT_FOUND);
}
$loggedUser = Auth::user();
if($this->checkActiveUser and $loggedUser->status != 'A') {
return response()->json('Your account is not active to run "update" action', HTTP_RESPONSE_UNAUTHORIZED);
}
if ($loggedUser->id !== $page->creator_id) { // Only owner of the page can update the page
return response()->json('Only owner of the page can update the page', HTTP_RESPONSE_UNAUTHORIZED);
}
if ($page->published) { // Owner of the page can update only unpublished page
return response()->json('Owner of the page can update only unpublished page',
HTTP_RESPONSE_BAD_REQUEST);
}
DB::beginTransaction();
try {
Before Transaction I have several rules. How to implement with custom validation classes ?
Firstly I tried to create a custom class with command
php artisan make:request UpdatePageRulesRequest
But I found it not good for my purposes. I want to have something like :
$page = Page::find($id);
$loggedUser = Auth::user();
$updatePageRules = new UpdatePageRules(page : $page, actionLabel: "update");
$retRules = $updatePageRules->check( rules : [CK_NOT_FOUND, CK_ACTIVE_STATUS, CK_CHECK_CREATOR, CK_CHECK_PUBLISHED ] );
if(!$retRules['result']) {
return response()->json($retRules['message'], $retRules['returnCode']);
}
and inside of UpdatePageRules::check method make several conditions and returning array with ['result', 'message', 'returnCode'].
Maybe UpdatePageRules::check has to raise some custon exception, but in which way then can be cathed in update method ?
CK_NOT_FOUND, CK_ACTIVE_STATUS - just enum which checks must be run.
In which way it could be implemented to be in good style ?
I managed to create a class app/Library/Rules/RulesPageUpdate.php :
namespace App\Library\Rules;
use App\Models\Page;
use App\Models\User;
use App\Enums\UpdatePageRules;
/**
* Validation rules for page model
*/
class RulesPageUpdate
{
protected int|null $id;
protected Page|null $page;
protected string $actionLabel;
public function __construct(int|null $id, Page|null $page = null, string $actionLabel, User $loggedUser = null)
{
$this->id = $id;
$this->page = $page;
$this->actionLabel = $actionLabel;
$this->loggedUser = $loggedUser;
}
/**
*
* @param array $rulesToValidate - which rules must be checked
* @param bool $checkActiveUser - if logged user must be checked as logged
*
* @return array of : bool 'result' = Was validation successful,
* string 'message' => 'Error message if validation was not successful',
* int 'returnCode' => returned http code
*/
public function check(array $rulesToValidate, bool $checkActiveUser = false): array
{
if (empty($this->loggedUser)) {
return response()->json('Your account is not found to run "' . $this->actionLabel . '" action',
HTTP_RESPONSE_UNAUTHORIZED);
}
if (in_array(UpdatePageRules::UPR_PAGE_NOT_FOUND_BY_ID, $rulesToValidate)) {
if (empty($this->page) or ! ($this->page instanceof \App\Models\Page)) { // check if $this->page is valid Page model
return [
'result' => false,
'message' => 'Page # ' . $this->id . ' not found9999',
'returnCode' => HTTP_RESPONSE_NOT_FOUND
];
}
}
if (in_array(UpdatePageRules::UPR_LOGGED_USER_HAS_NOT_ACTIVE_STATUS_FOR_ACTION, $rulesToValidate)) {
if ($checkActiveUser and $this->loggedUser->status != 'A') { // Logged user account must be active
return [
'result' => false,
'message' => 'Your account is not active to run "' . $this->actionLabel . '" action',
'returnCode' => HTTP_RESPONSE_UNAUTHORIZED
];
}
}
if (in_array(UpdatePageRules::UPR_LOGGED_USER_IS_NOT_CREATOR_OF_PAGE, $rulesToValidate)) {
if ($this->loggedUser->id !== $this->page->creator_id) { // Only owner of the page can update the page
return [
'result' => false,
'message' => 'Only owner of the page can "' . $this->actionLabel . '" the page',
'returnCode' => HTTP_RESPONSE_UNAUTHORIZED
];
}
}
if (in_array(UpdatePageRules::ONLY_UNPUBLISHED_PAGE_UPR_CAN_UPDATED, $rulesToValidate)) {
if ($this->page->published) { // Owner of the page can update only unpublished page
return [
'result' => false,
'message' => 'Owner of the page can "' . $this->actionLabel . '" only unpublished page',
'returnCode' => HTTP_RESPONSE_BAD_REQUEST
];
}
}
return [
'result' => true,
'message' => '',
'returnCode' => HTTP_RESPONSE_OK
];
}
}
I dislike using of Union types, like :
protected int|null $id;
protected Page|null $page;
But I do not how else it can be done.
And calling of it in a controller :
$loggedUser = Auth::user();
$page = Page::find($id);
$rulesPageUpdate = new RulesPageUpdate(id: $id, page : $page, actionLabel: "update", loggedUser: $loggedUser);
$retResults = $rulesPageUpdate->check( rulesToValidate:
[
UpdatePageRules::UPR_PAGE_NOT_FOUND_BY_ID,
UpdatePageRules::UPR_LOGGED_USER_HAS_NOT_ACTIVE_STATUS_FOR_ACTION,
UpdatePageRules::UPR_LOGGED_USER_IS_NOT_CREATOR_OF_PAGE,
UpdatePageRules::ONLY_UNPUBLISHED_PAGE_UPR_CAN_UPDATED
],
checkActiveUser: $this->checkActiveUser
);
if(!$retResults['result']) {
return response()->json($retResults['message'], $retResults['returnCode']);
}
DB::beginTransaction();
...
Can it be done in better way ?
@mstdmstd A few things.
You can make things optional with ?
protected ?Page $page;
And you can use dependency injection to resolve RulesPageUpdate. But that would require you to move the parameters to a method and clean it up.
@Sinnbeck I used Page|null - that is UnionType - new feature of PHP8.
Please link where optional
protected ?Page $page;
described? How it works?
@mstdmstd For the question marks, see the PHP docs on nullable types.
If you want to simplify your class definition and constructor, you can also use constructor property promotion:
namespace App\Library\Rules;
use App\Models\Page;
use App\Models\User;
use App\Enums\UpdatePageRules;
/**
* Validation rules for page model
*/
class RulesPageUpdate {
public function __construct(protected ?int $id, protected ?Page $page, protected ?string $actionLabel, public ?User $loggedUser) {}
// rest of class
}
Note, however, that as of PHP 8.0, your constructor would be invalid (or rather, deprecated), since required arguments must come before optional ones. Since the only required argument is $actionLabel, that should come first in the argument list.
@mstdmstd https://www.php.net/manual/en/language.oop5.properties.php#language.oop5.properties.typed-properties
public ?string $name;
And regarding dependency injection. You can inject it in the method
public function foo(RulesPageUpdate $rulesPageUpdate)
{
$rulesPageUpdate->setParameters(id: $id, page : $page, actionLabel: "update", loggedUser: $loggedUser);
//rest of code
}
Here it would require you to rename __construct() to setParameters(). But its just an example. I might prefer setters for each
Please or to participate in this conversation.