Skip to main content

5, Zelf een view maken

DEZE EN VOLGENDE LESSEN WORDEN NOG AANGEPAST

Tot nu hebben we gebruik gemaakt van de GridView om data te laten zien (localhost:8080/country/index) - in deze les gaan we onze eigen view maken. Het maken van een eigen view kost meer tijd, maar je kunt meer zaken zelf aanpassen zoals de weergave (formattering) van getallen.

Menu - Controller - View

Om te beginnen maken we een nieuwe method in de controllers/CountryController class.

Deze controller noemen we actionOverzicht. Volgens de routing regels wordt de route wordt dus /country/overzicht.

Opdracht 1

Maar een menu item overzicht onder country dat naar /country/overzicht gaat.

image-1614620329168.png

Probeer het menu uit. Wat zie je en kun je verklaren wat je ziet?

Juist.... je krijgt een foutmelding want de routering verwijst naar de method/function actionOverzicht in de controller CountryController en die bestaat niet!

We gaan dus een stukje code toevoegen aan onze CountryController.

use yii\data\Pagination;

..
..
  
public function actionOverzicht()
{
    // dit is de query, dit is te vergelijken met select * from Country
    $countries=Country::find()->all();
  
	// de view wordt aangeroepen en het object $countries en $pagination wordt meegegeven.
    return $this->render('overzicht', [
        'countries' => $countries,
    ]);
}
Opdracht 2

Maak de function actionOverzicht in de CountryController zoals hierboven is aangegeven.

 

Test opnieuw wat er gebeurt als je het menu overzicht selecteert

image-1614623472969.png What? Weer een fout? Waarom nu?

Juist het menu gaat naar de actionOverzicht en de actionOverzicht voert een query uit en roept de view overzicht op. En die view bestaat (nog) niet.

We gaan dus in de folder views/country een nieuwe file overzicht.php aanmaken en plaatsen daar de volgende code in.

<?php
    foreach ($countries as $country) {
        echo $country->Name;
        echo " - ";
        echo $country->Code;
        echo " - ";
        echo number_format($country->Population, 0, ',', ' ');
        echo "<br>";
    }
?>
Opdracht 3

Maak de view overzicht zoals hierboven is aangegeven.

 

Het overzicht is bijna niet geformatteerd.

image-1614627165703.png

Weet je nog hoe een HTML table er uit ziet?

<table>

	<tr>
    	<td> .. </td>
        <td> .. </td>
        <td> .. </td>
     </tr>
     
     <tr>
    	<td> .. </td>
        <td> .. </td>
        <td> .. </td>
     </tr>
     
</table>

Hierboven staat een skelet van een table met twee rijen en drie kolommen.

Opdracht 4

Verander de /view/country/overzicht nu zo dat het netjes in een table wordt gezet. De output komt er als volgt uit te zien:

 

image-1614627534845.png

De kolommen staan nu dus netjes onder elkaar.

 

Je hebt nu zelf een view opgebouwd zonder gebruik te maken van de Gridview widget. Het kost meer tijd en moeite om een overzicht te maken maar je hebt wel veel meer controle over hoe jouw overzicht er uit komt te zien.

Sorteren en selecteren

We gaan nu een paar functies bouwen die in de Gridview widget al ingebouwd zijn. Dit gaat om sorteren en selecteren.

Kijk nog eens naar de CountryController bij de actionOverzicht, daar staat:

$countries=Country::find()->all();

Dit statement zoekt gaat naar het object country, dit staat in het model en zoekt daar alle regels (rows) in op. Yii vertaald dit nar de query

SELECT * FROM country

Maar we kunnen nog veel meer, kijk maar eens naar het volgende uitgebreide voorbeeld:

 $countries = country::find()->where(['Continent' => 'Europe'])->orderBy(['Name' => SORT_ASC])->all();

Hier worden alle countries geslecteerd met Continent=Europe, gesorteerd op Name. Het sql statement zou er zo uit zien:

SELECT * FROM country WHERE Continent = 'Europe' ORDER BY Name ASC

Op deze manier kun je dus via de code in de controller een selectie maken en de sortering aanpassen.

Opdracht 5
    • Maar een nieuw menu item en noem dit Overzicht Europe.

    • Maak een nieuw actionOverzichtEurope en koppel deze aan het menu item.
      (let op de vertaling naar de routering; in de routering staat nooit een hoofdletter en woorden worden gescheiden door - , zie les over routing).

    • Laat in dit overzicht alle landen van Europa zien, en druk de volgende kolommen af:

Name en Surface Area

 

    • Zet de twee kolommen netjes onder elkaar

    • Formateer de Surface Aera netjes met spatie tussen de duizendtallen en lijn ze recht uit.

    • Maak een header die bold is.

    • Sorteer het overzicht op Surface Area vangrootste land naar kleinste.

      Het overzicht kot er dus zo uit te zien:

image-1614629726011.png

 

Lees het commentaar in deze controller, zodat je begrijpt wat de verschillende blokken code doen.

use yii\data\Pagination;

..
..
  
public function actionOverzicht()
{
    $this->view->title = 'Search Countries';

    // dit is de query, dit is te vergelijken met select * from Country
    $query=Country::find();
  
  	// hier worden bepaald hoeveel regels er op één pagina worden getoond en hoeveel regels er in totaal zijn
    $pagination = new Pagination([
        'defaultPageSize' => 5,
        'totalCount' => $query->count(),
    ]);

	// hier wordt de query uitgevoerd, er wordt gesorteerd en er wordt slecht één pagina gelijktijdig binnen gehaald.
    $countries = $query->orderBy('name')
        ->offset($pagination->offset)
        ->limit($pagination->limit)
        ->all();

	// de view wordt aangeroepen en het object $countries en $pagination wordt meegegeven.
    return $this->render('overzicht', [
        'countries' => $countries,
        'pagination' => $pagination,
    ]);
}

View

In Yii zit standaard bootstrap(3) geïnstalleerd. In de volgende view wordt gebruik gemaakt van bootstrap(3) styles.

Dan zetten we in de file views/country/overzicht.php het volgende

<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>

<div class="card">
  <div class="card-body">
  <h3 class="card-title">Countries</h5>

    <table class="table" style="width: 70rem;" border=0>
      <tr>
          <th scope="col" style="width: 10rem;">Land</th>
          <th scope="col" style="width: 5rem;">Code</th>
          <th scope="col" style="width: 10rem;">Hoofdstad</th>
          <th scope="col" style="text-align: right;width: 10rem;">Inwoners</th>

      </tr>
      <?php foreach ($countries as $country): ?>
        <tr>
            <td><?= $country->Name ?></td>
            <td><?= $country->Code ?></td>
            <td><?php
              if ($country->capital) { // note: f.e. Antartica has no Capital
                echo $country->capital->Name;
              } else {
                echo "";
              }
            ?></td>
            <td style="text-align: right"><?= number_format($country->Population, 0, ',', ' '); ?></td>
        </tr>
      <?php endforeach; ?>
    </table>

  </div>
</div>

<?= LinkPager::widget(['pagination' => $pagination]) ?>

In deze HTML-code onderscheiden we enkele zaken:

  1. We hebben een table waarin we alles afdrukken.
  2. We hebben een table header waarin we de kopjes van de verschillende kolommen afdrukken.
  3. We hebben een loop waarmee we door het country object heen itereren en alle countries afdruken.
  4. We hebben een widget die ervoor zorgt dat we naar de volgende pagina kunnen springen.

Opdrachten

  1. schrijf van de vier bovenstaande punten op waar je dit precies vind in de code, noteer de regels waarop het betrekking heeft. Bijvoorbeeld: 1 heeft betrekking op regel 10-32

  2. wat (welk stukje code) zorgt ervoor dat het inwoneraantal netjes geformatteerd wordt afgedrukt?

  3. In deze code wordt de naam van de hoofdstad afgedrukt (en niet meer de foreign key zoals in ons eerdere overzicht). Op welke regel wordt de naam van de hoofdstad afgedrukt?

  4. Er staan 'landen' in de database die geen hoofdstad hebben zoals bijvoorbeeld Antartica. Verander de code, zodat er in deze gevallen een streepje (-) wordt afgedrukt.

Opmerking:

In de view zie je php-code staan tussen <?php ?> en tussen <?= ?> Dit is bijna hetzelfde:
<?= $a ?> is een verkorte notering voor <?php echo $a ?> 

 

--