Robert 8 months ago
parent f40d45d0d3
commit 535c14668d
  1. 2
      .gitignore
  2. 26
      Books.php
  3. 12
      LazyObject.php
  4. 3
      NullCoalescingAssignment.php
  5. 5
      composer.json
  6. 6
      ex/Example2.php
  7. 9
      ex/MyClass.php
  8. 3
      huge.txt
  9. 1
      huge.txt
  10. 5
      phpstan.neon
  11. 0
      src/BcMath.php
  12. 32
      src/Books.php
  13. 0
      src/Coffee.php
  14. 0
      src/Dog.php
  15. 1
      src/LazyCollection.php
  16. 2
      src/LazyGhost.php
  17. 19
      src/LazyObject.php
  18. 8
      src/NullCoalescingAssignment.php
  19. 6
      src/ex/Example2.php
  20. 9
      src/ex/MyClass.php
  21. 11
      src/generics.php
  22. 3
      src/huge.txt
  23. 23
      src/libs/Collection.php
  24. 3
      src/libs/Dollars.php
  25. 35
      src/libs/LazyCollection.php
  26. 2
      src/libs/LazyObject.php
  27. 13
      src/libs/Scalar.php
  28. 0
      src/libs/autoload.php

2
.gitignore vendored

@ -0,0 +1,2 @@
composer.lock
vendor/

@ -1,26 +0,0 @@
<?php
interface HasAuthors {
public string $credits { get; }
public Author $mainAuthor { get; set; }
}
class Author {
public function __construct(public private(set) string $name) {}
}
class Book implements HasAuthors {
public string $credits {
get => "Authors: David Smith\n";
}
public Author $mainAuthor {
get => new Author("Smith");
set => throw new Exception("Main author cannot be changed.");
}
}
$book = new Book();
echo $book->credits;
$author = $book->mainAuthor;
echo $author->name;

@ -1,12 +0,0 @@
<?php
require "libs/autoload.php";
$lazyA = new libs\LazyObject(ex\MyClass::class);
$objectA = $lazyA->proxy(301);
// The object is initialized only when accessed
echo $objectA->someMethod() . "\n";
$lazyB = new libs\LazyObject(ex\Example2::class);
$objectB = $lazyB->proxy();
$objectB->hi();

@ -1,3 +0,0 @@
<?php
$name ??= "Bobby";
echo $name;

@ -0,0 +1,5 @@
{
"require": {
"phpstan/phpstan": "^2.1"
}
}

@ -1,6 +0,0 @@
<?php
namespace ex;
class Example2 {
public function hi() { echo "Hi!"; }
}

@ -1,9 +0,0 @@
<?php
namespace ex;
class MyClass {
public function __construct(public int $num) {}
public function someMethod() {
return $this->num;
}
}

@ -1,3 +0,0 @@
Hello,
you@
guys!

@ -0,0 +1 @@
src/huge.txt

@ -0,0 +1,5 @@
parameters:
level: max
paths:
- src

@ -0,0 +1,32 @@
<?php
interface HasAuthors {
public string $credits { get; }
public Author $mainAuthor { get; set; }
}
class Author {
public function __construct(public readonly string $name) {} // Using readonly instead of private(set)
}
class Book implements HasAuthors {
private Author $_mainAuthor; // Explicit backing field
public function __construct() {
$this->_mainAuthor = new Author("Smith"); // Initialize
}
public string $credits {
get => "Authors: David Smith\n";
}
public Author $mainAuthor {
get => $this->_mainAuthor; // Now reads the stored value
set => throw new \Exception("Main author cannot be changed.");
}
}
$book = new Book();
echo $book->credits; // "Authors: David Smith\n"
$author = $book->mainAuthor;
echo $author->name; // "Smith"

@ -19,6 +19,7 @@ $lazyCollection = libs\LazyCollection::make(function () {
ob_start();
$lazyCollection->each(function ($line) {
$line = new libs\Scalar()->intoString($line);
echo $line;
ob_flush();
flush();

@ -14,7 +14,7 @@ $reflector = new ReflectionClass(Example::class);
$object = $reflector->newLazyGhost($initializer);
var_dump($object);
var_dump($object instanceof Example);
// var_dump($object instanceof Example);
// Triggers initialization, and fetches the property after that
var_dump($object->data);

@ -0,0 +1,19 @@
<?php
require "libs/autoload.php";
$lazyA = new libs\LazyObject(ex\MyClass::class);
$runA = (function(int $i) use ($lazyA) {
$objectA = $lazyA->proxy($i);
// The object is initialized only when accessed
$data = $objectA->someMethod();
$data = new libs\Scalar()->intoString($data);
echo $data;
});
$lazyB = new libs\LazyObject(ex\Example2::class);
$objectB = $lazyB->proxy();
$objectB->hi();
$runA(800);

@ -0,0 +1,8 @@
<?php
require "libs/autoload.php";
$name ??= "Bobby";
$name = new libs\Scalar()->intoString($name);
echo $name;

@ -0,0 +1,6 @@
<?php
namespace ex;
class Example2 {
public function hi(): void { echo "Hi! \n"; }
}

@ -0,0 +1,9 @@
<?php
namespace ex;
class MyClass {
public function __construct(public int $num) { echo "Loaded \n"; }
public function someMethod(): int {
return $this->num;
}
}

@ -0,0 +1,11 @@
<?php
require "libs/autoload.php";
$names = new libs\Collection(['Mike','Lisa','Jenny']);
$names = $names->all();
foreach($names as $name) {
$name = new libs\Scalar()->intoString($name);
echo "Hello, " . $name . PHP_EOL;
}

@ -0,0 +1,3 @@
Hello,
you@
guys!

@ -0,0 +1,23 @@
<?php
namespace libs;
/**
* @template TItem
*/
final readonly class Collection {
/**
* @param array<int, TItem> $items
*/
public function __construct(
private array $items
) {
}
/**
* @return array<int, TItem>
*/
public function all(): array {
return $this->items;
}
}

@ -14,10 +14,11 @@ class Dollars {
return '$' . number_format($this->moneyAsFloat($money), 2, '.', ',');
}
public function intlUSD(Number $money): string {
public function intlUSD(Number $money): string|false {
if (class_exists('NumberFormatter')) {
$formatter = new \NumberFormatter('en_US', \NumberFormatter::CURRENCY);
return $formatter->formatCurrency($this->moneyAsFloat($money), 'USD');
}
return false;
}
}

@ -1,11 +1,19 @@
<?php
namespace libs;
/**
* @template TKey
* @template TValue
* @implements \IteratorAggregate<TKey, TValue>
*/
class LazyCollection implements \IteratorAggregate
{
/** @var \Closure|self|array<TKey, TValue>|null */
protected $source;
/**
* @param \Closure(): iterable<TKey, TValue>|self<TKey, TValue>|iterable<TKey, TValue>|null $source
*/
public function __construct($source = null)
{
if ($source instanceof \Closure || $source instanceof self) {
@ -17,11 +25,18 @@ class LazyCollection implements \IteratorAggregate
}
}
/**
* @return \Traversable<TKey, TValue>
*/
public function getIterator(): \Traversable
{
return $this->makeIterator($this->source);
}
/**
* @param \Closure(): iterable<TKey, TValue>|self<TKey, TValue>|array<TKey, TValue> $source
* @return \Traversable<TKey, TValue>
*/
protected function makeIterator($source)
{
if ($source instanceof \Closure) {
@ -35,12 +50,22 @@ class LazyCollection implements \IteratorAggregate
return $source;
}
/**
* @template TNewKey
* @template TNewValue
* @param \Closure(): iterable<TNewKey, TNewValue>|iterable<TNewKey, TNewValue>|null $source
* @return self<TNewKey, TNewValue>
*/
public static function make($source = null)
{
return new static($source instanceof \Closure ? $source() : $source);
}
public function each(callable $callback)
/**
* @param callable(TValue, TKey): bool $callback
* @return self<TKey, TValue>
*/
public function each(callable $callback): LazyCollection
{
foreach ($this->getIterator() as $key => $value) {
if ($callback($value, $key) === false) {
@ -51,7 +76,11 @@ class LazyCollection implements \IteratorAggregate
return $this;
}
protected function getArrayableItems($items)
/**
* @param mixed $items
* @return array<TKey, TValue>
*/
protected function getArrayableItems($items): array
{
if (is_array($items)) {
return $items;

@ -5,7 +5,7 @@ namespace libs;
class LazyObject {
public function __construct(public string $className) {}
public function proxy(mixed ...$args) {
public function proxy(mixed ...$args): Object {
$className = $this->className;
if (!class_exists($className, true)) {
throw new \InvalidArgumentException("Class {$className} does not exist");

@ -0,0 +1,13 @@
<?php
namespace libs;
class Scalar {
public function intoString(mixed $name): string {
if (is_scalar($name) || (is_object($name) && method_exists($name, '__toString'))) {
return (string)$name;
} else {
return ''; // or handle the error case
}
}
}
Loading…
Cancel
Save