SOLID principles apply to terminology at the class level; they do not explicitly indicate methods. SRP itself states that classes should have one reason for change, so if you can replace responsibility that is wrapped in one class, you are fine.
Consider this:
$userMapper = new Mapper\MySQL(); // or $userMapper = new Mapper\Mongo(); // or $userMapper = new Mapper\ArangoDb(); $userService = new UserService($userMapper);
All these switches implement one interface and fulfill one responsibility - they are engaged in abstract access to storage for users. Therefore, mappers have one reason to change, as you can easily change them.
In your case, it's not about SRP. This is more about best practice. Best practice for methods is that they should only do one thing when possible, and take as few arguments as possible. This makes reading and finding errors easier.
There is another principle called the Least Surprise Principle . He simply states that method names must explicitly do what their names mean.
Returning to your code example:
save() implies that all this relates to saving data (updating an existing record), not creating it. By performing both insert and update, you are breaking PoLA.
So that when you explicitly call insert() , you know and expect it to add a new record. The same thing about the update() method - you know and expect that it will update the method, it will not create a new one.
Therefore, I will not do both things in save() . If I want to update a record, I would call update() . If I want to create a record, I would call insert() .
source share