Was ist die Fluent-Klasse?
Fluent ist eine universelle Utility-Klasse, mit der Sie Arrays wie Objekte handhaben. Sie liegt unter Illuminate\Support\Fluent, existiert seit den ersten Laravel-Versionen — wird aber in der offiziellen Doku kaum erwähnt.
Intern verwaltet sie das Array in einer Property und ermöglicht über die Magic Methods __get, __set und __call einen Property-ähnlichen Zugriff.
In Laravel 11 kam der Helper fluent() hinzu, und die Klasse wurde erweitert — jetzt ist ein guter Zeitpunkt, sie einzusetzen.
Instanz erzeugen
Konstruktor
use Illuminate\Support\ Fluent ;
// Initialisierung per Array
$user = new Fluent ([ 'name' => 'Laravel' , 'type' => 'Framework' ]);
echo $user -> name ; // 'Laravel'
echo $user -> type ; // 'Framework'
Factory make()
use Illuminate\Support\ Fluent ;
$config = Fluent :: make ([
'host' => 'localhost' ,
'port' => 3306 ,
'database' => 'laravel'
]);
echo $config -> host ; // 'localhost'
Helper fluent()
Ab Laravel 11 gibt es den Helper fluent(), äquivalent zu Fluent::make().
$request = fluent ([
'method' => 'POST' ,
'path' => '/api/users' ,
'status' => 201
]);
echo $request -> method ; // 'POST'
Property-Zugriff
Dynamisches Lesen und Schreiben
$fluent = new Fluent ();
// Schreiben
$fluent -> name = 'Laravel' ;
$fluent -> version = 13 ;
// Lesen
echo $fluent -> name ; // 'Laravel'
echo $fluent -> version ; // 13
Method-Chain
Über die Magic Method __call werden nicht existierende Methodenaufrufe in Property-Zuweisungen umgewandelt. Die Methoden geben $this zurück und lassen sich verketten.
$config = new Fluent ();
$config
-> host ( 'localhost' )
-> port ( 3306 )
-> database ( 'laravel' )
-> username ( 'root' )
-> password ( 'secret' );
echo $config -> host ; // 'localhost'
echo $config -> password ; // 'secret'
So können Sie statt eines Arrays eine Fluent API zum Setzen der Werte verwenden.
Wichtige Methoden
get() — Zugriff per Dot-Notation
$user = new Fluent ([
'profile' => [
'email' => '[email protected] ' ,
'phone' => '090-xxxx-xxxx'
]
]);
// Verschachtelte Werte per Dot-Notation
$email = $user -> get ( 'profile.email' ); // '[email protected] '
$phone = $user -> get ( 'profile.phone' ); // '090-xxxx-xxxx'
// Standardwert möglich
$fax = $user -> get ( 'profile.fax' , 'N/A' ); // 'N/A'
set() — Setzen per Dot-Notation
$fluent = new Fluent ();
$fluent -> set ( 'user.name' , 'Laravel' );
$fluent -> set ( 'user.email' , '[email protected] ' );
print_r ( $fluent -> toArray ());
// Array (
// [user] => Array (
// [name] => Laravel
// [email] => [email protected]
// )
// )
fill() — mehrere Properties auf einmal setzen
$fluent = new Fluent ([ 'initial' => 'value' ]);
$fluent -> fill ([
'name' => 'Laravel' ,
'version' => 13 ,
'license' => 'MIT'
]);
echo $fluent -> name ; // 'Laravel'
echo $fluent -> version ; // 13
all() — alle Properties als Array
$fluent = fluent ([
'name' => 'Laravel' ,
'version' => 13 ,
'license' => 'MIT'
]);
// Alle Properties
$all = $fluent -> all ();
// ['name' => 'Laravel', 'version' => 13, 'license' => 'MIT']
// Nur bestimmte Properties
$subset = $fluent -> all ([ 'name' , 'license' ]);
// ['name' => 'Laravel', 'license' => 'MIT']
scope() — verschachtelte Werte in neuen Fluent überführen
$config = fluent ([
'database' => [
'host' => 'localhost' ,
'port' => 3306 ,
'name' => 'laravel'
]
]);
$dbConfig = $config -> scope ( 'database' );
// $dbConfig ist eine neue Fluent-Instanz
echo $dbConfig -> host ; // 'localhost'
echo $dbConfig -> port ; // 3306
So handhaben Sie verschachtelte Arrays als eigene Fluent-Objekte.
value() — Standardwert dynamisch per Callback
$user = fluent ([ 'role' => 'admin' ]);
// Existiert der Key, wird der Wert geliefert
$role = $user -> value ( 'role' ); // 'admin'
// Existiert der Key nicht, kommt der Standardwert
$status = $user -> value ( 'status' , 'active' );
// 'active'
// Standardwert per Callback
$timestamp = $user -> value ( 'updated_at' , function () {
return now () -> toIso8601String ();
});
Array-Operationen
toArray() — in ein Array umwandeln
$fluent = fluent ([ 'name' => 'Laravel' , 'version' => 13 ]);
$array = $fluent -> toArray ();
// ['name' => 'Laravel', 'version' => 13]
print_r ( $array );
getAttributes() — direkter Zugriff auf interne Attribute
$fluent = fluent ([ 'a' => 1 , 'b' => 2 ]);
$attributes = $fluent -> getAttributes ();
// ['a' => 1, 'b' => 2]
ArrayAccess-Interface
Fluent implementiert ArrayAccess — Sie können damit array-artig arbeiten.
$config = new Fluent ();
// Wie ein Array setzen
$config [ 'host' ] = 'localhost' ;
$config [ 'port' ] = 3306 ;
// Wie ein Array lesen
echo $config [ 'host' ]; // 'localhost'
// Existenz prüfen
if ( isset ( $config [ 'port' ])) {
echo $config [ 'port' ];
}
// Löschen
unset ( $config [ 'port' ]);
IteratorAggregate-Interface
Fluent lässt sich per foreach iterieren.
$settings = fluent ([
'debug' => true ,
'cache' => 'redis' ,
'queue' => 'database'
]);
foreach ( $settings as $key => $value ) {
echo " $key : $value \n " ;
// debug: 1
// cache: redis
// queue: database
}
JSON-Verarbeitung
toJson() — als JSON-String
$response = fluent ([
'success' => true ,
'data' => [ 'id' => 1 , 'name' => 'User' ]
]);
$json = $response -> toJson ();
// {"success":true,"data":{"id":1,"name":"User"}}
// Für API-Responses
return $json ;
$data = fluent ([
'users' => [
[ 'id' => 1 , 'name' => 'Alice' ],
[ 'id' => 2 , 'name' => 'Bob' ]
]
]);
echo $data -> toPrettyJson ();
// {
// "users": [
// {
// "id": 1,
// "name": "Alice"
// },
// {
// "id": 2,
// "name": "Bob"
// }
// ]
// }
JsonSerializable-Interface
Fluent implementiert JsonSerializable, wodurch json_encode() direkt funktioniert.
$fluent = fluent ([ 'status' => 'ok' , 'code' => 200 ]);
$json = json_encode ( $fluent );
// {"status":"ok","code":200}
$data = json_decode ( $json , true );
// ['status' => 'ok', 'code' => 200]
Zustandsprüfung
isEmpty() / isNotEmpty()
$empty = new Fluent ();
$filled = fluent ([ 'value' => 1 ]);
$empty -> isEmpty (); // true
$empty -> isNotEmpty (); // false
$filled -> isEmpty (); // false
$filled -> isNotEmpty (); // true
Conditionable-Trait
Fluent nutzt den Trait Conditionable und unterstützt bedingte Verarbeitung.
$config = fluent ([ 'env' => 'production' ]);
$config
-> when ( $config -> env === 'production' , function ( $fluent ) {
$fluent -> debug = false ;
$fluent -> cache = 'redis' ;
})
-> when ( $config -> env === 'local' , function ( $fluent ) {
$fluent -> debug = true ;
$fluent -> cache = 'array' ;
});
echo $config -> debug ;
echo $config -> cache ;
Mit when() / unless() lassen sich Konfigurationen fluent bedingt schreiben.
Macroable-Trait
Fluent nutzt zudem Macroable, sodass Sie dynamisch Methoden ergänzen können.
use Illuminate\Support\ Fluent ;
// Im boot() des Providers definieren
Fluent :: macro ( 'isProduction' , function () {
/** @var Fluent $this */
return $this -> env === 'production' ;
});
Fluent :: macro ( 'isDevelopment' , function () {
/** @var Fluent $this */
return $this -> env === 'development' ;
});
// Nutzung
$config = fluent ([ 'env' => 'production' ]);
if ( $config -> isProduction ()) {
// Produktivpfad
}
Praktische Anwendungsfälle
API-Response-Builder
namespace App\Support ;
use Illuminate\Support\ Fluent ;
class ApiResponse
{
public static function success ( $data = null , string $message = 'Success' ) : string
{
return fluent ([
'success' => true ,
'message' => $message ,
'data' => $data ,
'timestamp' => now () -> toIso8601String ()
]) -> toJson ();
}
public static function error ( string $message , int $code = 400 ) : string
{
return fluent ([
'success' => false ,
'message' => $message ,
'code' => $code ,
'timestamp' => now () -> toIso8601String ()
]) -> toJson ();
}
}
// Verwendung im Controller
public function store ( Request $request )
{
$user = User :: create ( $request -> validated ());
return response () -> json (
json_decode ( ApiResponse :: success ([ 'id' => $user -> id ]))
);
}
Config-Builder
$dbConfig = fluent ()
-> host ( env ( 'DB_HOST' , 'localhost' ))
-> port ( env ( 'DB_PORT' , 3306 ))
-> database ( env ( 'DB_DATABASE' , 'laravel' ))
-> username ( env ( 'DB_USERNAME' , 'root' ))
-> password ( env ( 'DB_PASSWORD' , '' ))
-> charset ( 'utf8mb4' )
-> collation ( 'utf8mb4_unicode_ci' )
-> when ( env ( 'APP_ENV' ) === 'production' , function ( $config ) {
$config -> sslmode ( 'require' );
$config -> sslcert ( env ( 'DB_SSL_CERT' ));
});
// Werte prüfen und aktivieren
config ([ 'database.connections.mysql' => $dbConfig -> toArray ()]);
Request-Parameter normalisieren
namespace App\Services ;
use Illuminate\Support\ Fluent ;
class SearchFilter
{
public function apply ( array $params ) : Fluent
{
$filter = fluent ()
-> page ( $params [ 'page' ] ?? 1 )
-> perPage ( $params [ 'per_page' ] ?? 15 )
-> sort ( $params [ 'sort' ] ?? 'created_at' )
-> order ( $params [ 'order' ] ?? 'desc' )
-> when ( isset ( $params [ 'search' ]), function ( $f ) use ( $params ) {
$f -> search = $params [ 'search' ];
})
-> when ( isset ( $params [ 'status' ]), function ( $f ) use ( $params ) {
$f -> status = $params [ 'status' ];
});
// Paginierung berechnen
$filter -> offset = ( $filter -> page - 1 ) * $filter -> perPage ;
return $filter ;
}
}
// Verwendung
$filter = app ( SearchFilter :: class ) -> apply ( request () -> all ());
$users = User :: query ()
-> when ( $filter -> has ( 'search' ), fn ( $q ) => $q -> search ( $filter -> search ))
-> when ( $filter -> has ( 'status' ), fn ( $q ) => $q -> where ( 'status' , $filter -> status ))
-> orderBy ( $filter -> sort , $filter -> order )
-> offset ( $filter -> offset )
-> limit ( $filter -> perPage )
-> get ();
Kombination von Model und Fluent
namespace App\Models ;
use Illuminate\Database\Eloquent\ Model ;
use Illuminate\Support\ Fluent ;
class Post extends Model
{
protected $casts = [
'metadata' => 'json'
];
public function getMetadataAttribute ( $value ) : Fluent
{
return new Fluent ( $value ?? []);
}
public function setMetadataAttribute ( $value ) : void
{
if ( $value instanceof Fluent ) {
$this -> attributes [ 'metadata' ] = $value -> toJson ();
} else {
$this -> attributes [ 'metadata' ] = json_encode ( $value );
}
}
}
// Verwendung
$post = new Post ();
$post -> metadata = fluent ()
-> title ( 'SEO Title' )
-> description ( 'Meta Description' )
-> keywords ([ 'laravel' , 'fluent' , 'tutorial' ])
-> author ( 'Laravel Community' );
$post -> save ();
// Lesen
$post = Post :: first ();
echo $post -> metadata -> title ; // 'SEO Title'
echo $post -> metadata -> author ; // 'Laravel Community'
namespace App\Http\Requests ;
use Illuminate\Foundation\Http\ FormRequest ;
use Illuminate\Support\ Fluent ;
class CreateUserRequest extends FormRequest
{
public function rules () : array
{
return [
'name' => 'required|string' ,
'email' => 'required|email|unique:users' ,
'password' => 'required|min:8|confirmed' ,
'role' => 'in:user,admin' ,
'preferences' => 'json' ,
];
}
// Validierte Daten als Fluent
public function toFluent () : Fluent
{
$preferences = is_string ( $this -> preferences )
? json_decode ( $this -> preferences , true )
: $this -> preferences ;
return fluent ([
'name' => $this -> name ,
'email' => $this -> email ,
'password' => bcrypt ( $this -> password ),
'role' => $this -> role ?? 'user' ,
'preferences' => new Fluent ( $preferences ?? [])
]);
}
}
// Im Controller
public function store ( CreateUserRequest $request )
{
$data = $request -> toFluent ();
$user = User :: create ( $data -> all ());
return response () -> json ([ 'success' => true , 'user_id' => $user -> id ]);
}
Vergleich mit anderen Klassen
Fluent vs. Array
Fähigkeit Fluent Array Property-Zugriff $fluent->name$array['name']Method-Chain ✓ ✗ JSON-Umwandlung Methode toJson() Funktion json_encode() Dot-Notation ✓ get('user.name') ✗ manuell Zustandsprüfung isEmpty()Funktion empty() Dynamische Methoden Macroable ✗
Fluent vs. Model
Fähigkeit Fluent Model DB-Persistenz ✗ ✓ automatisch Speichereffizienz ✓ leicht ✗ schwer Beziehungen ✗ ✓ Casts ✗ ✓ Validierung ✗ ✓ Fluent API ✓ △ eingeschränkt
Details der internen Implementierung
class Fluent
{
protected $attributes = [];
// Magic: Zugriff auf nicht existente Property
public function __get ( $key )
{
return $this -> value ( $key );
}
// Magic: Setzen einer nicht existenten Property
public function __set ( $key , $value )
{
$this -> offsetSet ( $key , $value );
}
// Magic: Aufruf einer nicht existenten Methode
// Der Methodenname wird zum Property-Key
public function __call ( $method , $parameters )
{
$this -> attributes [ $method ] = count ( $parameters ) > 0
? $parameters [ 0 ]
: true ;
return $this ;
}
}
Wenn kein Macro registriert ist, setzt __call den Methodennamen als Schlüssel im Attribut-Array und liefert $this zurück. Genau das ermöglicht Method-Chains.
Fluent verwendet folgende Traits mit jeweils unterschiedlicher Funktion:
Conditionable — bedingte Verarbeitung mit when() / unless()
InteractsWithData — Datenoperationen wie data()
Macroable — dynamisches Ergänzen von Methoden
Nächste Schritte
Collection-Klasse Tiefgehende Betrachtung der Collection-Klasse für mehrere Elemente.
Conditionable-Trait Bedingte Verarbeitung fluent schreiben mit dem Conditionable-Trait.
Macroable-Trait Bestehende Klassen dynamisch um Methoden erweitern.
Zuletzt geändert am 13. Juli 2026