Skip to content
This repository was archived by the owner on Sep 5, 2023. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/php.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions prop-relations/Brand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

class Brand
{
public function __construct (
public readonly int $id,
public readonly string $name,
) {
}
}
10 changes: 10 additions & 0 deletions prop-relations/Category.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

class Category
{
public function __construct (
public readonly int $id,
public readonly string $name,
) {
}
}
63 changes: 63 additions & 0 deletions prop-relations/Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

/**
* Collection<T[]>
*/
class Collection implements Iterator
{
private int $position = 0;
private ?array $array;

public function __construct (
/** @var T[] */
?array $items = null,
) {
$this->array = $items;
}

public function rewind (): void
{
$this->isInitializedOrFail();
$this->position = 0;
}

public function current ()
{
$this->isInitializedOrFail();
return $this->array[$this->position];
}

public function key ()
{
$this->isInitializedOrFail();
return $this->position;
}

public function next (): void
{
$this->isInitializedOrFail();
++$this->position;
}

public function valid (): bool
{
$this->isInitializedOrFail();
return isset($this->array[$this->position]);
}

/**
* @return T[]
*/
public function getItems (): array
{
$this->isInitializedOrFail();
return $this->array;
}

protected function isInitializedOrFail (): void
{
if ($this->array === null) {
throw new CollectionNotInitializedException();
}
}
}
6 changes: 6 additions & 0 deletions prop-relations/CollectionNotInitializedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

class CollectionNotInitializedException extends Exception
{

}
19 changes: 19 additions & 0 deletions prop-relations/Product.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

class Product
{
public function __construct (
public readonly int $id,
public readonly string $name,
/** @var Collection<Category> */
public readonly Collection $categories,
// Option: add ID
public readonly ?int $brandId = null,
// Option: add Model
public readonly ?Brand $brand = null,
// Option: schrodinger cat
public readonly ?Relation $brand_ = null,
)
{
}
}
29 changes: 29 additions & 0 deletions prop-relations/Relation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* Relation<T>
*/
class Relation
{
public function __construct (
/** @var T */
protected readonly ?object $value = null,
) {
}

/**
* @return T
*/
public function getValue (): object
{
$this->isInitializedOrFail();
return $this->value;
}

protected function isInitializedOrFail (): void
{
if ($this->value === null) {
throw new CollectionNotInitializedException();
}
}
}
68 changes: 68 additions & 0 deletions prop-relations/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

$categoryA = new Category(1, 'category a');
$categoryB = new Category(2, 'category b');

// GetProductWithCategoriesQuery
$productWithCategories = new Product(
1,
'product a',
new Collection([$categoryA, $categoryB]),
);

// Works
$productCategories = $productWithCategories->categories->getItems();

// GetProductQuery
$productWithoutCategories = new Product(
1,
'product a',
new Collection(),
);

// Throw Exception
$productCategories = $productWithoutCategories->categories->getItems();

// -------------------------------------------------------

// how to differentiate if Brand was filled or is null

// Oriol suggestion
$productWithBrand = new Product(
id: 2,
name: 'product b',
categories: new Collection(),
brandId: 1,
brand: null, //new Brand(1, 'brand a'),
);

// Miguel Angel suggestion
$productWithoutBrand = new Product(
id: 2,
name: 'product b',
categories: new Collection(),
brand: null, //new Brand(1, 'brand a'),
);

// Àlex Suggestion
// GetProductWithBrandQuery
$productWithOptionalBrand = new Product(
id: 2,
name: 'product b',
categories: new Collection(),
brand_: new Relation(new Brand(1, 'brand a')),
);

// Works
$productBrand = $productWithOptionalBrand->brand_->getValue();

// GetProductQuery
$productWithoutOptionalBrand = new Product(
id: 2,
name: 'product b',
categories: new Collection(),
brand_: new Relation(),
);

// Throw Exception
$productBrand = $productWithoutOptionalBrand->brand_->getValue();