l1.php

2.1 Uppgift 1

[ Utskriftsversion av denna uppgift ]

 

För att utföra denna uppgift behöver du göra följande:

l2.php

2.2 Uppgift 2

[ Utskriftsversion av dessa uppgifter ]

 

I sin enklaste form kan ett dataprogram beskrivas på följande sätt:

  1. Vi ger programmet någon form av indata
  2. Programmet behandlar detta data
  3. Programmet visar resultatet av behandlingen

För att exemplifiera detta i PHP så skall vi göra ett lite större system: En gästbok
Detta program kommer att byggas upp del för del, och ni kan konstatera att program inte skrivs uppifrån och neråt, utan att de istället byggs på inifrån och ut genom att sätta in tilläggsfunktionalitet i flera steg.

 

OBS! Ni skall SKRIVA koden som finns. Den är lite svår att bara knycka med Copy/Paste. Om jag märker att ni bara kopierar lägger jag ut allt i pdf-format med bortkopplad copy funktionalitet. Ni kan INTE lära er NÅGONTING genom att bara kopiera...

l3.php

2.2.1 1

OBS! Alla filer - såväl program- som datafiler - sätts i er php katalog om inte annat anges. Jag antar även att ni bläddrat genom de övriga sidorna i denna sajt, så att ni har en översikt över PHP...

Grundidén

Vi kommer att skapa ett formbaserat PHP program för en gästbok. Efter viss planering har vi kommit fram till att följande uppgifter behövs:

  1. Datum när det blev skrivet i gästboken
  2. Vem som skrivit i gästboken
  3. Elpostadressen till den som skrev
  4. En rubrik (subject) för meddelandet
  5. Själva texten i meddelandet

Dessutom finns det följande saker att beakta:

  1. Inläggen skall sorteras så att det senast skrivna kommer först och sedan de andra i omvänd ordning.
  2. För att enklast kunna sortera datum så behöver de vara i sorteringsbar ascii-form, d.v.s. i formen YYYYMMDD eller liknande med år före månad före dag före tid.
  3. Datum skall inte skrivas in i gästboken, utan de skall hanteras av systemet.
  4. För att enklast kunna sortera hela rader så sätts datum först i raden

För att lagra detta skall det användas en vanlig textfil. Det skulle även gå att använda en databas, men för tillfället duger en textfil.

 

Hur skall då denna fil se ut? Man skulle kunna tänka sig att sätta in de ovanstående uppgifterna på separata rader, men det är enklare att hantera datat om varje enskilt inlägg kommer på en rad i fil. Jämför gärna med databasers post och fält begrepp.

 

Vi börjar inte med att koda inmatningen, utan istället skapar vi en "fejkad" fil som vi jobbar vidare med.

Skapa datafilen:

Skapa en fil med namnet guestbook.txt och skriv in följande rader. Var noga med att slå <enter> efter varja rad - även den sista. Ordet <enter> skrivs inte in utan betyder att du skall trycks på enter tangenten...

2003.09.02 12:23|Mr X|mrx@some.com|Hej...|...på dej<enter>
2003.09.02 12:23|Ms Y|mry@where.com|test|testar bara<enter>

Ovastående är ett exempel på en s.k "delimited file". För att skilja fälten från varandra sätts det in ett valt tecken. Detta skulle kunna vara ett komma (comma separated values - CSV) eller tabulator (tab separated values). Jag har dock valt att sätta "|"- tecknet istället. Dels för att komma mycket väl kan förekomma i ett inlägg och dels för att tabulatorer syns lite dåligt ibland i listningar.

Skapa PHP programmet:

Det finns en praktisk liten funktion i PHP som heter file (se filerna_fil3.php). Den tar en komplett fil och sätter in resultatet i en array. Eftersom vi sett till att varje inlägg är en separat rad så är det praktiskt att kunna öppna filen i ett svep för att sedan loopa genom den. PHP har en hel del praktiska funktioner för att loopa genom arrays, t.ex. foreach (se array_cc.php) För att plocka ut de enskilda delarna av strängen använder vi explode (se array_str.php samt explode *)

Vi kommer nedan att bygga upp listningen steg för steg:

 

<?php
# öppna filen och sätt allt in i en array med namnet $innehållet
# om det inte fungerar så meddelar vi detta med Die funktionen
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");

# loopa genom arrayen
foreach( $innehållet as $rad )
{
    
# plocka ut de enskilda delarna som separeras av | tecknet
    
$fälten = explode( "|", $rad );
    
$datum =  $fälten[ 0 ];
    
$vem = $fälten[ 1 ];
    
$elpost = $fälten[ 2 ];
    
$ärende = $fälten[ 3 ];
    
$texten = $fälten[ 4 ];
    
# visa bara $vem för tillfället
    
echo $vem;
}
?>
Listning 2.3.1.1 - samples/_l3.php
[Visa i separat fönster]

För att slippa använda arrays så sätter vi in värdena i ett antal variabler med namnen $datum, $vem, $elpost, $ärende och $texten. Det finns en kortare form som gör samma sak och som ser ut så här (se även array_str.php):

<?php
# öppna filen och sätt allt in i en array med namnet $innehållet
# om det inte fungerar så meddelar vi detta med Die funktionen
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");

# loopa genom arrayen
foreach( $innehållet as $rad )
{
    
# plocka ut de enskilda delarna som separeras av | tecknet
    
list($datum, $vem,$elpost,$ärende,$texten) = explode( "|", $rad );
    
# visa bara $vem för tillfället
    
echo $vem;
}
?>
Listning 2.3.1.2 - samples/_l3a.php
[Visa i separat fönster]

 

Provkör programmet genom att surfa iväg till http://www.cc.puv.fi/~xxxxx/php/guestbook.php, där xxxxx är ditt användarnamn i nätverket. Tag gärna en titt på den genererade koden genom att ta <Högerklick>, View Source (i IE).

Mellananalys:

Vi borde nu ha insett följande saker:

  1. PHP har kraftfull hantering av såväl filer som arrays. I VB brukar vi kanske undvika arrays, mest eftersom de egentligen inte är så användbara, men i PHP skall vi försöka använda dem så mycket som möjligt.
  2. Variabler kan innhålla åäö, men måste börja med ett $ tecken
  3. PHP kod skall alltid omslutas med <?php .... ?>
  4. Kommentarer skrivs med hjälp av (bland annat) #
  5. För att skriva till webbsidan kan man använda echo
  6. Programsatser avslutas alltid med ;

Dessutom borde vi ha lagt märke till följande:

  1. De två raderna vi skriver kommer på samma rad på webbsidan.
  2. Det vi skapat är inte helt korrekt HTML kod, såtillvida att det fattas <html><head>... mm.

Första ändringarna i programmet:

  1. Ändra på raden:

    echo $vem;

    så att den istället blir

    echo $vem . "<br>";

    Detta gör att de två echo raderna kommer att komma på olika rader i browsern, men om du tar och tittar på den generarade html koden i browsern så är de i alla fall på samma rad i denna.

  2. Ändra samma rad till följande (och ta en titt på browserns source efteråt):

    echo $vem . "<br>\n";


  3. Vi skall även se till att det skapas giltig html kod genom att sätta in "vanlig html kod i filen. Observera att den med fördel kan sättas "utanför" php-koden:

    <html>
          <head>
            <title>En g&auml;stbok</title>
          </head>
        <body>
        <?php
        
    # öppna filen och sätt allt in i en array med namnet $innehållet
        # om det inte fungerar så meddelar vi detta med Die funktionen
        
    $innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
        
        
    # loopa genom arrayen
        
    foreach( $innehållet as $rad )
        {
            
    # plocka ut de enskilda delarna som separeras av | tecknet
            
    $fälten = explode( "|", $rad );
            
    $datum =  $fälten[ 0 ];
            
    $vem = $fälten[ 1 ];
            
    $elpost = $fälten[ 2 ];
            
    $ärende = $fälten[ 3 ];
            
    $texten = $fälten[ 4 ];
            
    # visa bara $vem för tillfället
            
    echo $vem . "<br>\n";
        }
        
    ?>
        </body>
    </html>
    Listning 2.3.1.3 - samples/_l3b.php
    [Visa i separat fönster]


    OBS! Jag kommer i fortsättningen att lämna bort all icke nödvändig html kod för att spara utrymme. Det är självklart att du skall se till att php skapar korrekta html sidor.

Mer komplett visning av gästboken

För att komma vidare måste vi sätta ut mer av de uppgifter som finns i gästboksfilen, samt även formatera dessa. För formateringen kommer det att användas html-tabeller så om du inte är förtrigen med dess så bör du ta en snabb titt på vad <table>, <tr> och <td> har för betydelse i vanlig html.

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <?php
    
# öppna filen och sätt allt in i en array med namnet $innehållet
    # om det inte fungerar så meddelar vi detta med Die funktionen
    
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
    
    
# börja en tabell - detta skall ske före loopen
    # sätt in radbyten \n för att ge mer lättläst kod om du
    # tittar på source...
    # observera änven att man inte kan skriva border="1" eftersom
    # "-tecknet skulle avsluta strängen. Man måste skriva \" för att få
    # ett " tecken innuti en teckensträng
    
    
echo "<table border=\"1\">\n";    
    

    # loopa genom arrayen
    
foreach( $innehållet as $rad )
    {
        
# plocka ut de enskilda delarna som separeras av | tecknet
        
$fälten = explode( "|", $rad );
        
$datum =  $fälten[ 0 ];
        
$vem = $fälten[ 1 ];
        
$elpost = $fälten[ 2 ];
        
$ärende = $fälten[ 3 ];
        
$texten = $fälten[ 4 ];
        
# nedan är nytt/ändrat
        # en rad för datum
        
        
echo "<tr><td>" . $datum . "</td></tr>\n";
        
# och fortsätt med resten
        
echo "<tr><td>" . $vem . "</td></tr>\n";
        echo
"<tr><td>" . $elpost . "</td></tr>\n";
        echo
"<tr><td>" . $ärende . "</td></tr>\n";
        echo
"<tr><td>" . $texten . "</td></tr>\n";        
        

    
}
    
# avsluta tabellen - detta skall ske efter loopen
    
    
echo "</table>\n";
    

    
?>
    </body>
</html>
Listning 2.3.1.4 - samples/_l3c.php
[Visa i separat fönster]

 

Listningen ser inte så vacker ut men det är ditt problem att få den snyggare. Kom bara ihåg att varje gång du vill få " i en teckensträng så måste du skriva \", t.ex för att få <td colspan="2"> så måste du skriva echo "<td colspan=\"2\">";

En vidareutveckling

Tag en titt på nedanstående kod och ändra i ditt program det som visas som överstruket till det som visas med fetstil. Tag sedan en ordentlig funderare på hur citationstecken mm. egentligen kommer in i den genererade koden...

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <?php
    $innehållet
= file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
    
    echo
"<table border=\"1\">\n";    
    foreach(
$innehållet as $rad )
    {
        
$fälten = explode( "|", $rad );
        
$datum =  $fälten[ 0 ];
        
$vem = $fälten[ 1 ];
        
$elpost = $fälten[ 2 ];
        
$ärende = $fälten[ 3 ];
        
$texten = $fälten[ 4 ];
        echo
"<tr><td>" . $datum . "</td></tr>\n";
        echo
"<tr><td>" . $vem . "</td></tr>\n";
        
        
echo "<tr><td>" . $elpost . "</td></tr>\n";
        
        
echo "<tr><td><a href=\"mailto:" . $elpost . "\">";
        echo
$elpost . "</a></td></tr>\n";
        

        
echo "<tr><td>" . $ärende . "</td></tr>\n";
        echo
"<tr><td>" . $texten . "</td></tr>\n";        
    }
    echo
"</table>\n";
    
?>
    </body>
</html>
Listning 2.3.1.5 - samples/_l3d.php
[Visa i separat fönster]

Du bör nu:

  1. Fundera över om du förstår den kod vi hitintills har. Om inte, bör du kontrollera från övriga sidor på denna site, och/eller ta en titt på nätet (förslagsvis på php:s hemsida) efter mer information om de enskilda programkoncept som framgår ur koden.
  2. Du får även "snygga till" den tabell som används för att visa gästboken. Ändra dock inte variabelnamnen.
  3. Du kan även fundera lite över lämpligheten att sätta ut mailto: länkar på en webbsida...
l4.php

2.2.2 2

Datum skrivs inte ut som vi vill ha det i Finland. Som datum är skapat är det dock enkelt att plocka ut de enskilda delarna. Året är alltid de fyra första tecknen, månad börjar alltid vid postion fem och är två tecken osv. För detta kan vi använda php-funktionen substr (se strings_van.php#substr). Vill vi att eventuella 0-utfyllnader skall tas bort kan vi omvandla delsträngen till ett heltal med t.ex. casting (se variabler.php)

 

Även sorteringen är enkel, eftersom det finns färdiga funktioner för arraysortering i php (se array_sort.php)

 

Se nedanstående kod:

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <?php
    $innehållet
= file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
    

    # sortera i omvänd ordning
    
arsort($innehållet);
    

    
echo "<table border=\"1\">\n";    
    foreach(
$innehållet as $rad )
    {
        
$fälten = explode( "|", $rad );
        
$datum =  $fälten[ 0 ];
        
$vem = $fälten[ 1 ];
        
$elpost = $fälten[ 2 ];
        
$ärende = $fälten[ 3 ];
        
$texten = $fälten[ 4 ];
        

        # plocka ut de olika delarna av datumet och plocka
        # ihop dem igen i rätt ordning
        
$datum = substr($datum, 8, 2) . "." .
                     (int)
substr($datum, 5, 2) . "." .
                     (int)
substr($datum, 0, 4) . " " .
                    
substr($datum, 11);        
        

        
echo "<tr><td>" . $datum . "</td></tr>\n";
        echo
"<tr><td>" . $vem . "</td></tr>\n";
        echo
"<tr><td><a href=\"mailto:" . $elpost . "\">";
        echo
$elpost . "</a></td></tr>\n";
        echo
"<tr><td>" . $ärende . "</td></tr>\n";
        echo
"<tr><td>" . $texten . "</td></tr>\n";        
    }
    echo
"</table>\n";
    
?>
    </body>
</html>
Listning 2.3.2.1 - samples/_l3e.php
[Visa i separat fönster]

 

l5.php

2.2.3 3

Vi sätter in en helt vanlig html-form i vårt program. Observera att formen sätts "utanför" php-koden och att php-koden skall vara oförändrad från tidigare steg. För mer om formar se forms.php. Man kan med fördel använda t.ex. Dreamweaver för att konstruera formen, eftersom denna inte skrivs i PHP.

 

Du bör framför allt observera name= som används för alla komponenter i formen. Provkör gärna koden nedan genoma att klicka på länken under koden. Skriv in något i textrutorna och klicka sedan på "Skriv" knappen. Tag en titt på hur adressradens URL ändras.

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    
# all PHP kod som tidigare
    # ...
    
?>
    </body>
</html>
Listning 2.3.3.1 - samples/_l3f.php
[Visa i separat fönster]

l6.php

2.2.4 4

För att kunna hantera det data som blev sänt av formen behöver vi göra ett tillägg i php-koden

 

Se isset.php, _request.php samt datum.php för mer information.

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    

    # kontrollera om det fanns "knapp=" i URL raden
    
if ( isset( $_REQUEST[ "knapp" ] ) )    
    {
        
# tag vem= värdet från URL
        
$vem = $_REQUEST[ "vem" ];
        
        
# tag elpost= värdet från URL    
        
$elpost = $_REQUEST[ "elpost" ];
        
        
# tag arende= värdet från URL            
        # observera att man helst inte skall använda
        # åäö i URL sammanhang
        # i PHP går det däremot bra med åäö
        
$ärende = $_REQUEST[ "arende" ];
        
        
# tag texten= värdet från URL            
        
$texten = $_REQUEST[ "texten" ];

        
# tag datum från systemet och formatera detta korrekt
        
$datum = date("Y.m.d H:i");
        
        
# skarva ihop en textsträng som skall kunna skrivas till filen
        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;
                
        
# för tillfället visar vi den bara på sidan och skriver inte
        # till någon fil
        
echo "Du klickade på Skriv och
                följande kommer att sättas i filen<br><pre>"
;
        echo
$allt;
        echo
"<pre>";
    }
    

    # all PHP kod som tidigare
    # ...
    
?>
    </body>
</html>
Listning 2.3.4.1 - samples/_l3g.php
[Visa i separat fönster]

Prova programmet genom att skriva in olika saker i formen...

l7.php

2.2.5 5

Det finns några problem med koden som den är. Prova genom att skriva in följande i Text: textarean på sidan som finns under denna länk:

  1. hej "kalle"
  2. Nu skall jag jäklas <textarea rows=1000>Hi hi</textarea>De va kul
  3. <a href=http://www.en.mycket.hemsk.porrsajt.com>oskyldig länk?</a>
  4. <font face=arial color=red size=7>Im BIG</font>
  5. En rad<enter>
    en till rad<enter>
    och en till
  6. En massa streck ||||||||||

Vi ser tydligt att måste beakta två saker i texten för att kunna sätta in detta i vår fil (som skall ha en rad per inlägg i gästboken):

  1. Radbyten måste beaktas och kanske bytas ut till <br>
  2. Vi kan inte godkänna html kod i texten - förr eller senare kommer det en lustigkurre och skriver t.ex. textarea exemplet ovan...
  3. Eftersom vår fil använder | för att avdela mellan fälten måste dessa tas bort om någon skriver in dem i en textbox.
  4. Eftersom PHP ändrar " till \" måste vi ändra den tillbaka...

Nedan är koden som beaktar detta. Tag eventuellt en titt på strings_conv.php, strings_van.php, funktioner.php samt syntax.php för mer information om de använda funktionerna.

 

Eftersom det är flera strängar som behöver beaktas/modifieras är det enklast att skapa en funktion som sköter om detta.

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    

    # funktion som "städar upp" texen så att den skall gå
    # att sätta in i filen
    
function beakta_alla_dumheter( $text )
    {
        
# tag bort alla html tags i texten
        
$text = strip_tags( $text );
        
# tag bort alla html tags i texten
        
$text = strip_tags( $text );
        
        
# sätt in <br> tags där det finns <enter> (CRLF)
        
$text = nl2br( $text );

        
# Radbyten hanteras lite olika i olika miljöer
        # i Unix sätts det in en LF (ascii 13) som i PHP
        # betecknas med \n
        # medan Windows maskiner sätter in CRLF (ascii 10 + ascii 13)
        # som i PHP betecknas med \r\n
        # för säkerhets skull tar vi bort bägge
        
        # tag bort eventuella \r ( CR )
        
$text = str_replace( "\r", "", $text  );
        
# tag bort eventuella \n ( LF )
        
$text = str_replace( "\n", "", $text );
        
        
# byt ut \" till " - jo det skall vara "\\\""
        
$text = str_replace( "\\\"", "\"", $text );

        
# tag bort eventuella | tecken
        
$text = str_replace( "|", "", $text );
        
        
# låt funktionen returnera den modifierade texten
        
return $text;
    }
    

    
if ( isset( $_REQUEST[ "knapp" ] ) )    
    {
        
$vem = $_REQUEST[ "vem" ];
        
$elpost = $_REQUEST[ "elpost" ];
        
$ärende = $_REQUEST[ "arende" ];
        
$texten = $_REQUEST[ "texten" ];
        
$datum = date("Y.m.d H:i");
        

        
$vem        = beakta_alla_dumheter( $vem );
        
$ärende     = beakta_alla_dumheter( $ärende );
        
$elpost     = beakta_alla_dumheter( $elpost );
        
$texten     = beakta_alla_dumheter( $texten );
        


        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;
        

        # ändrat lite på echo för att visa tydligare vad som skett
        
echo "Du klickade på Skriv och
                följande kommer att sättas i filen<br>"
;
        echo
htmlentities ($allt);
        

    
}
    

    # all PHP kod som tidigare
    # ...
    
?>
    </body>
</html>
Listning 2.3.5.1 - samples/_l3i.php
[Visa i separat fönster]

OBS! För tillfället bryr vi oss inte om att det kan lämnas tomt i alla textboxar - valideringen kommer senare...

l8.php

2.2.6 6

Det är förhållandevis enkelt att läsa filer. Hela Internet går ju ut på att läsa filer och visa dessa. Att skriva är dock lite mer komplicerat.

 

Kopiera all kod som fiinns i rutan nedan och sätt in i en ny fil som du kallar filtest.php. Prova detta program genom att surfa till detta program på din hemsideskatalog.

 

<?php     
    $teststräng
= "en liten teststräng";
    
# Öppna en fil för skrivning      
    # skapa den vid behov
    
$filen = fopen ( "testa.txt", "w+" );

     
    
# gick det?
    
if ( $filen )  
    {
        
# lås filen så att andra kan läsa men inte skriva
        
flock( $filen, 1 );
        
# skriv till filen
        
fputs ( $filen, $teststräng );
        
# tag bort låsningen
        
flock( $filen, 3 );  
        
# stäng filen
        
fclose ( $filen );
        echo
"Har skrivit till filen";
    }
    else
    {
        echo
"Det sket sig!";
    }
    
?>
Listning 2.3.6.1 - samples/tt2.php
[Visa i separat fönster]

 

Om detta program fungerar är allt frid och fröjd, men troligtvis får du följande resultat istället (... kommer att ersättas av din hemkatalogs path):


Warning: fopen("testa.txt", "w+") - Permission denied in

...\tt2.php on line 5
Det sket sig!

 

Om du fick ett felmeddelande i stil med ovanstående beror detta på att php-programmet inte har rätt att skriva till denna fil. Gör i så fall följande:

(Bägge operativsystemen kräver således att filen finns för att man skall kunna ändra på dess rättigheter. En bättre idé kan vara att sätta alla filer som skall kunna ändras till en underkatalog, och därefter se till att hela katalogen har modifieringsrättigheter.)

 

Efter att ha gjort ovanstående ändringar i filskyddet för testa.txt kan du prova filtest.php igen. Förhoppningsvis fungerar det nu.

 

Du kan även prova följande ändringar. Prova programmet flera gånger genom att klicka på refresh i din browser. Tag sedan en titt på vad filen testa.txt innehåller.

 

<?php     
    $teststräng
= "en liten teststräng";
    
# Öppna en fil för skrivning      
    # skapa den vid behov
    
    
$filen = fopen ( "testa.txt", "a");

     
    
# gick det?
    
if ( $filen )  
    {
        
# lås filen så att andra kan läsa men inte skriva
        
flock( $filen, 1 );
        
# skriv till filen
        
fputs ( $filen, $teststräng . "\r\n");
        
# tag bort låsningen
        
flock( $filen, 3 );  
        
# stäng filen
        
fclose ( $filen );
        echo
"Har skrivit till filen";
    }
    else
    {
        echo
"Det sket sig!";
    }
    
?>
Listning 2.3.6.2 - samples/tt3.php
[Visa i separat fönster]

Modifiera din gästboksfil

Se till att guestbook.txt har skrivrättigheter satt på samma sätt som du satte skrivrättigheter för filen testa.txt. Vill du veta vad 766 egentligen betyder så ta en titt på sidan filerna_fil.php. Dessutom kan det vara skäl att se hur fopen fungerar på sidan filerna_fil3.php

 

Modifiera din guestbook.php

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    
function beakta_alla_dumheter( $text )
    {
        
$text = strip_tags( $text );
        
$text = strip_tags( $text );
        
$text = nl2br( $text );
        
$text = str_replace( "\r", "", $text  );
        
$text = str_replace( "\n", "", $text );
        
$text = str_replace( "\\\"", "\"", $text );
        
$text = str_replace( "|", "", $text );
        return
$text;
    }
    if ( isset(
$_REQUEST[ "knapp" ] ) )    
    {
        
$vem = $_REQUEST[ "vem" ];
        
$elpost = $_REQUEST[ "elpost" ];
        
$ärende = $_REQUEST[ "arende" ];
        
$texten = $_REQUEST[ "texten" ];
        
$datum = date("Y.m.d H:i");
        
$vem        = beakta_alla_dumheter( $vem );
        
$ärende     = beakta_alla_dumheter( $ärende );
        
$elpost     = beakta_alla_dumheter( $elpost );
        
$texten     = beakta_alla_dumheter( $texten );
        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;

        
# ändrat lite på echo för att visa tydligare vad som skett
        echo "Du klickade på Skriv och
                följande kommer att sättas i filen<br>";
        echo htmlentities ($allt);

        
        # öppna guestbook.txt för "append" = tillägg
        
$filen = fopen ( "guestbook.txt", "a");  
        
# gick det?
        
if ( $filen )   
        {  
            
# lås filen så att andra kan läsa men inte skriva
            
flock( $filen, 1 );  
            
# skriv till filen \n är för att notepad skall
            
fputs ( $filen, $allt . "\n");  
            
# tag bort låsningen
            
flock( $filen, 3 );   
            
# stäng filen
            
fclose ( $filen );
        }
        

    
}

    
# all PHP kod som tidigare
    # ...
    
?>
    </body>
</html>
Listning 2.3.6.3 - samples/_l3j.php
[Visa i separat fönster]

l9.php

2.2.7 7

Förhoppningsvis har du nu en hyfsat fungerande gästbok.

 

Det finns dock två allvarliga buggar + ett litet problem:

  1. Om man tar Refresh på sidan efter att ha skrivit i gästboken så kommer det stt skrivas samma sak på nytt.
  2. Man kan ju faktiskt lämna tomt i alla fält.
  3. Koden börjar bli lite komplicerad - mest eftersom den innehåller såväl html som php kod. Jobbar vi vidare på så sätt blir allt en hemsk soppa.
Det är den sista vi skall börja med...

Dela upp html och kod

Tag en kopia av din fil guestbook.php och kalla kopian för guestcode.php (den skall finnas i samma katalog som guestbook.php och guestbook.txt)

 

Modifiera sedan guestcode.php så att allt som inte finns innanför <?php och ?> tas bort. Se även till att <?php kommer direkt som första rad / tecken i filen:

<?php
    
function beakta_alla_dumheter( $text )
    {
        
$text = strip_tags( $text );
        
$text = strip_tags( $text );
        
$text = nl2br( $text );
        
$text = str_replace( "\r", "", $text  );
        
$text = str_replace( "\n", "", $text );
        
$text = str_replace( "\\\"", "\"", $text );
        
$text = str_replace( "|", "", $text );
        return
$text;
    }
    if ( isset(
$_REQUEST[ "knapp" ] ) )    
    {
        
$vem = $_REQUEST[ "vem" ];
        
$elpost = $_REQUEST[ "elpost" ];
        
$ärende = $_REQUEST[ "arende" ];
        
$texten = $_REQUEST[ "texten" ];
        
$datum = date("Y.m.d H:i:s");
        
$vem        = beakta_alla_dumheter( $vem );
        
$ärende     = beakta_alla_dumheter( $ärende );
        
$elpost     = beakta_alla_dumheter( $elpost );
        
$texten     = beakta_alla_dumheter( $texten );
        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;
        
$filen = fopen ( "guestbook.txt", "a");  
        if (
$filen )   
        {  
            
flock( $filen, 1 );  
            
fputs ( $filen, $allt . "\n");  
            
flock( $filen, 3 );   
            
fclose ( $filen );
        }
    }
    
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
    
arsort($innehållet);
    echo
"<table border=\"1\">\n";     
    foreach(
$innehållet as $rad )
    {
        
$fälten = explode( "|", $rad );
        
$datum =  $fälten[ 0 ];
        
$vem = $fälten[ 1 ];
        
$elpost = $fälten[ 2 ];
        
$ärende = $fälten[ 3 ];
        
$texten = $fälten[ 4 ];
        
$datum = substr($datum, 8, 2) . "." .
                     (int)
substr($datum, 5, 2) . "." .
                     (int)
substr($datum, 0, 4) . " " .
                     
substr($datum, 11);         
         
        echo
"<tr><td>" . $datum . "</td></tr>\n";
        echo
"<tr><td>" . $vem . "</td></tr>\n";
        echo
"<tr><td><a href=\"mailto:" . $elpost . "\">";
        echo
$elpost . "</a></td></tr>\n";
        echo
"<tr><td>" . $ärende . "</td></tr>\n";
        echo
"<tr><td>" . $texten . "</td></tr>\n";         
    }
    echo
"</table>\n";
?>
Listning 2.3.7.1 - samples/guestcode.php
[Visa i separat fönster]

Modifiera sedan gustbook.php så att all php-kod tas bort:

<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    
    </body>
</html>
Listning 2.3.7.2 - samples/guestbook.php
[Visa i separat fönster]

Du har nu två php-filer: en med alla php kod och en med all html kod.

 

Ändra sedan guestcode.php så att gästbokslistningen blir till en funktion:

<?php
    
function beakta_alla_dumheter( $text )
    {
        
$text = strip_tags( $text );
        
$text = strip_tags( $text );
        
$text = nl2br( $text );
        
$text = str_replace( "\r", "", $text  );
        
$text = str_replace( "\n", "", $text );
        
$text = str_replace( "\\\"", "\"", $text );
        
$text = str_replace( "|", "", $text );
        return
$text;
    }
    if ( isset(
$_REQUEST[ "knapp" ] ) )    
    {
        
$vem = $_REQUEST[ "vem" ];
        
$elpost = $_REQUEST[ "elpost" ];
        
$ärende = $_REQUEST[ "arende" ];
        
$texten = $_REQUEST[ "texten" ];
        
$datum = date("Y.m.d H:i:s");
        
$vem        = beakta_alla_dumheter( $vem );
        
$ärende     = beakta_alla_dumheter( $ärende );
        
$elpost     = beakta_alla_dumheter( $elpost );
        
$texten     = beakta_alla_dumheter( $texten );
        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;
        
$filen = fopen ( "guestbook.txt", "a");  
        if (
$filen )   
        {  
            
flock( $filen, 1 );  
            
fputs ( $filen, $allt . "\n");  
            
flock( $filen, 3 );   
            
fclose ( $filen );
        }
    }

    
function visa_gästboken()
    {

        
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
        
arsort($innehållet);
        echo
"<table border=\"1\">\n";     
        foreach(
$innehållet as $rad )
        {
            
$fälten = explode( "|", $rad );
            
$datum =  $fälten[ 0 ];
            
$vem = $fälten[ 1 ];
            
$elpost = $fälten[ 2 ];
            
$ärende = $fälten[ 3 ];
            
$texten = $fälten[ 4 ];
            
$datum = substr($datum, 8, 2) . "." .
                         (int)
substr($datum, 5, 2) . "." .
                         (int)
substr($datum, 0, 4) . " " .
                        
substr($datum, 11);         
            
            echo
"<tr><td>" . $datum . "</td></tr>\n";
            echo
"<tr><td>" . $vem . "</td></tr>\n";
            echo
"<tr><td><a href=\"mailto:" . $elpost . "\">";
            echo
$elpost . "</a></td></tr>\n";
            echo
"<tr><td>" . $ärende . "</td></tr>\n";
            echo
"<tr><td>" . $texten . "</td></tr>\n";         
        }
        echo
"</table>\n";

    
}

?>
Listning 2.3.7.3 - samples/guestcode2.php
[Visa i separat fönster]

Ändra sedan guestbook.php på följande sätt:

<?php

include_once("guestcode.php");
# säkrare version kan vara:
# include_once( dirname(__FILE__) . "/guestcode.php");

?>
<html>
      <head>
        <title>En g&auml;stbok</title>
      </head>
    <body>
    <form>
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    
visa_gästboken();
    
?>
    </body>
</html>
Listning 2.3.7.4 - samples/guestbook2.php
[Visa i separat fönster]

 

Dess ändringar gör php-koden mer modulär och html-koden blir enklare att editera i en vanlig html-editor. Dessutom kan man nu dela upp projektet så att en person skriver php och en annan skriver html; en ack så viktig finess...

 

l10.php

2.2.8 8

Problemet är ju att URL i adressfältet är guestbook.php?vem=aa&...

efter att vi skrivit i gästboken, och om vi laddar om sidan är det ju denna url som laddas.

Vi borde således "tömma" adressen från alla parametrar efter att vi skrivit till filen. Det går dock inte att tömma dessa i efterskott. Det är däremot helt möjligt att ladda sidan på nytt, man denna gång utan parametrar. Detta görs med några rader på lämpligt ställe, se nedan:

 

<?php
    
function beakta_alla_dumheter( $text )
    {
        
$text = strip_tags( $text );
        
$text = strip_tags( $text );
        
$text = nl2br( $text );
        
$text = str_replace( "\r", "", $text  );
        
$text = str_replace( "\n", "", $text );
        
$text = str_replace( "\\\"", "\"", $text );
        
$text = str_replace( "|", "", $text );
        return
$text;
    }
    if ( isset(
$_REQUEST[ "knapp" ] ) )
    {
        
$vem = $_REQUEST[ "vem" ];
        
$elpost = $_REQUEST[ "elpost" ];
        
$ärende = $_REQUEST[ "arende" ];
        
$texten = $_REQUEST[ "texten" ];
        
$datum = date("Y.m.d H:i:s");
        
$vem        = beakta_alla_dumheter( $vem );
        
$ärende     = beakta_alla_dumheter( $ärende );
        
$elpost     = beakta_alla_dumheter( $elpost );
        
$texten     = beakta_alla_dumheter( $texten );
        
$allt = $datum . "|" . $vem . "|" . $elpost . "|" .
                
$ärende . "|" . $texten ;
        
$filen = fopen ( "guestbook.txt", "a");
        if (
$filen )
        {
            
flock( $filen, 1 );
            
fputs ( $filen, $allt . "\n");
            
flock( $filen, 3 );
            
fclose ( $filen );
        }

        # ladda sidan på nytt - men utan några ULR parametrar
        # du får INTE skriva något till sidan innan du sätter
        # header
        # OBS! Stora L i Location och EXAKT ett
        # mellanslag efter :
        
header("Location: guestbook.php");
        exit;

    
}

    function
visa_gästboken()
    {
        
$innehållet = file ( "guestbook.txt" ) Or Die("Kunde inte öppna filen");
        
arsort($innehållet);
        echo
"<table border=\"1\">\n";
        foreach(
$innehållet as $rad )
        {
            
$fälten = explode( "|", $rad );
            
$datum =  $fälten[ 0 ];
            
$vem = $fälten[ 1 ];
            
$elpost = $fälten[ 2 ];
            
$ärende = $fälten[ 3 ];
            
$texten = $fälten[ 4 ];
            
$datum = substr($datum, 8, 2) . "." .
                         (int)
substr($datum, 5, 2) . "." .
                         (int)
substr($datum, 0, 4) . " " .
                        
substr($datum, 11);

            echo
"<tr><td>" . $datum . "</td></tr>\n";
            echo
"<tr><td>" . $vem . "</td></tr>\n";
            echo
"<tr><td><a href=\"mailto:" . $elpost . "\">";
            echo
$elpost . "</a></td></tr>\n";
            echo
"<tr><td>" . $ärende . "</td></tr>\n";
            echo
"<tr><td>" . $texten . "</td></tr>\n";
        }
        echo
"</table>\n";
    }
?>
Listning 2.3.8.1 - samples/guestcode3.php
[Visa i separat fönster]

 

Vad gör vi egentligen?

Location modifierar headern på sidan. Tag en titt på följande länk (location.php) där jag visar allt - inklusive headern - som sänds från servern för två sidor, den ena är en sida som finns, medan den andra är en sida som "redirectar" till en annan sida. Observera att Location: är satt på den andra sidan.

När browsern stöter på Location i headern så kommer den att ladda den url som där anges, utan att fortsätta med sidan. Det är detta vi simulerar genom att sätta Header("Location: guestbook.php")

 

 

l11.php

2.2.9 9

Den enklaste formen av validering är att låta JavaScript sköta om detta redan på klienten. Se även Uppgift 1.5 (ep1.php)

<?php
include_once("guestcode3.php");
?>
<html>
      <head>
        <title>En g&auml;stbok</title>

        <script>
        <!--
        function kolla()
        {
            // kontrollera om det står något i formen med namnet
            // myform och textboxen vem
            if (document.myform.vem.value.length == 0)
            {
                alert("Du måste ange namn.");
                return false;
            }
            if (document.myform.elpost.value.length == 0)
            {
                alert("Du måste ange elpost.");
                return false;
            }
            if (document.myform.arende.value.length == 0)
            {
                alert("Du måste ange ärende.");
                return false;
            }
            if (document.myform.texten.value.length == 0)
            {
                alert("Du måste ange ärende.");
                return false;
            }
        }
        //-->
        </script>

      </head>
    <body>
    <form name="myform" onsubmit="return kolla();">
        <table border="1">
        <tr><td>Namn:</td><td>
            <input type="text" name="vem">
        </td></tr>
        <tr><td>Elpost:</td><td>
            <input type="text" name="elpost">
        </td></tr>
        <tr><td>Ärende:</td><td>
            <input type="text" name="arende">
        </td></tr>
        <tr><td>Text:</td>
        <td>
            <textarea name="texten" rows="5" cols="40"></textarea>
        </td></tr>
        <tr><td>&nbsp;</td><td>
            <input type="submit" name="knapp" value="    Skriv    ">
        </td></tr>
        </table>
    </form>
    <?php
    visa_gästboken
();
    
?>
    </body>
</html>
Listning 2.3.9.1 - samples/guestbook4.php
[Visa i separat fönster]

 

 

 

l12.php

2.2.10 Din uppgift

Jag antar att du nu har gått igenom alla steg, och dessutom försökt lista ut vad alla delar av programmet gör - har du inte eller vet du inte går du först igenom alla tidigare delar en gång till.

 

Jag vill sedan att du skall göra följande:

  1. Sekunder
    Gästbokens sortering fungerar inte för inlägg som skett samma minut. Ändra koden där det skrivs till textfilen så att även sekunder skrivs in i filen. Som det är nu är det ju bara timmar och minuter.

  2. Sortering
    Ändra sortering så att inläggen listas med de äldsta först och nyare senare.

  3. Numrering
    Ändra visningen av gästboksinlägg så att varje inlägg numreras. Numreringen sker så att första som visas får nummer 1, den andra får nummer 2 o.s.v.
    Tips: En klassisk ackumulerande variabel i loopen gör säkert susen...

  4. Snygga till
    Snygga till sidan. Formen (guestbook.php) går att snygga till i t.ex. Dremweaver, medan koden för listningen kräver kunskap i html. Observera hur html-attribut skrivs in i textsträngar...

  5. Textfilen
    När vi öppnar en fil för append, så skapas den om den inte finns. Problemet med nuvarande kod är att filen först måste skapas, så att vi kan ge den rätta filsäkerhetsinställningar. En lösning är att skapa en data katalog under vår php katalog. Om vi ger data katalogen skrivrättigheter kommer alla filer som skapas där även att ha skrivrättigheter.
    Skapa data katalogen, ge den skrivrättigheter och modifiera sedan koden så att guestbook.txt antas finnas i denna katalog. Prova koden genom att inte ha en färdig guestbook.txt.

    OBS! i en Unix miljö funkar det oftast bäst om vi anger att data är en underkatalog till nuvarande genom att skriva "./data/gustbook.txt" och inte "data/gustbook.txt".
    OBS2! Även om vi använder Windows så fungerar / i PHP - använd aldrig \ som i t.ex. "data\guestbook.txt" utan använd alltid sk. "forward slash" som i Unix (/).

  6. Och om du vill...
    Extra uppgift. Ej obligatorisk, men ger charmpoäng ;-)
    På sidan http://www.bet.puv.fi/anders.enges/enges/ finns den enda gästbok jag någonsin gjort. Det som skiljer denna från vår är att i min gästbok kan man även göra hemliga inlägg. Ändra på koden så att även hemliga inlägg kan göras. Detta kräver ändring i såväl form, kod som filstruktur för gästboksfilen.

 

 

ovn1_1.php

2.3 Extra uppgift

[ Utskriftsversion av dessa uppgifter ]

 

Sidans tema: include_once, allmänt om kodning

 

Denna övning är en flerstegsprocess där resultatet skall bli en sida där man kan sätta in och ta bort länkar. Jag använder inte en databas, utan kör mot en vanlig textfil. Som lite extra krydda skall sidan ha möjlighet att kontrollera att länkarna är i skick samt - vid behov - tid och storlek för filen som länkats till.

Startpunkten

  1. Skapa en katalog under din site (Linux eller Windows). Katalogen skall heta links. Se till att webservern har skrivrättigheter till denna.
    I linux betyder detta att du efter att ha skapat katalogen med mkdir links så skriver du chmod 777 links
    (Detta är inte en helt god idé - mer om detta senare)
    I Windows ser du till att IUSR_SERVERNAMN har read, write och execute rätt till katalogen

  2. Skapa en fil med namnet o1code.php i denna katalog och sätt in följande i denna fil:
    <?php
        
    # det kommer nog mer hit...
    ?>
    Listning 2.8.1 - samples/o1code.php

    Resultat av listning 2.8.1


  3. Skapa en fil med namnet links.php i denna katalog och sätt in följande HTML-kod i denna fil:
    <?php
        
    include_once( dirname ( __FILE__ ) . "/o1code.php" );
    ?>
    <html>
    <head>
    <title>Mina länkar</title>
    <meta    http-equiv="Content-Type"
            content="text/html; charset=iso-8859-1">
    </head>
    <body bgcolor="#FFFFFF">


    </body>
    </html>
    Listning 2.8.2 - samples/o1.php

    Mina länkar
    Resultat av listning 2.8.2


  4. Skapa en fil med namnet links.txt och sätt den i samma katalog som de övriga filerna (visserligen skall filen kunna hanteras direkt med ett webgränssnitt men vi kommer snabbare igång med en startfil) . Skriv in ett antal rader enligt följande system:

    webadress<tabulator>förklaring<tabulator>betyg<tabulator>titel<enter>

    OBS! Se gärna till att ni sätter in minst en giltig adress, minst en adress där servern finns men inte sidan och minst en där servern inte finns

    Exempel:
    http://www.puv.fi/    En websajt    1    Vasa Yrkeshögskola
    http://www.puv.fi/not_exist.asp     En annan    2    En sida
    http://www.not_exist.fi/test.htm    Funkar?      3     Titel
    Listning 2.8.3 - samples/links_demo.txt
    [Visa i separat fönster]

    OBS! Se till att URL slutar med / om du inte har ett filnamn angivet

ovn1_2.php

2.3.1 Listningen

Sidans tema: file, list, foreach, function

 

OBS! Jag måste skapa nya filer för varje steg. Ni skall använda samma filer som i föregående sida.

Modifiera o1code.php

Öppna o1code.php och sätt in följande

<?php
    
# en funktion som visar innehållet i
    # länklistan
    # parameter: namnet på filen
    
function visaLänkarna ( $filnamn )
    {
        
# öppna filen och sätt allt in i en array
        
$allt = file( $filnamn  );

        
# vi skall returnera en komplett HTML-tabell
        # observera .= (en punkt före =)
        
$result = "<table border=\"1\">";    
        
$result .= "<tr>";
        
$result .= "<td>URL</td>";
        
$result .= "<td>Förklaring</td>";
        
$result .= "<td>Betyg</td>";
        
$result .= "<td>Titel</td>";
        
$result .= "</tr>";

        
# loopa genom arrayen allt
        # raden kommer att vara en rad i filen
        
foreach( $allt as $raden )
        {
            
# plocka ut ut de enskilda fälten
            # explode skapar en array och
            # list skapar enskilda variabler av arrayen
            
list($url, $description, $rating, $title ) = explode ( "\t", $raden );
            
            
# plocka ihop såval tabellen men också "a href"
            
$result .= "<tr><td><a href=\"$url\">$url</a></td>";
            
$result .= "<td>$description</td>";
            
$result .= "<td>$rating</td>";
            
$result .= "<td>$title</td></tr>";
        }

        
# avsluta tabellen
        
$result .= "</table>";

        
# returnera den genererade tabellen
        
return $result;
    }
?>
Listning 2.8.1.1 - samples/o1code2.php

Resultat av listning 2.8.1.1

Modifiera links.php

Sätt sedan in detta i links.php. Observera att det även har ändrats i början av filen

<?php
    
# jag måste skapa en ny fil - du skall fortfarende
    # inkludera "/o1code.php"
    # om du bara tar copy/paste varje gång
    # så får du problem (skyll dig själv)
    
include_once( dirname ( __FILE__ ) . "/o1code2.php" );

    
# med den katalogstruktur som er övning har
    # kan du även skriva
    # $länkFilen = "links.txt" ;
    # med min struktur måste jag skriva lite annorunda
    
$länkFilen = dirname ( __FILE__ ) . "/links.txt" ;
?>
<html>
<head>
<title>Mina länkar</title>
<meta    http-equiv="Content-Type"
        content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">

<?php
    
# använd funktionen i den inkuderade filen
    # och visa dess resutat
    
echo visaLänkarna( $länkFilen );
?>

</body>
</html>
Listning 2.8.1.2 - samples/o1_2.php

Mina länkar
URLFörklaringBetygTitel
Resultat av listning 2.8.1.2

Att fundera på:

Förstår du hur systemet fungerar? Om inte...

Skule det inte vara bra att kunna visa listan sorterad på lite olika sätt? Se nästa sida.

ovn1_3.php

2.3.2 Sortera - steg 1

Sidans tema: $HTTP_SERVER_VARS

Modifiera o1code.php

Öppna o1code.php och ändra den på följande sätt

<?php
    
# en funktion som visar innehållet i
    # länklistan
    # parameter: namnet på filen
    
function visaLänkarna ( $filnamn )
    {
        
# NYTT------------------------------------------
        # I PHP 4.1.0 skulle vi också kunnat skriva
        # $filen = $_SERVER["PHP_SELF"];
        # och inte behövt global raden...
        
global $HTTP_SERVER_VARS;
        
$filen = $HTTP_SERVER_VARS["PHP_SELF"];
        
# SLUT PÅ NYTT-----------------------------------

        # öppna filen och sätt allt in i en array
        
$allt = file( $filnamn  );

        
# vi skall returnera en komplett HTML-tabell
        
$result = "<table border=\"1\">";    
        
        
# ÄNDRADE ---------------------------------------
        
$result .= "<tr>";
        
$result .= "<td><a href=\"$filen?SORT=url\">URL</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=description\">Förklaring</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=rating\">Betyg</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=title\">Titel</a></td>";
        
$result .= "</tr>";
        
# SLUT PÅ ÄNDRADE -------------------------------

        # loopa genom arrayen allt
        # raden kommer att vara en rad i filen
        
foreach( $allt as $raden )
        {
            
# plocka ut ut de enskilda fälten
            # explode skapar en array och
            # list skapar enskilda variabler av arrayen
            
list($url, $description, $rating, $title ) = explode ( "\t", $raden );
            
            
# plocka ihop såval tabellen men också "a href"
            
$result .= "<tr><td><a href=\"$url\">$url</a></td>";
            
$result .= "<td>$description</td>";
            
$result .= "<td>$rating</td>";
            
$result .= "<td>$title</td></tr>";
        }

        
# avsluta tabellen
        
$result .= "</table>";

        
# returnera den genererade tabellen
        
return $result;
    }
?>
Listning 2.8.2.1 - samples/o1code3.php

Resultat av listning 2.8.2.1

Inga ändringar i links.php

<?php
    
# jag måste skapa en ny fil - du skall fortfarende
    # inkludera "/o1code.php"
    # om du bara tar copy/paste varje gång
    # så får du problem (skyll dig själv)
    
include_once( dirname ( __FILE__ ) . "/o1code3.php" );
    
    
# med den katalogstruktur som er övning har
    # kan du även skriva
    # $länkFilen = "links.txt" ;
    # med min struktur måste jag skriva lite annorunda
    
$länkFilen = dirname ( __FILE__ ) . "/links.txt" ;
?>
<html>
<head>
<title>Mina länkar</title>
<meta    http-equiv="Content-Type"
        content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">

<?php
    
# använd funktionen i den inkuderade filen
    # och visa dess resutat
    
echo visaLänkarna( $länkFilen );
?>

</body>
</html>
Listning 2.8.2.2 - samples/o1_3.php

Mina länkar
URLFörklaringBetygTitel
Resultat av listning 2.8.2.2

Att fundera på:

Observera att när du klickar på länkarna i tabellen kommer ?SORT=x att sättas till arderssen

ovn1_4.php

2.3.3 Sortera - steg 2

Sidans tema: uasort, referens, $HTTP_GET_VARS , strcasecmp

 

Modifiera o1code.php

Öppna o1code.php och ändra den på följande sätt

<?php
    
# NYA ----------------------------------------------
    
    # funktion som sorterar arrayen
    # observera & tecknet som gör att
    # arrayen sänds med referens
    # och modifieras "in-place"
    
function minSortering( &$arrayen )
    {    
        
# Kolla om det fanns en sortering i adressraden
        
global $HTTP_GET_VARS;
        if ( isset (
$HTTP_GET_VARS["SORT"] ) )
        {
            
$sorteringsNyckel = $HTTP_GET_VARS["SORT"];
        }
        else
        {
                
# default sortering är enligt url
                
$sorteringsNyckel = "url" ;
        }
        
# sortera enligt angiven nyckel
        # det vi i praktiken sände via URL var vilken
        # funktion vi skulle använda för sortering
        
uasort( $arrayen, $sorteringsNyckel );
    }

    
# funktion som sorterar enligt url
    
function url( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[0], $rightArray[0] );
    }
    
    
# funktion som sorterar enligt description
    
function description( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[1], $rightArray[1] );
    }
    
    
# funktion som sorterar enligt rating
    
function rating( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[2], $rightArray[2] );
    }

    
# funktion som sorterar enligt title
    
function title( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[3], $rightArray[3] );
    }
    
# SLUT PÅ NYA --------------------------------------

    # en funktion som visar innehållet i
    # länklistan
    # parameter: namnet på filen
    
function visaLänkarna ( $filnamn )
    {
        global
$HTTP_SERVER_VARS;
        
$filen = $HTTP_SERVER_VARS["PHP_SELF"];
        
        
# öppna filen och sätt allt in i en array
        
$allt = file( $filnamn  );
        
        
# NYTT ---------------------------------------------
        
minSortering( $allt );
        
# SLUT PÅ NYTT -------------------------------------
        
        # vi skall returnera en komplett HTML-tabell
        
$result = "<table border=\"1\">";    
        
        
$result .= "<tr>";
        
$result .= "<td><a href=\"$filen?SORT=url\">URL</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=description\">Förklaring</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=rating\">Betyg</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=title\">Titel</a></td>";
        
$result .= "</tr>";

        
# loopa genom arrayen allt
        # raden kommer att vara en rad i filen
        
foreach( $allt as $raden )
        {
            
# plocka ut ut de enskilda fälten
            # explode skapar en array och
            # list skapar enskilda variabler av arrayen
        
list($url, $description, $rating, $title ) = explode ( "\t", $raden );
            
            
# plocka ihop såval tabellen men också "a href"
            
$result .= "<tr><td><a href=\"$url\">$url</a></td>";
            
$result .= "<td>$description</td>";
            
$result .= "<td>$rating</td>";
            
$result .= "<td>$title</td></tr>";
        }

        
# avsluta tabellen
        
$result .= "</table>";

        
# returnera den genererade tabellen
        
return $result;
    }
?>
Listning 2.8.3.1 - samples/o1code4.php

Resultat av listning 2.8.3.1

Du behöver inte göra några ändringar i links.php

<?php
    
# jag måste skapa en ny fil - du skall fortfarende
    # inkludera "/o1code.php"
    # om du bara tar copy/paste varje gång
    # så får du problem (skyll dig själv)
    
include_once( dirname ( __FILE__ ) . "/o1code4.php" );
    
    
# med den katalogstruktur som er övning har
    # kan du även skriva
    # $länkFilen = "links.txt" ;
    # med min struktur måste jag skriva lite annorunda
    
$länkFilen = dirname ( __FILE__ ) . "/links.txt" ;
?>
<html>
<head>
<title>Mina länkar</title>
<meta    http-equiv="Content-Type"
        content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">

<?php
    
# använd funktionen i den inkuderade filen
    # och visa dess resutat
    
echo visaLänkarna( $länkFilen );
?>

</body>
</html>
Listning 2.8.3.2 - samples/o1_4.php
[Visa i separat fönster]

 

ovn2_1.php

2.3.4 Kontroll

Sidans tema: fopen, file, fsockopen, HTTP protokollet

 

Skulle det inte vara bra om man kunde kolla om sidorna finns kvar och när de ändrats om de finns kvar? OK, lets do it!

Skapa en fil med namet checklinks.php

Sätt den i samma katalog som de övriga och sätt in följande:

<?php
    
function kollaLänkarna ( $filnamn )
    {
        
# öppna filen och sätt allt in i en array
        
$allt = file( $filnamn  );
        
# filen har redan stängts
        
        # öppna upp filen för skrivning
        
$fp = fopen( $filnamn, "w+" );

        
# lås filen så att andra kan läsa men inte skriva
        
flock( $fp, 1 );
        
        
# loopa genom arrayen allt
        
foreach( $allt as $raden )
        {
            list(
$url, $description, $rating, $title ) = explode ( "\t", $raden );
            
            
# plocka ut servernamn respektive filnamn ur url:n
            # sätt dem in i en array där $matches[1] är servern
            # och $matches[2] är sidan (om någon)
            
preg_match( "/http:\/\/([^\/]*)\/(.*)/", $url, $matches );
            
            
# skapa en tom header för reslutatet
            
$headerdata = array();
            
            
# kolla om sidan finns
            # om funktionen returnerar true kommer
            # $headerdata att fyllas med headerns data
            # i annat fall kommer $headerdata["Status"] att
            # innehålla orsaken till felet
            
if ( kontaktaServern( $matches ,$headerdata ) )
            {
                
# skapa en tabseparerad rad
                
$nyrad =  $url . "\t";
                
$nyrad .= $description. "\t";
                
$nyrad .= $rating . "\t";
                
$nyrad .= trim($title) . "\t";
                
$nyrad .= $headerdata["Date"] ."\r\n" ;
            }
            else
            {    
                
# skapa en tabseparerad rad
                
$nyrad = $url . "\t";
                
$nyrad .= $description. "\t";
                
$nyrad .= $rating . "\t";
                
$nyrad .= trim($title) . "\t";
                
$nyrad .= $headerdata["Status"] . "\r\n";
            }
            
# skriv den tabseparerade raden till links.txt
            
fputs( $fp, $nyrad );
        }
        
        
# tag bort fillåsningen
        
flock( $fp, 3 );
        
        
# stäng filen
        
fclose( $fp );
        
    }
    
    
# funktion som kollar om en server är vid liv och om sidan
    # finns
    # första parametern är en array med servernamnen
    # och file (inklusive path)
    # andra är en *referens* till en array som kommer att användas för
    # resultat-rapportering
    
function kontaktaServern( $data , &$resultat )
    {
        
$server = $data[1];
        
# det finns kanske inte alltid ett andra element
        # i arrayen - därav @
        
$file  = "/" . @ $data[2];

        
# prova öppna porten
        
$fp = fsockopen (
                        
$server,    # adressen - ip går också
                        
80,            # port. 80 = HTTP
                        
$errno,        # för eventuella felnummer
                        
$errstr,    # eventuella felmeddelanden
                        
20            # timeout tid innan vi skall ge upp
                        
);

        
# gick det inte att öppna ?
        
if ( !$fp )  
        {
            
# Sätt felmeddelande om inte det gick
            
$resultat["Status"] = "Servern död";
            
# och returnera false
            
return false;
        }  
        else  
        {
            
# skapa ett normalt HTTP GET kommando
            # observera att en den alltid måste sluta
            # med \r\n\r\n (två CRLF)

            
$command = "GET $file ";
            
$command .= "HTTP/1.0\r\n";
            
$command .= "Host: $server\r\n\r\n";
        
            
# sänd detta
            
fputs ( $fp, $command );
                 
            
# läs första raden
            
$row  = fgets ( $fp, 4096 );

            
# ett normalt status medelande innehåller alltid 200
            # alla andra nummer visar på fel - t.ex att sidan inte finns
            # Vanliga meddelandenummer
            #        200 - OK
            #        301 - Moved Permanently
            #        302 - Moved Temporarily
            #        400 - Bad Request
            #        401 - Unauthorized
            #        402 - Forbidden
            #        404 - Not found
            #        500 - Internal server error
            
            
if ( ! ( strpos ( $row, "200" ) > 0 ) )
            {
                
$resultat["Status"] = "Sidan finns inte";
                return
false;
            }

            
# läs vidare tills headern är slut
            
while ( trim( $row ) != "" AND ( !feof( $fp ) ) )
            {
                
$row  = fgets ( $fp, 4096 );

                
# tag bort nedanstående kommentarstecken # om du vill
                # se vad som egentligen händer.
                # echo "$row <br />";

                # Headern från min server innehåller bland annat
                # Server: Microsoft-IIS/5.0
                # Date: Thu, 28 Feb 2002 14:52:40 GMT
                # Connection: Keep-Alive
                # Content-Length: 10168
                # Content-Type: text/html
                
                # observera att det alltid är ett kolon i raden

                
if (strpos ( $row, ":") > 0 )
                {
                    
# plocka ut det före kolon och det efter kolon
                    
list( $header, $content ) = explode ( ":", $row );
                    
                    
# kolla om det var date
                    # konvertera från GMT datum til en dateserial
                    
if ( strcasecmp( trim( $header ), "Date" ) == 0 )
                        
$content = strtotime( $content ) ;
                    
# sätt in detta i resultat arrayen
                    
$resultat[ trim( $header ) ] = trim ( $content );
                }
            }
    
            
# stäng porten
            
fclose ( $fp );
            
            
# kom vi ända hit måste väl allt vara ok
            
return true;
        }
    }
?>
Listning 2.8.4.1 - samples/checklinks.php

Resultat av listning 2.8.4.1

Ändra lite i o1code.php

<?php

    
    
# funktion som sorterar arrayen
    # observera & tecknet som gör att
    # arrayen sänds med referens
    # och modifieras "in-place"
    
function minSortering( &$arrayen )
    {    
        
# Kolla om det fanns en sortering i adressraden
        
global $HTTP_GET_VARS;
        if ( isset (
$HTTP_GET_VARS["SORT"] ) )
        {
            
$sorteringsNyckel = $HTTP_GET_VARS["SORT"];
        }
        else
        {
                
# default sortering är enligt url
                
$sorteringsNyckel = "url" ;
        }
        
# sortera enligt angiven nyckel
        # det vi i praktiken sände via URL var vilken
        # funktion vi skulle använda för sortering
        
uasort( $arrayen, $sorteringsNyckel );
    }

    
# funktion som sorterar enligt url
    
function url( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[0], $rightArray[0] );
    }
    
    
# funktion som sorterar enligt description
    
function description( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[1], $rightArray[1] );
    }
    
    
# funktion som sorterar enligt rating
    
function rating( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[2], $rightArray[2] );
    }

    
# funktion som sorterar enligt title
    
function title( $left, $right )
    {
            
$leftArray = explode ( "\t", $left );
            
$rightArray = explode ( "\t", $right );
            return
strcasecmp( $leftArray[3], $rightArray[3] );
    }


    
# en funktion som visar innehållet i
    # länklistan
    # parameter: namnet på filen
    
function visaLänkarna ( $filnamn )
    {
        global
$HTTP_SERVER_VARS;
        
$filen = $HTTP_SERVER_VARS["PHP_SELF"];
        
        
# öppna filen och sätt allt in i en array
        
$allt = file( $filnamn  );


        
minSortering( $allt );
        
        
# vi skall returnera en komplett HTML-tabell
        
$result = "<table border=\"1\">";    
        
        
$result .= "<tr>";
        
$result .= "<td><a href=\"$filen?SORT=url\">URL</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=description\">Förklaring</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=rating\">Betyg</a></td>";
        
$result .= "<td><a href=\"$filen?SORT=title\">Titel</a></td>";
        
$result .= "</tr>";

        
# loopa genom arrayen allt
        # raden kommer att vara en rad i filen
        
foreach( $allt as $raden )
        {
            
# plocka ut ut de enskilda fälten
            # explode skapar en array och
            # list skapar enskilda variabler av arrayen
            
            # ÄNDRAD ---------------------------------------------
            
list($url, $description, $rating, $title, $status ) = explode ( "\t", $raden );
            
# SLUT PÅ ÄNDRAD -------------------------------------
            
            # NY -------------------------------------------------
            
if ( intval ( $status ) != 0 )
            {
                
$status = "Senast ändrad : " . date("d.m.Y", trim( $status )  );
            }
            
# SLUT PÅ NY ----------------------------------------

            # plocka ihop såval tabellen men också "a href"
            
$result .= "<tr><td><a href=\"$url\">$url</a></td>";
            
$result .= "<td>$description</td>";
            
$result .= "<td>$rating</td>";
            
$result .= "<td>$title</td></tr>";
            
            
# NY -------------------------------------------------
            
$result .= "<tr><td colspan=\"4\">$status</td></tr>";
            
# SLUT PÅ NY ----------------------------------------
        
}

        
# avsluta tabellen
        
$result .= "</table>";

        
# returnera den genererade tabellen
        
return $result;
    }
?>
Listning 2.8.4.2 - samples/o2code1.php

Resultat av listning 2.8.4.2

Ändra lite i links.php

<?php
    
    
# NY -------------------------------------------------
    
include_once( dirname ( __FILE__ ) . "/checklinks.php" );
    
# SLUT PÅ NY -----------------------------------------

    # du skall fortfarande inkludera o1code.php
    
include_once( dirname ( __FILE__ ) . "/o2code1.php" );
    
$länkFilen = dirname ( __FILE__ ) . "/links.txt" ;
?>
<html>
<head>
<title>Mina länkar</title>
<meta    http-equiv="Content-Type"
        content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">

<?php
    
    
# NY -------------------------------------------------
    
kollaLänkarna ($länkFilen );
    
# SLUT PÅ NY -----------------------------------------

    
echo visaLänkarna( $länkFilen );
    
?>

</body>
</html>
Listning 2.8.4.3 - samples/o2_1.php

Mina länkar
Warning: fopen(/home/vhome/enges.org/www/phpkurs/samples/links.txt) [function.fopen]: failed to create stream: Permission denied in /home/vhome/enges.org/www/phpkurs/samples/checklinks.php on line 9

Warning: flock(): supplied argument is not a valid stream resource in /home/vhome/enges.org/www/phpkurs/samples/checklinks.php on line 12

Warning: flock(): supplied argument is not a valid stream resource in /home/vhome/enges.org/www/phpkurs/samples/checklinks.php on line 55

Warning: fclose(): supplied argument is not a valid stream resource in /home/vhome/enges.org/www/phpkurs/samples/checklinks.php on line 58
URLFörklaringBetygTitel
Resultat av listning 2.8.4.3

 

din2.php

2.3.5 Din uppgift

  1. UPPGIFT 2:
    Content-Length i HTTP headern (se föregående sidas kod) säger hur stor filen är. Se till att detta visas i KB och med 2 decimaler i tabellen. Sök fram info om number_format samt övriga behövliga funktioner.
    OBS! Efter att funktionen kontaktaServern har blivit körd så kommer $headerdata["Content-Length"] att innehålla sidans storlek... (kanske)

    Beräknad tidsåtgång: ca. 0,5h.

  2. UPPGIFT 3:
    Ändra programmet så att det i tabellen visas

    +
    om sidan finns
    - om sidan inte finns
    ? om servern inte svarade

    Se till att detta visas före filens namn i tabellen, och se till att det bara visas en rad per länk.

    Beräknad tidsåtgång: ca. 1h.

  3. UPPGIFT 4:
    Att ge fulla rättigheter åt alla med chmod 777 i Linux, eller fulla rättigheter åt IUSR_SERVERNAMN i Windows är inte så god idé. Ändra programmet så att länkfilen läggs i en annan katalog än php-filerna (t.ex. data).
    Vilka är de mest restriktiva rättigheter du kan ge åt katalogen som innehåller links.txt samt links katalogen där dina PHP-filer finns. Programmet skall fungera, men inte mer...
    Tips. tag en titt på chmod funktionen

    Beräknad tidsåtgång: ca. 1h.

  4. UPPGIFT 5:
    På föregående sida fanns programkod som automatiskt uppdaterade länkfilen när sidan laddades. Ändra om sidan så att du sätter en länk i början av sidan:
    <a href="links.php?REFRESH=true">Kontrollera alla länkar</a>

    Ändra PHP-koden så att kollaLänkarna funktinen endast körs om REFRESH=true fanns i adressraden. Använd isset och $HTTP_GET_VARS...

    Beräknad tidsåtgång: ca. 0,5h.

  5. UPPGIFT 6:
    Skapa en skild PHP sida. Kalla den insertlink.php Denna sida skall innehålla en form med:
    1. En textbox för URL (adress)
    2. En combobox som skall innehålla siffrorna 1 till 5 för betyget på sidan
    3. En textbox för en kort förklaring över vad detta är för slags sida
    4. En Submit knapp

    När du skrivit in något och submittat skall det du skrivit sättas in i slutet av links.txt på samma sätt som de övriga raderna, med tab mellan de enskilda uppgifterna.
    Tips: tag en till på fopen, flock och fputs

    Beräknad tidsåtgång: ca. 1h.

  6. EXTRA UPPGIFT FÖR DEN SOM VILL STILA LITE:
    På sidan strings_reg_ex.php visas kod som öppnar en websida och (bland annat) hämtar titeln från sidan. Du kanske lade märke till att formen i ovanstående uppgift inte hade någon textbox för titel. (Jag hoppas du beaktade detta i koden.)
    Skapa en funktion som får en URL som parameter och som returnerar sidans titel (om någon).
    Använd denna funktion i samband med skrivning till länkfilen, så att titel kommer automatiskt.