Hello OOP specialisten vooral :)

Ik ben na lange tijd maar weer is achter de PHP classes oefeningen gedoken.

Voor een nieuwe oefening dacht ik een navigatie menu te maken d.m.v. een Navigation class. Waar ik nu precies naar benieuwd ben, wat moet er zoal in en waar moet ik rekening mee houden. zijn er dingen die minimaal in een navigaton class moeten komen? ( denk hierbij aan de interface class ) etc...

alle tips zijn welkom :)

[offtopic]
ik post de vraag ook op andere fora dus wees niet verrast als je het tegenkomt, uiteraard zal ik het uiteindelijke resultaat overal neerzetten.
[/offtopic]
Reshad F op 04/11/2012 19:53:57

hmm @Raoul als ik deze twee nu wil scheiden. moet/kan ik dan gewoon de item methods in een andere class zetten en de class aanroepen in mijn navigation constructor?

en vervolgens in mijn display(); methode de methodes ervan ook aanroepen?

of is hier een andere manier voor..


Opzetje:

<?php

class Navigation
{
	private $_items = null;

	public function addChild(Navigation_Item $item)
	{
		$this->_items[] = $item;
	}

	public function render()
	{
		$html = '<ul>';

		foreach($this->_items as $item)
		{
			$html .= $item->render();
		}

		$html .= '</ul>';

		return $html;
	}
}

class Navigation_Item
{
	private $_link;
	private $_text;

	public function setLink($link)
	{
		$this->_link = $link;
	}

	public function setText($text)
	{
		$this->_text = $text;
	}

	public function getLink()
	{
		return $this->_link;
	}

	public function getText()
	{
		return $this->_text;
	}

	public function render()
	{
		return '<li><a href="' . $this->getLink() . '">' . $this->getText() . '</a>';
	}
}
?>
zoiets?

<?php
class NavigationItem implements NavigationItemInterface {

public $menu = null;

public function __construct() {

}

public function setMenuItem($items) {

$this->menuItem = $items;
}

public function getMenuItem($menu) {
return $menu;
}

public function display() {

if(is_array($this->menuItem))
{
foreach($this->menuItem as $val)
{
$menu .= '<li><a class="' . $this->getClass() . '" href="index.php?page=' . $this->getMenuItem($val) . '.php">' . $this->getMenuItem($val) . '</a></li>';
}
}
else{
$menu .= '<li><a class="' . $this->getClass() . '" href="index.php?page=' . $this->getMenuItem($this->menuItem) . '.php">' . $this->getMenuItem($this->menuItem) . '</a></li>';

}

return $menu;
}

}
?>

en

<?php
class Navigation implements navigationInterface{

public $menu = null;
public $name = null;
public $klasse = null;
public $navItem = null;

public function __construct($name, $klasse) {

$this->name = $name;
$this->klasse = $klasse;

}

public function addChild(Navigation_Item $item)
{
$this->navItem[] = $item;
}

public function getName() {
return $this->name;
}

public function getClass() {
return $this->klasse;
}


public function display() {

$menu = '<nav class="' . $this->getName() . '"><ul>';

$navItem->display();

$menu .= '</ul></nav>';

return $menu;

}
}
?>
De code zou niet kunnen: Waar haal je $navItem vandaan op regel 34 en wat denk je dat er in zou zitten als je hem goed zou schrijven?

Nogmaals: Loop je script eens rustig door en kijk of alle logica qua code wel klopt.
Helloo, ik heb mijn classes gesplitst. en het ziet er nu uit als volgt.

<?php
class NavigationItem implements NavigationItemInterface {

public $menu = null;
public $menuItem = null;

public function setMenuItem($items) {

$this->menuItem = $items;
}

public function getMenuItem() {
return $this->menuItem;
}

public function getClass() {

if(isset($_GET['page']) and $_GET['page'] == $this->getMenuItem() . '.php')

{
$class = 'current';
}
else
{
$class = '';
}

return $class;
}

public function display() {


return '<li><a class="' . $this->getClass() . '" href="index.php?page=' . $this->getMenuItem() . '.php">' . $this->getMenuItem() . '</a></li>';

}

}
?>

en dan de navigation class

<?php
class Navigation implements navigationInterface{

public $menu = null;
public $name = null;
public $items = null;

public function __construct($name) {

$this->name = $name;

}

public function addChild(NavigationItem $item)
{
$this->items[] = $item;
}

public function getName() {
return $this->name;
}

public function display() {

$menu = '<nav class="' . $this->getName() . '"><ul>';

foreach ($this->items as $item) {

$menu.= $item->display();

}

$menu .= '</ul></nav>';

return $menu;

}
}
?>

het gebruik ervan is als volgt:

<?php
$menu = new Navigation("navigation");
$menu_items = array("home", "about", "playground");
foreach($menu_items as $item)
{
$items = new NavigationItem();
$items->setMenuItem($item);
$menu->addChild($items);
}
echo $menu->display();

?>

Volgens mij kan het nog simpeler aanroepen ( zoals het voorbeeldje van jullie ) maar dat heb ik niet kunnen realiseren tot nu.
Volgens mij kan het nog simpeler aanroepen ( zoals het voorbeeldje van jullie ) maar dat heb ik niet kunnen realiseren tot nu.

Gewoon een constructor maken waar je de waardes kan instellen.

Tevens heb je nog een verantwoordelijkheid die je nog niet hebt opgesplitst: De rederer

[size=xsmall]Toevoeging op 06/11/2012 11:11:07:[/size]

Volgens mij kan het nog simpeler aanroepen ( zoals het voorbeeldje van jullie ) maar dat heb ik niet kunnen realiseren tot nu.

Gewoon een constructor maken waar je de waardes kan instellen.

Tevens heb je nog een verantwoordelijkheid die je nog niet hebt opgesplitst: De rederer
hmm dus dan heb ik 3 classes?

- Navigatie class
- NavigatieItem class
- Render class

Maar kan je mij dan ook uitleggen waarom in dit geval de render gescheiden moet worden?
Omdat een verantwoordelijkheid is en je dat dus in een andere klasse moet stoppen. Je kan bijv. een ListRenderer hebben of een XmlRenderer
hmm en dan moet ik dus de render van zowel Navigatie als NavigatieItem in een class stoppen?
Ik zou 2 aparte render klasses maken en 1 hoofd rederer die je dan kunt aanroepen. Een UlRenderer en een LiRenderer en die samenvoegen in een ListRenderer die dan zoiets wordt:
<?php

class ListRenderer
{
// ...

public function render()
{
$builder = $this->getFormBuilder();

$items = array_map($builder->getItems(), function($item) {
$item = new LiRenderer($item);

return $item->render();
});

$list = new UlRenderer($items);

return $list->render();
}
}
?>

Maar nu ik dit schrijf denk ik dat dit iets teveel in klassen proppen wordt. Die Ul en Li Renderers zullen toch nooit iets anders worden, beter is daar gewoon 2 aparate methods van te maken in de ListRenderer klasse.

Reageren