Storybook

Sorakuilu

Harjoituksen osat

Tunti 1. Toimeksianto ja storybook-sovelluksen esitutkimus
Tunti 2. Suunnittele storybook
Tunti 3. Toteuta tietokanta
Tunti 4. Toteuta käyttöliittymä
Tunti 5. Laadi runko ja reititys järjestelmään
Tunti 6. Toteuta lukijan etusivu (tietojen haku lukijan näkymässä)
Tunti 7. Toteuta rekisteröityminen(tietojen lisäys lukijan näkymässä)
Tunti 8. Toteuta autentikointi (kirjaudu ja kirjaudu ulos)
Tunti 9. Toteuta ylläpidon etusivu (tietojen haku)
Tunti 10.Toteuta jutun lisäys ylläpitonäkymässä, tietojen tarkistus mukaan
Tunti 11.Toteuta jutun muokkaus ylläpitonäkymässä, tietojen tarkistus mukaan
Tunti 12.Toteuta jutun poistaminen ylläpitonäkymässä
Omat tehtävät: suunnittele ja toteuta admin-näkymän yhden jutun näyttäminen (linkki on jo olemassa), omien tietojen muokkaaminen sekä salasanan vaihtaminen (piirrä lisäksi kaaviot)


Tunti 6. Toteuta lukijan etusivu (tietojen haku lukijan näkymässä) (./)

Lukijan pääsivun toteuttamiseen tehdään seuraavat toimet:

  1. otetaan tietokanta käyttöön index.php-sivulla
  2. aloitetaan malli Story.php (class Story), luodaan siihen metodi get_last_five_stories_and_name(), joka palauttaa viisi viimeistä juttua sekö metodi, joka palauttaa yhden jutun id:n perusteella
  3. aloitetaan kontrollereista toinen: StoryController (storyController.php) ja laaditaan siihen metodi index() sekö readStory($id)
  4. lisätään reitit pääsivua ja yhden sivun lukemista varten index.php-tiedostoon
  5. laaditaan näkymät etusivua ja yhden jutun lukemista varten

toteutettavat osat

Kuvassa näkyvät tässä vaiheessa tarvittavat osat, jo toteutetut ovat harmaalla pohjalla.

Alla oleva yksinkertainen sekvenssikaavio kuvaa yleistasolla keskustelua tiedostojen ja käyttäjän sekä tietokannan välillä:

sekvenssikaavio, index

Otetaan tietokanta käyttöön

Laadimme tunnilla kolme tietokantaa varten kolme tiedostoa: .config, Connection.php ja db.php.

.config sisältää tiedot yhteyttä varten, se on sijoitettu juurikansion ulkopuolelle (ja kannattaa sijoittaa mieluimmin www-kansioiden ulkopuolelle).

Connection.php on luokka yhteydenottamista varten.

db.php hakee molemmat edelliset käyttöön ja kutsuu Connection-luokan metodia make(), joka luo PDO-olion (yhteyden) muuttujaan $db.

Yhteys tietokantaan

Lisätään yhteys index.php-tiedostoon, koodissa näkyy lopputulos:

<?php
require './Route.php'// routing class
require './database/db.php'// database connection
?>

Aloitetaan malli (class Story)

Tietokantaa käsittelevään luokkaan kannattaa yleensä laittaa tietojäseniksi taulun kentät. Niin teemme myös tässä järjestelmässä.

Tietojäsenet ovat:

Järjestelmässä käytetään paljon staattisia metodeja (eivät käytä oliota, kutsutaan suoraan), tietojäseniä käytetään vain vähän hyväksi. Siitä syystä konstruktori asettaa arvot tyhjiksi. Kaaviossa staattiset metodit on alleviivattu.

Metodi get_last_five_stories_and_name() lukee kahdesta eri taulusta tietoa ja palauttaa viisi viimeistä järjestelmään kirjoitettua juttua sekä kirjoittajan nimen.

Mielenkiintoinen kohta on metodissa kirjoitettu määre "global $db". Varattua sanaa $global käytetään funktion sisältä kutsumaan pääohjelmassa määritettyä muuttujaa (se muuttaa muuttujan näkyvyysaluetta (scope) siten, että myös funktio voi käyttää muuttujaa). Tässä tietokanta tulee funktioiden käyttöön.

Lisätietoa näkyvyydestä

<?php
class Story 
{
    private 
$story_id;
    private 
$headline;
    private 
$article;
    private 
$published;
    private 
$hidedate;

    
    public function 
__construct()
    {
        
$this->story_id NULL;
        
$this->headline NULL;
        
$this->article NULL;
        
$this->published NULL;
        
$this->hidedate NULL;
    }
    
    
    public static function 
get_last_five_stories_and_name()
    {
        global 
$db;
        
        try 
        {
            
$statement $db->prepare("SELECT stories.story_id,stories.headline,stories.article,stories.published,stories.hidedate,stories.account_id,users.account_name FROM stories INNER JOIN users ON stories.account_id= users.account_id ORDER BY stories.published desc LIMIT 5;");
            
            
$statement->execute();
            return 
$statement->fetchAll(PDO::FETCH_CLASS);
        }
        catch (
PDOException $e)
        {
              
/* Exception (SQL error) */
              
echo $e->getMessage();
              return 
FALSE;
        }    
     }


    public static function 
getStoryById($id)
    {
        global 
$db;
        
        try  {
            
$statement $db->prepare("SELECT * FROM stories WHERE story_id = ?");
            
$statement->execute(array($id));
                    return 
$statement->fetchAll(PDO::FETCH_CLASS);
        }
        catch (
PDOException $e)
        {
          
/* Exception (SQL error) */
          
echo $e->getMessage();
          return 
FALSE;
        }
    }
}
?>

Aloitetaan StoryController.php

StoryController-luokan tietojäsen on suojattu $story.

Konstruktori luo uuden Storyn.

Metodi index() käyttää Story-luokan metodia get_last_five_stories_and_name() ja kutsuu index.view-näkymää.

<?php

require './database/models/story.php';


class 
StoryController 
{
    protected 
$story;
    
    public function 
__construct()
    {
        
$this->story = new Story();
    }
    
    public static function 
index()
    {
        
$stories Story::get_last_five_stories_and_name();
        require 
'./views/index.view.php';
    }

    public static function 
readStory($id)
    {
        
$story Story::getStoryById($id);
        require 
'./views/story.view.php';
    }
    
}

Lisätään reitti pääsivua varten index.php-tiedostoon

Lisätään reitti index.php-tiedostoon, koodissa näkyy lopputulos:

<?php
require './Route.php'// routing class
require './database/db.php'// database connection


require './controllers/StoryController.php';
$storyController = new StoryController();

//every route gets its own controller or view
Route::add('/',function() {
    global 
$storyController;
    
$storyController->index();    
},
'get');


Route::add('/story/(.*)',function($id) use ($storyController){
    
$storyController->readStory($id);
},
'get');


//start...
Route::run('/');
?>

Jos sovellus on muualla kuin juurikansiossa, viimeisen metodin (run) määrittämä polku vaihtuu.

Lisätään näkymä ./views/index.view.php

Kaikki html tulostetaan näkymätiedostoissa. Sen lisäksi kontrollerit luovat muuttujia, jotka sisältävät järjestelmän muodostamaa dataa. Näkymät lisätään kontrollerin loppuun sisällyttämällä ne require-funktiolla, joten muuttujat ovat automaattisesti näkymien käytössä.

Näkymätiedosto lisää ensin html-alkuosan ja loppuosan. Sen jälkeen se lisää niiden väliin kontrollerissa muodostettujen muuttujien $stories ja $message avulla html:n.

<?php
require './views/partials/head.php';

if(isset(
$message)) echo $message;

if(!empty(
$stories)) {
    foreach(
$stories as $story) {?>
        <h1><a href="./story/
        <?=$story->story_id ?>
        ">
        <?=$story->headline ?></a></h1>
        <h2><?=$story->published ?></h2>
        <h2><?=$story->account_name ?></h2>
        <p><?=$story->article ?></p>    
        <?php    
    
}
}

require 
'./views/partials/end.php';
?>

Lisätään näkymä ./views/story.view.php

<?php
require './views/partials/head.php';
?>

<h1><?=$story[0]->headline ?></h1>
<h2><?=$story[0]->published ?></h2>
<p><?=$story[0]->article ?></p>    
<?php    
require './views/partials/end.php';
?>


>> Tunti 7. Toteuta rekisteröityminen(tietojen lisäys lukijan näkymässä) >>