Skip to content

Instantly share code, notes, and snippets.

@FerrielMelarpis
Last active December 17, 2018 06:30
Show Gist options
  • Save FerrielMelarpis/f65b9d1cf651cd022f337964864e6e88 to your computer and use it in GitHub Desktop.
Save FerrielMelarpis/f65b9d1cf651cd022f337964864e6e88 to your computer and use it in GitHub Desktop.
Component Design PHP
<?php
interface Displayable {
public function display();
}
class ArticleCardProps {
protected $thumbnailComponent;
protected $detailsComponent;
protected $thumbnailOverlayComponent = null;
public function __construct( Displayable $thumbnailComponent, Displayable $detailsComponent ) {
$this->thumbnailComponent = $thumbnailComponent;
$this->detailsComponent = $detailsComponent;
}
public function getThumbnailComponent() : Displayable {
return $this->thumbnailComponent;
}
public function setThumbnailComponent( Displayable $thumbnailComponent ) : void {
$this->thumbnailComponent = $thumbnailComponent;
}
public function getDetailsComponent() : Displayable {
return $this->detailsComponent;
}
public function setDetailsComponent( Displayable $detailsComponent ) : void {
$this->detailsComponent = $detailsComponent;
}
/**
* @return Displayable | null
*/
public function getThumbnailOverlayComponent() {
return $this->thumbnailOverlayComponent;
}
public function setThumbnailOverlayComponent( Displayable $thumbnailOverlayComponent ) {
$this->thumbnailOverlayComponent = $thumbnailOverlayComponent;
return $this;
}
}
class ArticleCard implements Displayable {
protected $props;
public function __construct( ArticleCardProps $props ) {
$this->props = $props;
}
public function display() {
$thumbnailComponent = $this->props->getThumbnailComponent();
$detailsComponent = $this->props->getDetailsComponent();
$thumbnailOverlayComponent = $this->props->getThumbnailOverlayComponent();
?>
<div class="articleCard">
<?php
$thumbnailComponent->display();
$detailsComponent->display();
if( $thumbnailOverlayComponent ) {
$thumbnailOverlayComponent->display();
}
?>
</div>
<?php
}
}
class LearnArticleCardProps extends ArticleCardProps {
public function __construct( Displayable $thumbnailComponent, Displayable $detailsComponent, Displayable $thumbnailOverlayComponent ) {
( parent::__construct( $thumbnailComponent, $detailsComponent ) )
->setThumbnailOverlayComponent( $thumbnailOverlayComponent );
}
}
// Only extend when new display template is needed
class LearnArticleCard extends ArticleCard {
public function display() {
$thumbnailComponent = $this->props->getThumbnailComponent();
$detailsComponent = $this->props->getDetailsComponent();
$thumbnailOverlayComponent = $this->props->getThumbnailOverlayComponent();
?>
<div class="articleCard">
<?php
// e.g. thumbnail is required in LearnArticle and should be at top
// if( $thumbnailOverlayComponent ) {
$thumbnailOverlayComponent->display();
// }
$thumbnailComponent->display();
$detailsComponent->display();
?>
</div>
<?php
}
}
class Thumbnail implements Displayable {
public function display() {
?>
<div class="thumbnail">THUMBNAIL</div>
<?php
}
}
class Details implements Displayable {
public function display() {
?>
<div class="details">DETAILS</div>
<?php
}
}
class ThumbnailOverlay implements Displayable {
public function display() {
?>
<div class="thumbnail__overlay">THUMBNAIL OVERLAY</div>
<?php
}
}
class ArticleGrid implements Displayable {
protected $columns;
protected $arrArticleCards;
public function __construct( int $columns = 3 ) {
$this->columns = $columns;
$this->arrArticleCards = [];
}
public function addArticleCard( ArticleCard $articleCard ) : self {
$this->arrArticleCards[] = $articleCard;
return $this;
}
public function display() {
?>
<div class="articleGrid--columns<?= $this->columns ?>">
<?php
foreach( $this->arrArticleCards as $articleCard ) {
$articleCard->display();
}
?>
</div>
<?php
}
}
( new ArticleGrid() )
->addArticleCard(
new ArticleCard(
( new ArticleCardProps(
new Thumbnail(), // pass as constructor parameters if required
new Details()
) )->setThumbnailOverlayComponent( new ThumbnailOverlay() ) // setter for optional components
)
)
// Using this approach, you can even nest card within cards, grids within cards, etc.
->addArticleCard(
new ArticleCard(
new ArticleCardProps(
new Thumbnail(),
( new ArticleGrid( 2 ) )
->addArticleCard(
new ArticleCard(
new ArticleCardProps(
new Thumbnail(),
new Details()
)
)
)
->addArticleCard(
new ArticleCard(
new ArticleCardProps(
new Thumbnail(),
new Details()
)
)
)
)
)
)
->addArticleCard(
new LearnArticleCard(
new LearnArticleCardProps(
new Thumbnail(),
new Details(),
new ThumbnailOverlay()
)
)
)
->display();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment