99
1010namespace Demo ;
1111
12- use Demo \Contracts \Renderable ;
13- use Demo \Concerns \HasTimestamps ;
14- use Demo \Enums \Status ;
12+ use Exception ;
13+ use Stringable ;
1514
1615// ─── Interfaces ─────────────────────────────────────────────────────────────
1716
18- interface Stringable
19- {
20- public function toString (): string ;
21- }
22-
2317/**
2418 * @method string render()
2519 * @property-read string $output
@@ -49,7 +43,7 @@ public function setCreatedAt(string $date): static
4943
5044 public function touch (): void
5145 {
52- $ this ->updatedAt = date (" Y-m-d H:i:s " );
46+ $ this ->updatedAt = date (' Y-m-d H:i:s ' );
5347 }
5448}
5549
@@ -60,24 +54,24 @@ trait HasSlug
6054{
6155 public function generateSlug (string $ value ): string
6256 {
63- return strtolower (str_replace (" " , " - " , $ value ));
57+ return strtolower (str_replace (' ' , ' - ' , $ value ));
6458 }
6559}
6660
6761// ─── Enums ──────────────────────────────────────────────────────────────────
6862
6963enum Status: string
7064{
71- case Active = " active " ;
72- case Inactive = " inactive " ;
73- case Pending = " pending " ;
65+ case Active = ' active ' ;
66+ case Inactive = ' inactive ' ;
67+ case Pending = ' pending ' ;
7468
7569 public function label (): string
7670 {
7771 return match ($ this ) {
78- self ::Active => " Active " ,
79- self ::Inactive => " Inactive " ,
80- self ::Pending => " Pending " ,
72+ self ::Active => ' Active ' ,
73+ self ::Inactive => ' Inactive ' ,
74+ self ::Pending => ' Pending ' ,
8175 };
8276 }
8377
@@ -106,15 +100,15 @@ abstract class Model
106100 protected int $ id ;
107101
108102 /** @var string */
109- protected string $ table = "" ;
103+ protected string $ table = '' ;
110104
111- public const string CONNECTION = " default " ;
105+ public const string CONNECTION = ' default ' ;
112106 protected const int PER_PAGE = 15 ;
113- private const string INTERNAL_KEY = " __model__ " ;
107+ private const string INTERNAL_KEY = ' __model__ ' ;
114108
115109 public function __construct (
116- protected string $ name = "" ,
117- public readonly string $ uuid = "" ,
110+ protected string $ name = '' ,
111+ public readonly string $ uuid = '' ,
118112 ) {
119113 $ this ->id = rand (1 , 99999 );
120114 }
@@ -146,9 +140,9 @@ public static function find(int $id): ?static
146140 /**
147141 * @return static
148142 */
149- public static function make (string $ name = "" ): static
143+ public static function make (string $ name = '' ): static
150144 {
151- return new static ($ name );
145+ return new static ($ name, '' );
152146 }
153147
154148 abstract public function toArray (): array ;
@@ -177,16 +171,16 @@ class User extends Model implements Renderable
177171 protected Status $ status ;
178172 private array $ roles = [];
179173
180- public static string $ defaultRole = " user " ;
174+ public static string $ defaultRole = ' user ' ;
181175 public static int $ count = 0 ;
182176
183- public const string TYPE_ADMIN = " admin " ;
184- public const string TYPE_USER = " user " ;
177+ public const string TYPE_ADMIN = ' admin ' ;
178+ public const string TYPE_USER = ' user ' ;
185179
186180 public function __construct (
187181 string $ name ,
188182 string $ email ,
189- private readonly string $ password = "" ,
183+ private readonly string $ password = '' ,
190184 public int $ age = 0 ,
191185 ) {
192186 parent ::__construct ($ name );
@@ -232,10 +226,10 @@ public function getProfile(): UserProfile
232226 public function toArray (): array
233227 {
234228 return [
235- " id " => $ this ->getId (),
236- " name " => $ this ->getName (),
237- " email " => $ this ->email ,
238- " status " => $ this ->status ->value ,
229+ ' id ' => $ this ->getId (),
230+ ' name ' => $ this ->getName (),
231+ ' email ' => $ this ->email ,
232+ ' status ' => $ this ->status ->value ,
239233 ];
240234 }
241235
@@ -246,7 +240,7 @@ public function toString(): string
246240
247241 public function format (string $ template ): string
248242 {
249- return str_replace (" {name} " , $ this ->getName (), $ template );
243+ return str_replace (' {name} ' , $ this ->getName (), $ template );
250244 }
251245
252246 public static function findByEmail (string $ email ): ?self
@@ -269,8 +263,8 @@ private function secretInternalMethod(): void
269263
270264class UserProfile
271265{
272- public string $ bio = "" ;
273- public string $ avatarUrl = "" ;
266+ public string $ bio = '' ;
267+ public string $ avatarUrl = '' ;
274268
275269 public function __construct (private User $ user ) {}
276270
@@ -287,7 +281,7 @@ public function setBio(string $bio): self
287281
288282 public function getDisplayName (): string
289283 {
290- return $ this ->user ->getName () . " ( " . $ this ->user ->getEmail () . " ) " ;
284+ return $ this ->user ->getName () . ' ( ' . $ this ->user ->getEmail () . ' ) ' ;
291285 }
292286}
293287
@@ -307,7 +301,7 @@ public function __construct(string $name, string $email)
307301 public function toArray (): array
308302 {
309303 $ base = parent ::toArray ();
310- $ base [" permissions " ] = $ this ->permissions ;
304+ $ base [' permissions ' ] = $ this ->permissions ;
311305 return $ base ;
312306 }
313307
@@ -361,7 +355,12 @@ public function make(?string $abstract = null): mixed
361355 if ($ abstract === null ) {
362356 return $ this ;
363357 }
364- return $ this ->bindings [$ abstract ] ?? null ;
358+ return $ this ->bindings [$ abstract ] ?? new Exception ();
359+ }
360+
361+ public function bind (string $ abstract , object $ obj ): void
362+ {
363+ $ this ->bindings [$ abstract ] = $ obj ;
365364 }
366365}
367366
@@ -393,23 +392,28 @@ function createUser(string $name, string $email): User
393392
394393function findOrFail (int $ id ): User |AdminUser
395394{
396- return new User ("test " , "test@example.com " );
395+ return new User ('test ' , 'test@example.com ' );
396+ }
397+
398+ function getUnknownValue ()
399+ {
400+ return new AdminUser ('' , '' );
397401}
398402
399403// ─── Usage Examples ─────────────────────────────────────────────────────────
400404
401405// Instance member completion via ->
402- $ user = new User (" Alice " , " alice@example.com " );
406+ $ user = new User (' Alice ' , ' alice@example.com ' );
403407$ user ->getEmail (); // Completion: methods on User
404408$ user ->email ; // Completion: properties on User
405409$ user ->getCreatedAt (); // Completion: methods from HasTimestamps trait
406- $ user ->generateSlug (" Test " ); // Completion: methods from HasSlug trait
410+ $ user ->generateSlug (' Test ' ); // Completion: methods from HasSlug trait
407411
408412// Static member completion via ::
409413User::$ defaultRole ; // Completion: static properties
410414User::TYPE_ADMIN ; // Completion: class constants
411- User::findByEmail (" a@b.c " ); // Completion: static methods
412- User::make (" Bob " ); // Completion: inherited static methods from Model
415+ User::findByEmail (' a@b.c ' ); // Completion: static methods
416+ User::make (' Bob ' ); // Completion: inherited static methods from Model
413417
414418// Enum case completion via ::
415419Status::Active; // Completion: enum cases
@@ -425,7 +429,7 @@ function findOrFail(int $id): User|AdminUser
425429// static::find(1) — resolves to the calling class
426430
427431// Method call chaining
428- $ user ->setName (" Bob " )->setStatus (Status::Active)->getEmail ();
432+ $ user ->setName (' Bob ' )->setStatus (Status::Active)->getEmail ();
429433
430434// Property chain resolution: $this->prop->method()
431435$ profile = $ user ->getProfile ();
@@ -435,30 +439,30 @@ function findOrFail(int $id): User|AdminUser
435439$ user ->getProfile ()->getDisplayName ();
436440
437441// Static method return type -> chaining
438- $ made = User::make (" Charlie " );
442+ $ made = User::make (' Charlie ' );
439443$ made ->getEmail (); // Resolves static return type
440444
441445// Function return type resolution
442- $ u = createUser (" Dana " , " dana@example.com " );
446+ $ u = createUser (' Dana ' , ' dana@example.com ' );
443447$ u ->getName (); // Resolves createUser() return type -> User
444448
445449// Constructor promoted properties (readonly)
446450$ user ->age ; // public promoted property
447451$ user ->uuid ; // readonly promoted property from Model
448452
449453// new expression -> chaining (PHP 8.4+ / parenthesized)
450- new User (" Eve " , " eve@example.com " )->getEmail ();
454+ new User (' Eve ' , ' eve@example.com ' )->getEmail ();
451455
452456// Variable type inference from assignments
453- $ admin = new AdminUser (" Frank " , " frank@example.com " );
454- $ admin ->grantPermission (" delete " );
457+ $ admin = new AdminUser (' Frank ' , ' frank@example.com ' );
458+ $ admin ->grantPermission (' delete ' );
455459$ admin ->getCreatedAt (); // Inherited via trait from User
456460
457461// Union types — ambiguous variable across conditional branches
458462if (rand (0 , 1 )) {
459- $ ambiguous = new User (" X " , " x@example.com " );
463+ $ ambiguous = new User (' X ' , ' x@example.com ' );
460464} else {
461- $ ambiguous = new AdminUser (" Y " , " y@example.com " );
465+ $ ambiguous = new AdminUser (' Y ' , ' y@example.com ' );
462466}
463467$ ambiguous ->getName (); // Both User and AdminUser have getName()
464468
@@ -491,8 +495,8 @@ function findOrFail(int $id): User|AdminUser
491495
492496// Inline @var docblock for variable type hints
493497/** @var AdminUser $inlineTyped */
494- $ inlineTyped = someFactory ( );
495- $ inlineTyped ->grantPermission (" write " );
498+ $ inlineTyped = getUnknownValue (AdminUser::class );
499+ $ inlineTyped ->grantPermission (' write ' );
496500
497501// Null-safe operator chaining
498502$ maybeUser = User::find (1 );
@@ -509,12 +513,13 @@ function findOrFail(int $id): User|AdminUser
509513// - Relative in same namespace: User (resolved from current namespace Demo)
510514
511515// Response with union type properties
512- $ response = new Response (200 , [" data " => " ok " ]);
516+ $ response = new Response (200 , [' data ' => ' ok ' ]);
513517$ response ->getStatusCode (); // Returns string|int
514518$ response ->getBody (); // Returns string|array|null
515519
516520// Container with conditional return type
517521$ container = new Container ();
522+ $ container ->bind (User::class, new User ('' , '' ));
518523$ resolvedUser = $ container ->make (User::class);
519524$ resolvedUser ->getEmail (); // Conditional return resolves User from class-string
520525
0 commit comments