After looking at Services, let's look at a Service example that gets us closer to the "classical" design patterns.
It's an example from our previous lesson. Remember TwitterService, auto-injected into the Controller?
app/Http/Controllers/PublishPostController.php:
use App\Models\Post;use App\Services\TwitterService; class PublishPostController{ public function __invoke(Post $post, TwitterService $twitter) { // ... all other operations with `$post` $tweetResponse = $twitter->tweet($tweetText); if (! isset($tweetResponse['data']->id)) { return; } $tweetUrl = "https://twitter.com/freekmurze/status/{$tweetResponse['data']->id}"; $post->onAfterTweet($tweetUrl); $post->update(['tweet_sent' => true]); }}
TwitterService is a class built for interactions with Twitter via their external API. Look what may be inside that service:
app/Services/TwitterService.php:
namespace App\Services; use Abraham\TwitterOAuth\TwitterOAuth; class TwitterService{ public function tweet(string $text): ?array { if (! app()->environment('production')) { return null; } $twitter = new TwitterOAuth( config('services.twitter.consumer_key'), config('services.twitter.consumer_secret'), config('services.twitter.access_token'), config('services.twitter.access_token_secret') ); return (array) $twitter->post('tweets', compact('text')); }}
In this case, it uses a third-party package for OAuth with Twitter. All good, right?
Now, two questions:
- What if that package gets abandoned?
- What if Twitter's official API changes again? (hi Elon)
Then, this Service class would probably need to find and use another package or use the Twitter API directly to post a tweet.
So then, you have a choice...
The example you have shown uses dependency injection to select a service implementation depending on the environment (production or other). This is not an example of the Strategy pattern because there is no context that dynamically changes behavior at runtime. Instead, the implementation is selected once at application load time, which is more in line with the concept of dependency injection.
Yes please. Can we get an example of how we can change the service in runtime?