maxxxir's avatar

is this pattern a good idea ? need opinion of senior developer

i use service to run most of my logic usually people put in the controller , i used to call the services with facade but most of my services should be tight coupled with model objects

when i use facade the only way to pass model object to service class is as a function argument which can be counterproductive since we may need it in multiple methods or parent class methods

UserController 

function doSomething(Model/User $user){
   DoSomethingServiceFacade::doIt($user);
}

App/Services/DoSomethingService

class DoSomethingService extends BaseService {

     public  function doIt(Model/User $user){
        $this->checkSomething($user);
		$this->baseServiceMethod($user);
     }

     private function checkSomething( Model/User $user ){
		 // checking 
     }
}

i want my service to be tight coupled with the model object so i dont have to pass it around when i call methods inside service

class DoSomethingService extends BaseService {

    function __construct(protected Model/User $user){}

     public function doIt(){
        $this->checkSomething();
		$this->baseServiceMethod();
     }

     private function checkSomething( ){
		 // checking 
     }
}

but i cant pass the model object to constructor using facade , so here is simplified version of what i came up with

enum UserServiceLoader:string implements ServiceLoaderContract
{
   case DO_SOMETHING = App/Services/Model/DoSomethingService::class  ;
   case DO_SOMETHING_ELSE = App/Services/Model/DoSomethingElseService::class ;
}


Model/User 
class User {
		
	// inside a trait  
	function serve(ServiceLoaderContract $serviceLoader , ... $args ){
		  return new $serviceLoader->value($this  , ...$args );
	}
}

UserController 

function doSomething(Model/User $user){
   $user->serve(UserServiceLoader::DO_SOMETHING)->doIt();
}

im pretty happy with this , calling services is bit bloated but i like readability and tight coupling it provides ... but i like to ask opinion of a senior developer if there is a reason not to use it

0 likes
5 replies
jlrdw's avatar

I generally use another class to return something, Example I have a complex search, rather than a bloated controller method I call a class I made to work up the complex query string needed.

Same for a lengthaware paginator, I have a service class I call.

But usually you are just returning something back to the controller to be used.

1 like
maxxxir's avatar

@jlrdw well if i have a complicated search thats related to my query i put them in a scope in the model ... im asking about service class

but generally yes we both use service class for lengthy logic maybe im haven't been clear , my question is about initiating the service class object and pattern im using todo it not when/which scenario i should use them

1 like
jlrdw's avatar

@maxxxir

my question is about initiating the service class object and pattern im using todo it not when/which scenario i should use them

I use __callStatic() in many cases. But for some simple things I use static methods.

puklipo's avatar

If you're using route model binding, you're relying on Eloquent, so you should make more use of it.

Make it simpler. Traits are sufficient for commonality.

trait DoSomething
{
    public function doIt()
    {
        $this->
    }
}
class User
{
    use DoSomething;
}
class Post
{
    use DoSomething;
}
// Controller 

public function user(User $user){
   $user->doIt();
}

public function post(Post $post){
   $post->doIt();
}

You should get rid of the idea of ​​using the same service class for multiple models. In this day and age, using inheritance for commonality is completely bad practice.

2 likes
maxxxir's avatar

@puklipo thanx maybe you misunderstood me im not using the same service class for multiple models , each model has it's own services for a specific tasks

for example if user wants to delete his account or admin wants to kick some user out .... i want to check if he has any money in his wallet if so i want to return it to his credit card

after that i want to delete all his posts and create a log in db for deleted user

if you put these codes in the controller , you have to repeat it in admin controller and users controller but if you put it in a service class you can use it in both controllers without repeating the codes

also since this service is only for a specific task i can have multiple methods for each task instead of putting all of them inside a single controller method

Please or to participate in this conversation.