Advanced Kittenry - Tietokantasovellusohjeet

Sovelluksen rakenne ja kontrollerit

Tiivistelmä:

  • Sovelluksen sivut ovat projektin juuressa olevia kontrollereita, jotka käyttävät malleja ja näkymiä.
  • Kaikki näkymät menevät kansioon views
  • Tee sovelluksesi yleisesti käytetyille toiminnoille kirjastotiedosto, johon voi sijoittaa yleiskäyttöisiä toimintoja.
  • Kaikki kirjastotiedostot menevät omaan kansioonsa, esim. libs.
  • Mallit voi sijoittaa kirjastotiedostojen mukana omaan kansioonsa. Esim. libs/models.

Lopullisen projektin pitäisi noudatella tämäntapaista kansiorakennetta

views/
  userlist.php
libs/
  models/
    user.php
  common.php (Yleiskäyttöisiä funktioita)
users.php (Käyttäjänhallinnan kontrolleri)
~~~

PHP on historialtaan ja luonteeltaan selkeä skriptikieli. Toisin kuin useimmat käännettävien ohjelmointikielien ohjelmat, PHP-ohjelmalla ei ole erityistä nimettyä alkukohtaa, vaan suoritus alkaa tiedoston alusta ja jatkuu siitä tiedoston loppuun, ellei sitä erikseen keskeytetä.

Lisäksi PHP eroaa hieman useimmista muista web-ohjelmointikielistä suoraviivaisessa lähestymisessään URL-osoitteiden ja suoritettavan ohjelmakoodin väliseen riippuvuuteen.

Perussääntö on hyvin yksinkertainen, jokainen tiedosto näkyy oman URL:insa takana sillä palvelimella, minne tiedostot on sijoitettu.

Eräänlaisena poikkeuksena toimivat etusivut: Jos syöttää osoitekenttään pelkän hakemiston osoitteen, esim. http://tunnus.users.cs.helsinki.fi on se sama kuin kirjoittaisi http://tunnus.users.cs.helsinki.fi/index.php, kunhan htdocs-kansiossa on index.php-tiedosto.

Tästä johtuen yksinkertaisin tapa toteuttaa yksittäisen toiminnon kontrolleri PHP:llä ei oikeastaan vaadi muuta kuin sopivaan osoitteeseen sijoitetun PHP-tiedoston, joka kutsuu tarvitsemiaan kirjastoja tuottaakseen käyttäjälle halutun vastauksen aineistopyyntöön.

Spagettikoodi ja kontrolleri

Tiiviimmillään ja rumimmillaan tämä näkyy vieläkin ikävän yleisenä spagettikoodina, jossa sovelluksen kaikki kolme osaa: kontrolleri, näkymä ja malli ovat sulassa sovussa ja sekasotkussa samassa tiedostossa. Lopputulos on vähänkään monimutkaisemmissa sovelluksissa sekava ja hyvin vaikea ylläpitää.

spagettikoodi.php

<?php
  $yhteys = new PDO('pgsql:');
  $nimi = 'Matti';
?><!DOCTYPE html>
<html>
  <head><title>PHP Page</title></head>
  <body>
    <h1>Hello <?php $nimi; ?></h1>
    <?php 

      $sql = "SELECT id, nimi, osoite FROM kayttajat WHERE ika >= ? and sukunimi = ?";
      $kysely = $yhteys->prepare($sql);
      $tulokset = $kysely->execute(array(18,"Lehtonen"));
      //Tulostetaan tietoja löydetyistä käyttäjistä
      while($rivi = $tulokset->fetchObject()) {
        echo "<div>Käyttäjän $rivi->etunimi $rivi->sukunimi ikä on $rivi->ika</div>";
      }

    ?>
  </body>
</html>

Tällä kurssilla pyrimme hieman selkeämpään arkkitehtuuriin, jossa mallit ja näkymät määritellään omissa tiedostoissaan.

Tämä ei kuitenkaan varsinaisesti estä käyttämästä PHP:n suoraviivaista luonnetta siihen, että jätämme varsinaiset kontrollerit paljaaksi koodiksi, joka vain suoraan kutsuu erilaisia kirjastoja ja näyttää lopulta näkymän.

Esimerkkinä kuvitteellinen kissalistan kontrolleri:

kissalista.php

<?php 
  //Otetaan käyttöön kirjastotiedosto, joka hakee kasan omatekoisia yleistoimintoja, sekä malliluokka:
  require_once 'src/common.php';
  require_once 'src/models/kissa.php';
  
  //Selvitetään onko käyttäjä tehnyt haun
  $hakusana = null;
  if (!empty($_GET['haku'])) {
    $hakusana = $_GET['haku'];
  }

  //Kutsutaan malliluokan staattista metodia
  $kissat = Kissa::etsiHakusanalla($hakusana);
  
  //Näytetään näkymä lähettäen sille muutamia muuttujia
  naytaNakymä("kissalista", array(
    'title' => "Kissalista",
    'kissat' => $kissat
  ));

Jotta yllä oleva esimerkki toimisi, on luotava sen tueksi malliluokat, näkymät ja muutama yleiskäyttöinen luokka ja funktio.

Kontrollereista voi myös halutessaan tehdä kokonaisia luokkia, joissa on metodeja erilaisille sivuille ja toiminnoille. Tästä on usein paljon hyötyä selkeyden muodossa siinä vaiheessa kun projekti on laajentunut hieman.

Mallit

Sijoita projektin mallit omaan kansioonsa kirjastokansiosi alle, siten että kussakin tiedostossa on yksi malliluokka.

Sijoita malliisi kentät tietokantataulun kenttiä varten ja luo kentille getterit ja setterit sekä halutessasi konstruktori, joka ottaa kenttien arvot vastaan.

Työn edetessä teemme luokkiin metodeja, jotka osaavat hakea olioihin sisältöä tietokannasta, sekä metodit, joilla tietoa päivitetään takaisin kantaan.

Seuraavaksi:

Seuraavaksi tutustumme tarkemmin näkymien toteuttamiseen.