API integration requires clean code. Laravel 7 introduces elegant HTTP client built on Guzzle. Route caching improvements and fluent strings enhance developer experience. At ZIRA Software, Laravel 7 powers production applications with external API dependencies.
HTTP Client
Before Laravel 7 (using Guzzle directly):
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.example.com/users', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
],
'query' => ['page' => 1],
]);
$users = json_decode($response->getBody(), true);
Laravel 7 HTTP client:
use Illuminate\Support\Facades\Http;
$response = Http::withToken($token)
->get('https://api.example.com/users', [
'page' => 1,
]);
$users = $response->json();
POST requests:
$response = Http::post('https://api.example.com/users', [
'name' => 'John Doe',
'email' => 'john@example.com',
]);
if ($response->successful()) {
return $response->json();
}
Headers and authentication:
// Bearer token
Http::withToken($token)->get($url);
// Basic auth
Http::withBasicAuth('username', 'password')->get($url);
// Custom headers
Http::withHeaders([
'X-Custom-Header' => 'value',
'Accept' => 'application/json',
])->get($url);
Form data:
// JSON (default)
Http::post($url, ['name' => 'John']);
// Form URL encoded
Http::asForm()->post($url, [
'name' => 'John',
'email' => 'john@example.com',
]);
// Multipart (file uploads)
Http::attach('photo', file_get_contents($photo), 'photo.jpg')
->post($url, ['name' => 'John']);
Response methods:
$response = Http::get($url);
$response->body(); // Raw body
$response->json(); // Decode JSON
$response->json('data.users'); // Get nested value
$response->status(); // HTTP status code
$response->successful(); // 200-299
$response->failed(); // 400+
$response->serverError(); // 500+
$response->clientError(); // 400-499
$response->header('Content-Type');
$response->headers(); // All headers
Error handling:
$response = Http::get($url);
if ($response->failed()) {
if ($response->clientError()) {
// 4xx error
logger()->warning('Client error', [
'status' => $response->status(),
'body' => $response->body(),
]);
}
if ($response->serverError()) {
// 5xx error
throw new \Exception('API server error');
}
}
// Or throw on error
$response = Http::get($url)->throw();
// Custom exception handler
$response = Http::get($url)->throw(function ($response, $e) {
// Custom handling
});
Retries:
// Retry 3 times with 100ms delay
$response = Http::retry(3, 100)->get($url);
// Retry with custom logic
$response = Http::retry(3, 100, function ($exception) {
return $exception instanceof ConnectionException;
})->get($url);
Timeout:
// 30 second timeout
$response = Http::timeout(30)->get($url);
// Connection timeout
$response = Http::connectTimeout(10)->get($url);
Testing HTTP requests:
use Illuminate\Support\Facades\Http;
public function test_user_profile_is_fetched()
{
Http::fake([
'api.example.com/users/*' => Http::response([
'name' => 'John Doe',
'email' => 'john@example.com',
], 200),
]);
$response = $this->get('/profile');
$response->assertSee('John Doe');
}
// Fake all requests
Http::fake();
// Fake with sequence
Http::fake([
'api.example.com/*' => Http::sequence()
->push(['status' => 'pending'], 200)
->push(['status' => 'completed'], 200)
->pushStatus(404),
]);
Fluent Strings
New Illuminate\Support\Stringable:
use Illuminate\Support\Str;
$string = Str::of(' laravel framework ')
->trim()
->title()
->replace('Framework', 'PHP Framework')
->slug();
echo $string; // "laravel-php-framework"
Chaining string operations:
$result = Str::of('john@example.com')
->before('@') // "john"
->ucfirst() // "John"
->append(' Doe') // "John Doe"
->slug(); // "john-doe"
Common methods:
Str::of('Hello World')
->upper(); // "HELLO WORLD"
->lower(); // "hello world"
->title(); // "Hello World"
->ucfirst(); // "Hello world"
Str::of('Laravel Framework')
->contains('Laravel'); // true
->startsWith('Laravel'); // true
->endsWith('Framework'); // true
Str::of('user@example.com')
->before('@'); // "user"
->after('@'); // "example.com"
->between('[', ']'); // Extract between chars
Str::of('Hello World')
->limit(8); // "Hello..."
->limit(8, '>>'); // "Hello>>"
Str::of('laravel-framework')
->camel(); // "laravelFramework"
->studly(); // "LaravelFramework"
->snake(); // "laravel_framework"
->kebab(); // "laravel-framework"
->slug(); // "laravel-framework"
Str::of('The quick brown fox')
->words(2); // "The quick..."
->words(3, '>>'); // "The quick brown>>"
Conditional operations:
$string = Str::of('Laravel')
->when(true, function ($string) {
return $string->append(' Framework');
})
->when(false, function ($string) {
return $string->append(' PHP'); // Skipped
});
// "Laravel Framework"
Testing strings:
Str::of('user@example.com')
->isEmail(); // true
Str::of('https://laravel.com')
->isUrl(); // true
Str::of('12345')
->isNumeric(); // true
Route Caching Improvements
Faster route compilation:
# Cache routes
php artisan route:cache
# Clear route cache
php artisan route:clear
Laravel 7 improvements:
- 2x faster route matching
- Reduced memory usage
- Better closure serialization
Custom Eloquent Casts
Define custom casts:
// app/Casts/Json.php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Json implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return json_decode($value, true);
}
public function set($model, $key, $value, $attributes)
{
return json_encode($value);
}
}
Use custom cast:
use App\Casts\Json;
class User extends Model
{
protected $casts = [
'options' => Json::class,
'preferences' => Json::class,
];
}
// Usage
$user->options = ['theme' => 'dark', 'language' => 'en'];
$user->save();
Cast with parameters:
namespace App\Casts;
class Encrypted implements CastsAttributes
{
protected $key;
public function __construct($key = null)
{
$this->key = $key;
}
public function get($model, $key, $value, $attributes)
{
return decrypt($value);
}
public function set($model, $key, $value, $attributes)
{
return encrypt($value);
}
}
// Use with parameter
protected $casts = [
'secret' => Encrypted::class . ':custom-key',
];
Blade Component Improvements
Inline component classes:
php artisan make:component Alert --inline
// app/View/Components/Alert.php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
public $type;
public $message;
public function __construct($type = 'info', $message)
{
$this->type = $type;
$this->message = $message;
}
public function render()
{
return <<<'blade'
<div class="alert alert-{{ $type }}">
{{ $message }}
</div>
blade;
}
}
Stub Customization
Publish stubs:
php artisan stub:publish
Customize in stubs/ directory:
// stubs/model.stub
<?php
namespace {{ namespace }};
use Illuminate\Database\Eloquent\Model;
class {{ class }} extends Model
{
protected $guarded = []; // Your custom default
}
Multiple Mail Drivers
Send via different drivers:
Mail::mailer('postmark')
->to($user)
->send(new OrderShipped($order));
// Config
'mailers' => [
'smtp' => [...],
'postmark' => [...],
'ses' => [...],
],
Conclusion
Laravel 7 enhances developer productivity with HTTP client, fluent strings, and custom casts. Route caching improvements boost performance. These features reduce boilerplate and improve code clarity.
Building Laravel applications? Contact ZIRA Software for expert development services.