Objects
Obj
Looks at an object and fills its public properties.
| Method | What it does |
|---|---|
Obj::fill($instance, $data) |
Sets the public properties from an array. Gives the object back. |
Obj::getPublicProperties($instance) |
The public properties, as ReflectionProperty by name. |
Obj::getPublicValues($instance) |
The values of the public properties. |
Obj::hasProperty($instance, $property, $public = true) |
Whether the property exists (only public ones by default). |
Obj::getClassName($instance) |
The name of the class. |
Obj::getReflection($instance) |
A ReflectionClass of the object. |
use Derafu\Support\Obj;
class Q
{
public $x = 1;
protected $y = 2;
private $z = 3;
public function __construct(public int $w = 4) {}
}
$q = new Q();
Obj::fill($q, ['x' => 10]);
Obj::getPublicValues($q); // ['x' => 10, 'w' => 4]
array_keys(Obj::getPublicProperties($q)); // ['x', 'w']
Obj::hasProperty($q, 'y'); // false: it is not public.
Obj::hasProperty($q, 'y', false); // true
Obj::getClassName($q); // "Q"
Factory and Hydrator
Hydrator fills an object from an array using its setters, and Factory creates the object and hydrates it.
use Derafu\Support\Factory;
use Derafu\Support\Hydrator;
$object = Factory::create(['a' => 1]); // A stdClass.
$object = Factory::create($data, MyClass::class); // A MyClass.
$objects = Factory::createMany($rows, MyClass::class); // A list of MyClass.
$object = Factory::createAndEnsureType($data, MyClass::class, MyInterface::class);
$object = Hydrator::hydrate($instance, $data); // An object that already exists.
$object = Hydrator::createAndHydrate(MyClass::class, $data);
For each attribute of the array, Hydrator tries, in this order:
- The method
setXxx()(Xxxis the attribute in StudlyCase:first_nameissetFirstName()). - The method
setXxxAttribute(). - The method
setAttribute($name, $value), if the class has it (it receives every attribute that the previous two did not take). - The property with that name. It is set directly, also if it is not public.
An attribute that none of them can take is a LogicException that says which attribute and which class. Factory::createAndEnsureType() also throws a LogicException if the object that it created is not of the expected type.
Because of the last step, do not hydrate an object with data that comes from a user as it is: the attributes are the names of its properties. Pick the fields first.
Serialization and JSON
use Derafu\Support\Serialization;
use Derafu\Support\JsonSerializer;
Serialization::isSerializable([1, 'a']); // true
Serialization::isSerializable('text'); // true
Serialization::isSerializable(new stdClass()); // true
Serialization::isSerializable(fn () => 1); // false: PHP does not serialize closures.
Serialization::isSerializable([fopen('php://memory', 'r')]); // false: a resource inside.
Serialization::isSerialized(serialize([1])); // true
Serialization::isSerialized('abc'); // false
Serialization::isSerialized('b:0;'); // true: it is a serialized `false`.
isSerializable() answers what PHP can do. A scalar and null can be serialized. An array or an object can be, if PHP can serialize it and what it has inside can be too. They are not serializable:
- Resources, open or closed: PHP would write them as
0. - What PHP does not serialize: closures, generators, anonymous classes, reflections, and the objects whose class forbids it or whose
__serialize()or__sleep()fails (or warns). - An array or an object that has any of them inside, in a property of any visibility, at any depth. For an object with
__serialize(), what is searched is what that method gives, which is what PHP serializes.
Circular references are fine, PHP serializes them. isSerialized() says whether a text is the result of serialize() (it checks its format, it does not unserialize it).
JsonSerializer::serialize($value, $flags = null, $depth = 512) makes the JSON of a value that json_encode() would not handle well, going through arrays and objects recursively. An object becomes:
- what its
jsonSerialize()gives, if it is aJsonSerializable; - what its
toArray()gives, if it has that method; - a text in ISO 8601 if it is a
DateTimeInterface; - its text if it is a
Stringable; - an array of its public properties otherwise.
JsonSerializer::serialize([
'date' => new DateTimeImmutable('2024-01-02 03:04:05'),
'text' => $stringable,
'data' => $objectWithToArray,
]);
// {"date": "2024-01-02T03:04:05-03:00", "text": "...", "data": {...}}
The flags by default make a readable output (pretty printed, without escaping unicode or slashes). A value that can not be encoded is a JsonException.
Debug
use Derafu\Support\Debug;
$info = Debug::inspect($var, 'myVar');
Debug::print($var, 'myVar');
inspect() gives an array with the label, the type (the class for an object), the length (of an array or a text), the file and line where it was called, the caller, the timestamp, the memory_usage and the value as text (print_r(), or JSON for null and booleans). The caller is the function or method that called it (inAFunction(), Class::method()), or {main} if it was called from the code that is outside of any function, as PHP says it in its traces. print() shows that array inside a <pre> (so it is for pages, not for the console), with the file, the line and the caller of the call to print().