Last active
December 17, 2018 06:30
-
-
Save FerrielMelarpis/f65b9d1cf651cd022f337964864e6e88 to your computer and use it in GitHub Desktop.
Component Design PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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