commit
ae3973a5d0
@ -0,0 +1,23 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @todo sudo apt install php8.4-bcmath |
||||||
|
* @todo sudo apt install php8.4-intl |
||||||
|
*/ |
||||||
|
|
||||||
|
use BcMath\Number; |
||||||
|
|
||||||
|
require "libs/Dollars.php"; |
||||||
|
|
||||||
|
function init(): Number { |
||||||
|
$num1 = new Number('2200'); |
||||||
|
$num2 = new Number('700'); |
||||||
|
$money = ($num1 / $num2) + $num1 - $num2; |
||||||
|
//echo bcround($result, 2); |
||||||
|
return $money; |
||||||
|
} |
||||||
|
|
||||||
|
$d = new Dollars(); |
||||||
|
$c = init(); |
||||||
|
echo $d->formatAsUSD($c); |
||||||
|
echo "\n"; |
||||||
|
echo $d->intlUSD($c); |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
<?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; |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
<?php |
||||||
|
interface SizeInterface { |
||||||
|
public function getSize(): string; |
||||||
|
} |
||||||
|
|
||||||
|
enum Size: string implements SizeInterface { |
||||||
|
case Small = 'small'; |
||||||
|
case Grande = 'grande'; |
||||||
|
|
||||||
|
public function getSize(): string { |
||||||
|
return $this->value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
class Coffee { |
||||||
|
public string $flavor { |
||||||
|
get { |
||||||
|
return $this->flavor . ' Spice'; |
||||||
|
} |
||||||
|
set(string $value) { |
||||||
|
if (strlen($value) > 16) throw new InvalidArgumentException('Input is too long'); |
||||||
|
$this->flavor = $value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function serve(SizeInterface $size): void { |
||||||
|
echo "\r\nServing a {$size->getSize()} coffee.\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$coffee = new Coffee(); |
||||||
|
$coffee->flavor = 'Pumpkin'; |
||||||
|
echo $coffee->flavor; |
||||||
|
|
||||||
|
$coffee->serve(Size::Grande); |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
<?php |
||||||
|
class Dog { |
||||||
|
public function bark(): string { |
||||||
|
return "Woof!"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$dog = new Dog()->bark(); |
||||||
|
echo $dog; |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
require "libs/LazyCollection.php"; |
||||||
|
|
||||||
|
$lazyCollection = LazyCollection::make(function () { |
||||||
|
try { |
||||||
|
$handle = fopen('huge.txt', 'r'); |
||||||
|
if (!$handle) throw new Exception("Could not open file"); |
||||||
|
|
||||||
|
while (($line = fgets($handle)) !== false) { |
||||||
|
yield $line; |
||||||
|
} |
||||||
|
} finally { |
||||||
|
if (isset($handle) && is_resource($handle)) { |
||||||
|
fclose($handle); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
ob_start(); |
||||||
|
$lazyCollection->each(function ($line) { |
||||||
|
echo $line; |
||||||
|
ob_flush(); |
||||||
|
flush(); |
||||||
|
}); |
||||||
|
ob_end_flush(); |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
<?php |
||||||
|
class Example { |
||||||
|
public function __construct(public int $data) { |
||||||
|
echo __METHOD__, "\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$initializer = static function (Example $ghost): void { |
||||||
|
// Initialize |
||||||
|
$ghost->__construct(1); |
||||||
|
}; |
||||||
|
|
||||||
|
$reflector = new ReflectionClass(Example::class); |
||||||
|
$object = $reflector->newLazyGhost($initializer); |
||||||
|
|
||||||
|
var_dump($object); |
||||||
|
var_dump($object instanceof Example); |
||||||
|
|
||||||
|
// Triggers initialization, and fetches the property after that |
||||||
|
var_dump($object->data); |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
require "libs/LazyObject.php"; |
||||||
|
|
||||||
|
class MyClass { |
||||||
|
public function __construct(public int $num) {} |
||||||
|
public function someMethod() { |
||||||
|
return $this->num; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Example2 { |
||||||
|
public function hi() { echo "Hi!"; } |
||||||
|
} |
||||||
|
|
||||||
|
$object = new LazyObject()->proxy(MyClass::class, 301); |
||||||
|
// The object is initialized only when accessed |
||||||
|
echo $object->someMethod() . "\n"; |
||||||
|
|
||||||
|
$objectB = new LazyObject()->proxy(Example2::class); |
||||||
|
$objectB->hi(); |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
<?php |
||||||
|
$name ??= "Bobby"; |
||||||
|
echo $name; |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
<?php |
||||||
|
use BcMath\Number; |
||||||
|
|
||||||
|
class Dollars { |
||||||
|
private function moneyAsFloat(Number $money): float { |
||||||
|
// Remove any existing currency symbols and thousands separators |
||||||
|
$t = preg_replace('/[^\d.-]/', '', $money); |
||||||
|
return (float)$t; |
||||||
|
} |
||||||
|
|
||||||
|
public function formatAsUSD(Number $money): string { |
||||||
|
return '$' . number_format($this->moneyAsFloat($money), 2, '.', ','); |
||||||
|
} |
||||||
|
|
||||||
|
public function intlUSD(Number $money): string { |
||||||
|
if (class_exists('NumberFormatter')) { |
||||||
|
$formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY); |
||||||
|
return $formatter->formatCurrency($this->moneyAsFloat($money), 'USD'); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,63 @@ |
|||||||
|
<?php |
||||||
|
class LazyCollection implements IteratorAggregate |
||||||
|
{ |
||||||
|
protected $source; |
||||||
|
|
||||||
|
public function __construct($source = null) |
||||||
|
{ |
||||||
|
if ($source instanceof Closure || $source instanceof self) { |
||||||
|
$this->source = $source; |
||||||
|
} elseif (is_null($source)) { |
||||||
|
$this->source = static::empty(); |
||||||
|
} else { |
||||||
|
$this->source = $this->getArrayableItems($source); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function getIterator(): Traversable |
||||||
|
{ |
||||||
|
return $this->makeIterator($this->source); |
||||||
|
} |
||||||
|
|
||||||
|
protected function makeIterator($source) |
||||||
|
{ |
||||||
|
if ($source instanceof Closure) { |
||||||
|
$source = $source(); |
||||||
|
} |
||||||
|
|
||||||
|
if (is_array($source)) { |
||||||
|
return new ArrayIterator($source); |
||||||
|
} |
||||||
|
|
||||||
|
return $source; |
||||||
|
} |
||||||
|
|
||||||
|
public static function make($source = null) |
||||||
|
{ |
||||||
|
return new static($source instanceof Closure ? $source() : $source); |
||||||
|
} |
||||||
|
|
||||||
|
public function each(callable $callback) |
||||||
|
{ |
||||||
|
foreach ($this->getIterator() as $key => $value) { |
||||||
|
if ($callback($value, $key) === false) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $this; |
||||||
|
} |
||||||
|
|
||||||
|
protected function getArrayableItems($items) |
||||||
|
{ |
||||||
|
if (is_array($items)) { |
||||||
|
return $items; |
||||||
|
} elseif ($items instanceof Traversable) { |
||||||
|
return iterator_to_array($items); |
||||||
|
} elseif (is_object($items) && method_exists($items, 'toArray')) { |
||||||
|
return $items->toArray(); |
||||||
|
} |
||||||
|
|
||||||
|
return (array) $items; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
<?php |
||||||
|
class LazyObject { |
||||||
|
public function proxy(string $className, mixed $c = null) { |
||||||
|
if (!class_exists($className, true)) { |
||||||
|
throw new InvalidArgumentException("Class {$className} does not exist"); |
||||||
|
} |
||||||
|
$reflector = new ReflectionClass($className); |
||||||
|
if (!$reflector->isInstantiable()) { |
||||||
|
throw new InvalidArgumentException("Class {$className} cannot be instantiated"); |
||||||
|
} |
||||||
|
$constructor = $reflector->getConstructor(); |
||||||
|
|
||||||
|
// If the class has a constructor with required parameters |
||||||
|
if ($constructor && $constructor->getNumberOfRequiredParameters() > 0) { |
||||||
|
$initializer = static function (mixed $i) use ($className) { |
||||||
|
return new $className($i); |
||||||
|
}; |
||||||
|
return $reflector->newLazyProxy(fn() => $initializer($c)); |
||||||
|
} else { |
||||||
|
$initializer = static function () use ($className) { |
||||||
|
return new $className(); |
||||||
|
}; |
||||||
|
return $reflector->newLazyProxy($initializer); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue