Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mstdmstd's avatar

How can I use rich possibilities of classes of PHP inside of laravel app ?

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!

0 likes
11 replies
kokoshneta's avatar

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.

martinbean's avatar

@mstdmstd Laravel is a PHP framework written in an object-oriented way. It’s difficult to work with Laravel without using classes.

mstdmstd's avatar

I mean using My custom classes with soild rules. I want practical skills in it. I requested them on interview when searching for job

martinbean's avatar

@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.

1 like
Sinnbeck's avatar

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

1 like
mstdmstd's avatar

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 ?

mstdmstd's avatar

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 ?

Sinnbeck's avatar

@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.

mstdmstd's avatar

@Sinnbeck I used Page|null - that is UnionType - new feature of PHP8.

Please link where optional

 protected ?Page $page;

described? How it works?

  1. I know how dependency injection works. When I set some service as parameter in constructor of a controller. Please more details how that could work in my case?
kokoshneta's avatar
Level 27

@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.

1 like
Sinnbeck's avatar

@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

1 like

Please or to participate in this conversation.