Gagnasafnsfræði, haust 2011

[ Dagskrá  |  Námsefni  |  Verkefni  |  Dæmatímar  |  Orðalisti  |  Námsmat  |  Kennslubók ]

Verkefni 5 - SQL og vefforritun

Lausnum skal skilað í hólf viðkomandi dæmakennara (sjá lista yfir dæmatíma).

Skiladagur: mánudaginn 3. október fyrir kl 16:00

Þið megið leysa verkefnið í forritunarmáli að ykkar eigin vali. Ég reikna samt með að flestir noti PHP og mun miða kennsluna við það.

Þið megið vinna saman í hópum (hámark 3 í hóp) og hver hópur skilar þá saman einni lausn.

Skilið öllum kóða á læsilegu formi með inndrætti.

Skiladæmi:

  1. Skilgreinið töflur til að halda utan um notendur, smáskilaboð (hámark 140 stafir) og vinatöflu.

    Taflan users skal innihalda eftirfarandi dálka:

    1. id: raðnúmer
    2. username fyrir login
    3. password, má vera sýnilegt (cleartext), fallegra að hafa það hakkað með t.d. MD5

    Taflan messages skal innihalda eftirfarandi dálka:

    1. id: raðnúmer
    2. userid: ytri vísun í users.id
    3. timestamp: tímasetning
    4. message: hámark 140 bókstafir

    Taflan follows skal innihalda eftirfarandi dálka:

    1. userid: ytri vísun í users.id
    2. following: ytri vísun í users.id

    Sýnið CREATE TABLE skipanirnar á læsilegu formi með inndrætti.

    Lausn:

    CREATE CREATE users (
    	id SERIAL PRIMARY KEY,
    	username VARCHAR(32) NOT NULL,
    	password CHAR(32) NOT NULL,
    	UNIQUE (username)
    );
    
    CREATE TABLE messages (
    	id SERIAL PRIMARY KEY, 
    	userid integer NOT NULL, 
    	timestamp TIMESTAMP NOT NULL, 
    	message VARCHAR(140) NOT NULL, 
    	FOREIGN KEY (userid) REFERENCES USERS (id)
    );
    
    CREATE TABLE follows (
    	userid INTEGER NOT NULL, 
    	following INTEGER NOT NULL, 
    	PRIMARY KEY (userid,following), 
    	FOREIGN KEY (userid) REFERENCES USERS (id), 
    	FOREIGN KEY (following) REFERENCES USERS (id)
    );
    
  2. Búið til vefsíðu til að skrá nýja notendur.

    register.php

    <?php
    require_once 'HTML/Template/Sigma.php';
    require_once 'config.php';
    
    session_start();
    
    $tpl = new HTML_Template_Sigma('tpl');
    $tpl->loadTemplateFile('register.tpl');
    
    $db = pg_connect($DB_CONF);
    
    $stat = pg_connection_status($db);
    
    if ($stat == PGSQL_CONNECTION_BAD)
    	die("Could not connect to database");
    
    if (isset($_POST['username']))
    {
    	$username = $_POST['username'];
    	$password = md5($_POST['password']);
    
    	$result = pg_insert($db, "users", array(
    		"username" => $username,
    		"password" => $password
    	));
    
    	header("Location: index.php");
    }
    
    $tpl->show();
    ?>
    

    register.tpl

    <!-- INCLUDE header.tpl -->
    <body>
    <h1>Twitter kerfi</h1>
    <h2>Skrá nýjan notanda</h2>
    <form method="POST" action="register.php">
    <label>Notandi</label>
    <input type="text" name="username">
    <label>Lykilorð</label>
    <input type="password" name="password">
    <input type="submit" value="Skrá">
    </form>
    </body>
    </html>
    

  3. Búið til vefsíðu þar sem notandi getur skráð sig inn (login) og skráð sig út (logout).

    Það þarf eina vefsíðu sem inniheldur HTML eyðublað þar sem notandi getur slegið inn notendanafn og lykilorð.

    Eyðublaðið er sent á dýnamíska vefsíðu sem les gögnin, flettir notanda upp í users og athugar hvort hann sé til og lykilorðið sé rétt.

    Ef allt stemmir þá eru viðeigandi upplýsingar skráðar í session geymsluna (notandi hefur verið auðkenndur, hvaða notandi þetta er, o.s.frv.)

    Búið einnig til vefsíðu þar sem notandi getur skráð sig út. Það hreinsar upp úr session geymslunni þ.a. notandi er ekki lengur auðkenndur.

    login.php

    <?php
    require_once 'HTML/Template/Sigma.php';
    require_once 'config.php';
    
    session_start();
    
    $tpl = new HTML_Template_Sigma('tpl');
    $tpl->loadTemplateFile('login.tpl');
    
    $db = pg_connect($DB_CONF);
    
    $stat = pg_connection_status($db);
    
    if ($stat == PGSQL_CONNECTION_BAD)
    	die("Could not connect to database");
    
    if (isset($_SESSION['auth']))
    {
    	header("Location: index.php");
    	exit;
    }
    
    if (isset($_POST['username']))
    {
    	$username = $_POST['username'];
    	$password = md5($_POST['password']);
    
    	$result = pg_query_params($db, 'SELECT * FROM users WHERE username=$1',
    				array($username));
    
    	if (pg_num_rows($result) == 0)
    	{
    		$tpl->touchBlock('loginerror');
    		$tpl->show();
    		exit;
    	}
    
    	$row = pg_fetch_assoc($result);
    
    	if ($row['password'] != $password)
    	{
    		$tpl->touchBlock('loginerror');
    		$tpl->show();
    		exit;
    	}
    
    	$_SESSION['auth'] = true;
    	$_SESSION['userid'] = $row['id'];
    	$_SESSION['username'] = $username;
    
    	header("Location: index.php");
    }
    
    $tpl->show();
    ?>
    

    login.tpl

    <!-- INCLUDE header.tpl -->
    <body>
    <h1>Twitter kerfi</h1>
    <h2>Innskráning</h2>
    <form method="POST" action="login.php">
    <label>Notandi</label>
    <input type="text" name="username">
    <label>Lykilorð</label>
    <input type="password" name="password">
    <input type="submit" value="Skrá inn">
    </form>
    <!-- BEGIN loginerror -->
    <font color="red">Vitlaus notandi eða lykilorð</font>
    <!-- END loginerror -->
    </body>
    </html>
    

    logout.php

    <?php
    session_start();
    session_destroy();
    
    header("Location: index.php");
    ?>
    
  4. Búið til vefsíðu til að sýna smáskilaboð hjá e-m tilteknum notanda.

    Vefsíðan skal lesa notandanafnið úr GET stika.

    Dæmi um hvernig væri hægt að kalla á vefsíðuna:

    http://server/view.php?user=abc
    

    Vefsíðan skal birta lista yfir nýjustu smáskilaboð notendans í tímaröð.

    view.php

    <?php
    require_once 'HTML/Template/Sigma.php';
    require_once 'config.php';
    
    session_start();
    
    $tpl = new HTML_Template_Sigma('tpl');
    $tpl->loadTemplateFile('view.tpl');
    
    $db = pg_connect($DB_CONF);
    
    $stat = pg_connection_status($db);
    
    if ($stat == PGSQL_CONNECTION_BAD)
    	die("Could not connect to database");
    
    $username = $_GET['username'];
    
    $query = <<<EOT
    SELECT TO_CHAR(m.timestamp, 'YYYY-MM-DD HH24:MI:SS') as timestamp,
           m.message
    FROM messages m, users u 
    WHERE m.userid=u.id 
      AND u.username=$1 
    ORDER BY timestamp DESC LIMIT 10
    EOT;
    
    $result = pg_query_params($db, $query, array($username));
    
    while ($row = pg_fetch_assoc($result))
    {
    	$tpl->setVariable($row);
    	$tpl->parse('message');
    }
    
    $tpl->show();
    ?>
    

    view.tpl

    <!-- INCLUDE header.tpl -->
    <body>
    <h1>Twitter kerfi</h1>
    <h2>Skilaboð</h2>
    <!-- BEGIN message -->
    {timestamp}: {message}
    <p>
    <!-- END message -->
    </body>
    </html>
    
  5. Búið til vefsíðu þar sem auðkenndur notandi getur sett inn ný smáskilaboð.

    Vefsíðan skal innihalda HTML eyðublað með textarea þar sem notandi getur slegið inn skilaboðin.

    Eyðublaðið er sent á dýnamíska vefsíðu sem skráir það í messages töfluna.

    post.php

    <?php
    require_once 'HTML/Template/Sigma.php';
    require_once 'config.php';
    
    session_start();
    
    $tpl = new HTML_Template_Sigma('tpl');
    $tpl->loadTemplateFile('post.tpl');
    
    if (empty($_SESSION['auth']))
    {
    	header("Location: login.php");
    	exit;
    }
    
    $db = pg_connect($DB_CONF);
    
    $stat = pg_connection_status($db);
    
    if ($stat == PGSQL_CONNECTION_BAD)
    	die("Could not connect to database");
    
    if (isset($_POST['message']))
    {
    	$message = $_POST['message'];
    
    	$result = pg_insert($db, "messages", array(
    		"userid"  => $_SESSION['userid'],
    		"timestamp" => date("Y-m-d H:i:s"),
    		"message" => $message
    	));
    
    	if (!$result)
    	{
    		print pg_last_error($db);
    		exit;
    	}
    
    	header("Location: index.php");
    }
    
    $tpl->show();
    ?>
    

    post.tpl

    <!-- INCLUDE header.tpl -->
    <body>
    <h1>Twitter kerfi</h1>
    <h2>Skrá ný skilaboð</h2>
    <form method="POST" action="post.php">
    <p>
    <textarea name="message" rows="6" cols="60" maxlength="140">
    </textarea>
    <p>
    <input type="submit" value="Senda">
    </form>
    </body>
    </html>
    
  6. Búið til vefsíðu til að sýna nýjustu smáskilaboð allra þeirra sem núverandi auðkenndur notandi fylgist með.

    Vefsíðan skal birta lista yfir nýjustu skilaboð fléttuð saman í tímaröð þ.a. hún birti t.d. síðustu 20 skilaboðin.

    feed.php

    <?php
    require_once 'HTML/Template/Sigma.php';
    require_once 'config.php';
    
    session_start();
    
    $tpl = new HTML_Template_Sigma('tpl');
    $tpl->loadTemplateFile('view.tpl');
    
    $db = pg_connect($DB_CONF);
    
    $stat = pg_connection_status($db);
    
    if ($stat == PGSQL_CONNECTION_BAD)
    	die("Could not connect to database");
    
    $query = <<<EOT
    SELECT
    	TO_CHAR(m.timestamp, 'YYYY-MM-DD HH24:MI:SS') as timestamp, 
    	m.message
    FROM messages m
    WHERE m.userid IN
       (SELECT following FROM follows WHERE userid=$1)
    ORDER BY timestamp DESC
    LIMIT 10
    EOT;
    
    $result = pg_query_params($db, $query, array($_SESSION['userid']));
    
    while ($row = pg_fetch_assoc($result))
    {
    	$tpl->setVariable($row);
    	$tpl->parse('message');
    }
    
    $tpl->show();
    ?>