Prosty system newsów w PHP – to nie takie trudne 37

Logo PHPW dzisiejszym artykule przedstawię Wam, jak stworzyć bardzo prosty, lecz mocno konfigurowalny system newsów PHP. A dlaczego PHP? Właśnie dlatego, że łatwiej się modyfikuje wygląd i układ strony, a do tego nie trzeba ruszać się z przeglądarki, aby dodać nowy artykuł! Nie jest to trudna rzecz, zwłaszcza gdy mamy serwer PHP z MySQL i trochę wiedzy dotyczącej PHP, MySQL i trochę HTML-a  i CSS-a.

Teraz wytłumaczę działanie strony. Do tego stworzymy pliki:

  • news.php – tutaj zostanie wyświetlony cały artykuł;
  • nowe.php – lista kilku najnowszych newsów na stronie wraz z krótkim wstępem;
  • archiwum.php  – lista wszystkich artykułów na stronie;
  • dodaj.php – skrypt dodający artykuł do bazy danych;
  • polacz.php – łączymy się z bazą oddzielnie dla uniknięcia problemów (wszystko w jednym pliku).

Musimy zacząć od stworzenia bazy danych, czyli w tym wypadku wystarczy jedna tabelka. Otwieramy PhpMyAdmin i tworzymy nową bazę danych – newsy, artykuly, nazwij jak Ci się podoba. Moja nazwa to news. Pamiętaj o zmianie rozpoznawania znaków na utf-8 polish. Teraz robimy nową tabelę. Musimy się zastanowić, jakie pola będą w naszej bazie. Na sam początek oferuję:

  • id (obowiązkowo);
  • nazwa;
  • autor;
  • data;
  • treść.

Wiadomo, później w ramach modyfikacji możesz dodać inne przydatne, ale na razie się nie rozpisuję. Zaczynamy tworzyć tabelkę, abyś nie tracił czasu, możesz skopiować i wkleić  do zakładki SQL w bazie danych kod poniżej.

CREATE TABLE `news` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`nazwa` VARCHAR( 30 ) NOT NULL ,
`data` DATETIME NOT NULL ,
`autor` VARCHAR( 15 ) NOT NULL ,
`tresc` LONGTEXT NOT NULL
) ENGINE = MYISAM ;

Masz już bazę danych, teraz musisz przystąpić do tworzenia (a raczej skopiowania). Zaczniemy od pliku polacz.php. Stwórz plik i otwórz go w jakimkolwiek programie. Na koniec zapisz to w nowym folderze (np. htdocs\newsy dla XAMPPa, czy nazwausera/public_html dla LAMPa w Linuksie).

<?php
mysql_connect('1', '2' , '3');
mysql_select_db("4");
mysql_query("SET NAMES 'utf8'");
?>

  1. Wpisujemy nazwę hosta bazy, w przypadku serwera lokalnego localhost;
  2. Użytkownik bazy danych, domyślnie root;
  3. Tutaj wpisz swoje hasełko do bazy;
  4. Wpisz nazwę bazy danych, u mnie news.

Mając już ten plik możemy od razu przejść do skryptów wyświetlania. Zanim to zrobisz, spróbuj stworzyć kilka przykładowych newsów (np. o nazwie „aaaaaaaaaa” i treści np. kilka akapitów Lorem Ipsum). Najpierw, po zrobieniu kilku (u mnie 13) artykułów, zrobimy listę pięciu najnowszych. Zapisz to jako nowe.php.

<?php
include("polacz.php"); // 1
$query = mysql_query("select * from news order by id desc limit 0,5"); // 2
while($rekord = mysql_fetch_array($query))
{
$naz .= '<li><a href="news.php?id='.$rekord[0].'">'.$rekord[1].'</a> Autor: '.$rekord[3].' - '.$rekord[2].'</li>'; // 3
}
echo '<ul>'.$naz.'</ul>'; // 4
?>

Teraz możesz zobaczyć efekt. Wejdź w localhost/newsy/nowe.php, a zobaczysz coś niesamowitego: Najnowsze pięć newsów! Wprawdzie linki jeszcze nie działają, ale o tym za chwilę. Teraz trochę nauki (jeśli nie chcesz tego czytać, to przewiń dalej):

  1. Łączymy się z bazą za pomocą polacz.php;
  2. Zapytanie do bazy (wybierz wszystkie pola z tabeli news sortując według id, biorąc tylko pierwsze 5 – proste, prawda?);
  3. Przetwarzamy i formatujemy każdy rekord z bazy;
  4. Wyświetlamy wszystkie wyniki.

Jeszcze zanim napiszę o wyświetlaniu newsa, opowiem o archiwum newsów. Wyświetla on wszystkie newsy ze wszystkich lat. Kod zapytania do bazy danych i wyświetlania jest praktycznie taki sam, tylko bez desc limit:

<?php
include("polacz.php");
$query = mysql_query("select * from news order by id");
while($rekord = mysql_fetch_array($query))
{
$naz .= '<li><a href="news.php?id='.$rekord[0].'">'.$rekord[1].'</a> Autor: '.$rekord[3].' - '.$rekord[2].'</li>';
}
echo '<ul>'.$naz.'</ul>';
?>

Zapisujemy jako archiwum.php, otwieramy w przeglądarce i mamy wszystkie artykuły. I wreszcie – najważniejsze, czyli skrypt wyświetlający newsa.

<?php
include("polacz.php");
$query = mysql_query("select * from news where id='".(int)$_GET['id']."'"); // 1
$rekord = mysql_fetch_array($query);
echo '<h1>'.$rekord[1].'</h1>Autor: '.$rekord[3].'<br/>Data: '.$rekord[2].'<p>'.$rekord[4].'</p>'; // 2
?>

I jak zwykle analiza.

  1. Znowu mamy styczność z zapytaniem do bazy danych. W tym przypadku: wybierz wszystko z tabeli news, gdzie id równa się zmiennej pobranej z linka strony (tutaj np. news.php?id=10).
  2. Do wyświetlenia jednego newsa nie potrzeba żadnej pętli, ponieważ jest pobierany z bazy tylko jeden rekord. Jak widać dołożyłem bardzo proste formatowanie (nagłówek).

Możesz zapisać plik jako news.php. Teraz otwórz w przeglądarce nowe.php i wejdź w jakiś link. Zobaczysz treść newsa (nieciekawą zapewne). Pod koniec przedstawię skrypt tworzenia newsów tak, byś nie musiał co chwilę wchodzić do PhpMyAdmin. Przed Tobą skrypt z formularzem dodaj.php:

<form action="" method="post">
tytuł: <input type="text" name="tytul">
<br/>autor <input type="text" name="autor">
<br/>treść <textarea name="tresc" rows="20" cols="50"></textarea>
<br/><input type="submit" value="Dodaj"></form>
<?php
include("polacz.php");
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$query = mysql_query("insert into news values('','".$_POST['tytul']."',now(),'".$_POST['autor']."','".$_POST['tresc']."')");
}
?>

Spróbuj stworzyć newsa dzięki temu skryptowi i sprawdź, czy na pewno wszystko jest dobrze zrobione! Nie robiłem tego dla zgodności z W3C, bo to sam musisz zadbać, ale dla pokazania, że nie jest to trudne, a wręcz przeciwnie – banalnie proste.

Na sam koniec, dodamy pierwszą modyfikację do pliku nowe.php, która wyświetla pierwsze 150 pierwszych znaków z pola tresc. Stwórz plik skrot.php i wklej poniższy kod:

<?php
if (substr($rekord[4], 0, 150)<$rekord[4]) // 1
{
$kr = '...'; //
}
else
{
$kr = '';
}
?>

Jeżeli pierwsze 150 znaków z pola treść jest mniejsze od całego pola treść to wyświetlony na końcu skrótu wielokropek. Zmodyfikuj jeszcze skrypt wyświetlania kawałka newsa w pliku nowe.php. Po prostu zamień zawartość starej pętli while na taką:

include("skrot.php");
$naz .= '<li><a href="news.php?id='.$rekord[0].'">'.$rekord[1].'</a>Autor: '.$rekord[3].' - '.$rekord[2].'<p>'.substr($rekord[4], 0, 150).''.$kr.'</p></li>';

Teraz, gdy masz już gotowy system newsów, spróbuj usprawnić działanie Twojej nowej strony, modyfikując ją:

  1. Stwórz szablon z użyciem poprawnego XHTML i CSS.
  2. Dodaj dodawanie newsów na login i hasło.
  3. Stwórz konta autorów, którzy sami będą mogli tworzyć artykuły bez konieczności wpisywania nazwy autora.
  4. Dodaj system oceniania w skali pięciostopniowej bazujący na sesjach.
  5. Utwórz system komentowania artykułów z kontrolą antyfloodową i antybotową (captcha?).
  6. Napisz własny panel administratora.
  7. Dołóż do tego kategorie wpisów.

I wtedy Twoja strona będzie piękna i funkcjonalna, prawie jak WordPress ;). Ale jeszcze musisz pamiętać o samej treści tych newsów, które tak naprawdę są najistotniejsze na stronach!

  • tomekby

    Nawet fajnie :)
    Nie testowałem, ale wierzę, że działa, tylko że mam kilka zastrzeżeń:
    1. while($rekord = mysql_fetch_array($query))
    {
    $naz .= '<a href="news.php?id='.$rekord[0].'" rel="nofollow">'.$rekord[1].' Autor: '.$rekord[3].' - '.$rekord[2].''; // 3
    }
    echo ''.$naz.''; // 4

    nie lepiej od razu wyświetlać(echo), a tagi otwierające/zamykające listę wstawić przed i po while? (prawdopodobnie działałoby szybciej)
    2. trzeba uważać na błędy typu SQL Injection (chyba nie chcemy, aby ktoś nam bazę wykasował?):
    $query = mysql_query("insert into news values('','".$_POST['tytul']."',now(),'".$_POST['tytul']."','".$_POST['tresc']."')");
    dane nie są W OGÓLE filtrowane (na szczęście tylko w tym przypadku)
    3. if (substr($rekord[4], 0, 150)<$rekord[4]) // 1 nie szybciej i wygodniej będzie użyć funkcji strlen()?
    4. to w sumie chyba błąd wordpressa: </li> tagi są tu wyświetlone jako encje…
    5. to nie błąd, ale mimo wszystko zapytania powinno się kończyć średnikiem, to samo tyczy się apostrofów, i cudzysłowów – bez nich też działa, ale ich stosowanie jest zalecane poza tym można by było zmienić sam kod SQL na wielkie litery – przejrzyściej wygląda
    6. (ostatni punkt) – zauważyłem, że czcionka zastosowana na stronie nie ma polskich znaków, można by ją zmienić :)

    pozdro

    ps. ten komentarz nie miał być złośliwy, tylko miał pomóc w ulepszeniu artykułu :)

  • Hmm… po Twoim komentarzu sprawdziłem kod i się okazało, że nie miał prawa działać… Teraz powinno być ok.
    3. No fakt, strlen. Ciągle po głowie mi chodził substring i jakoś tak wyszło
    4. Poprawione, wcześniej źle wkleiłem kod.
    5. Już sam nie wiem jak to w końcu robić, bo jedni robią tak, a drudzy tak przez co robię raz dobrze raz źle.
    6. Kolejna pomyłka – apostrofy.
    Ten komentarz wcale nie jest złośliwy, dzięki za zwrócenie uwagi ;)

  • zweit

    do wordpress’a to temu skryptowi tyle, co chińskiej republice ludowej do demokracji, ale od czegoś trzeba zacząć :) Dane do bazy danych polecam wrzucić przez addslashes($_POST….., a przy wyświetlaniu wyciąć backslashe stripslashes($w[‚kolumna….. No i oczywiście sprawdzić czy je przesyłamy, żeby nie było zonka typu kolumna nie może być null, albo jakieś śmieci, nie wspomnę, że przez ten formularz można wywalić całą bazę danych. Dalej, po co gromadzenie zwrotu z selecta do zmiennej ? i później wyświetlanie ? Pseudo templatki ? Może lepiej nQa początek polecam system templatów smarty, łatwy do opanowania dla początkujących, na później zend framework lub symfony.

  • tomekby

    Może lepiej nQa początek polecam system templatów smarty, łatwy do opanowania dla początkujących, na później zend framework lub symfony.

    A weź się wypchaj z tym zendem/symfony :P Są strasznie ciężkie i poooowolne. Jasne, ktoś może powiedzieć: coś za coś, ale nie za TO (tzn. wydajność). Ja wolę coś lżejszego i szybszego (np. kohanaphp), co nie zamuli strony przy czymkolwiek. :)

    A tak btw. to podobno o gustach się nie dyskutuje, więc taki trochę OT mi z tym komentarzem wyszedł…

  • Łukasz Kurowski

    Przez takie skrypty ch*j mnie trafia…jak trzeba edytować… $tablica[0] <- let's go do bazy sprawdzać co to jest -_-
    Nie wiesz, że można używać kolumn jako kluczy ?
    $tablica['title'] ?

  • początkujący

    Witam,
    skorzystałem z rozwiązania, machnąłem poprawki o których była mowa w poprzedzających komentarzach jednak nie daje mi spokoju jeden mały fakt. Czemu po wejściu na stronę dodaj.php tworzy się za każdym razem pusty rekord? Wolałbym jednak by po naciśnięciu submit wysyłało posta którego ja wypełnię. Czyżby autor skryptu przeoczył tą małą kwestię ?

  • początkujący

    Moja propozycja jest taka:

    tytuł:
    autor
    treść

  • Kod został zmodyfikowany.

  • szymoncx12

    Jak ktoś będzie potrzebował oto dodaj.php z zabezpieczeniem na login i hasło:

    <?php

    $login = "login"; // tu wpisz swój login
    $password = "haslo"; // a tu swoje hasło

    if(!isset($_SERVER['PHP_AUTH_USER']) or strcmp($_SERVER['PHP_AUTH_USER'],$login) or strcmp($_SERVER['PHP_AUTH_PW'],$password)) {
    header("WWW-Authenticate: Basic realm=strefa chroniona");
    header("HTTP/1.0 401 Unauthorized");
    die("Brak uprawnień do przeglądania strony");
    }
    else {
    echo "Witaj w strefie chronionej!";
    include("polacz.php");
    if($_SERVER['REQUEST_METHOD'] == 'POST')
    {
    $query = mysql_query("insert into news values('','".$_POST['tytul']."',now(),'".$_POST['autor']."','".$_POST['tresc']."')");
    }
    echo "”;
    echo „tytuł: „;
    echo „autor „;
    echo „treść „;
    echo „”;

    }

    ?>

  • Kubala

    Witam. Nie wiem czy coś zrobiłem nie tak, ale po kliknięciu w link zostaje odesłany do błędu 404 :wink:

  • @Kubala: nie masz pliku news.php

  • Kubala

    @Saibamen Tak, wiem ;) Ogarnąłem chwile po napisaniu komenta.

  • Krzysiek

    A czemu mi w nowe.php wyświetla mi sie:
    Notice: Undefined variable: naz in C:\xampp\htdocs\newsy\nowe.php on line 7
    A w archiwum:
    Notice: Undefined variable: naz in C:\xampp\htdocs\newsy\archiwum.php on line 6
    ???

  • paweo (Paweł)

    A gdzie wpisać nazwę bazy danych :?:

  • paweo (Paweł)

    poradziłem sobie ;-)

  • Kazik

    Wyśmienicie! Od 2 dni czytam o PHP i bazach i próbuję sobie coś robić. Dzięki temu tutkowi sporo zrozumiałem, a końcówka i „I wtedy Twoja strona będzie piękna i funkcjonalna, prawie jak WordPress.” dała mi sporego powera motywacyjnego :) Dzięki i pozdrawiam.

  • Pawel

    Swietny artykul, w prosty sposob pokazany jak zbudowac interesujacy system newsow, w polaczeniu z wiedza jaka posiadam bede mogl zbudowac na prawde ciekawy system, dzieki wielkie :)

  • Jan

    Dzięki wielkie, dzięki temu tutkowi pojąłem w końcu jak robić połączenie z bazą, tak to wcześniej tylko przerabiałem gotowce a teraz nawet wzorując się na twoim przykładzie udało mi się zrobić system logowania i nie tylko, jeszcze raz wielkie dzięki :D

  • @Jan: Cieszę się ogromnie, że artykuł pomaga zgłębiać tajniki programowania w PHP :) Pozdrawiam

  • Slash

    Wszystko fajnie działa oprócz tego skrótu, jak tak robię jak jest napisane to serwer się zawiesza.

    I jeszcze jedno, dlaczego dodaje mi kazdego newsa podwójnie ?

  • Slash

    Naprawiłem to z tym dublowaniem się.

    Tylko mam problem z tym skrótem, czy mógłby ktoś mi wkleić skrtpy „nowe.php” juz z tym skrótem?

    Byłbym bardzo wdzięczny

  • Slash

    Sorki za robienie syfu w komentarzach, sam do tego doszedłem ;D

  • Olek

    Witam! Mam pewien problem, analizuje sobie ten kod krok po kroku, ale sam nie chce działać. Mam w domu postawiony serwer na Linuxie, konkretniej UbuntuServer, oczywiście wszystko na nim gra, strona postawiona, php5 i mysql zainstalowany, ale jak mówię ten skrypt nie chce działać. Czy macie jakieś konkretne sugestie co robię źle??

    P.S. Nie jestem pewien co do zapisu tych plików na Linuxie, mogłby ktoś podać dokładną ścieżkę gdzie owe pliki zapisać??

  • Utwórz plik info.php w htdocs, a w nim kod . Sprawdź czy wyświetli Ci coś jeśli wejdziesz w localhost/info.php w przeglądarce.

  • Olek

    Witam! Chciałem przeprosić, że długo mnie tu nie było, ale byłem poza domem. Wstawiłem prosty skrypt najprostszy z możliwych () do dokładnie tej lokalizacji: /var/www/ i został on wyświetlony poprawnie. Niestety skrypt ze strony nie został wyświetlony :( Naprawdę nwm o co chodzi.

  • Olek

    Dobra, już wszystko sprawne, ale ze mnie osioł :P Trzeba było zmienić uprawnienia bazy i gra ;)

  • cjastek

    Notice to nie błąd. TO tylko informacja dla Ciebie.

  • cjastek

    ID jest ważne!!!

  • Jakub Klimczak

    Może powiedz co zrobić, żeby czas newsów się zgadzał, bo strefa jest GMT, czyli dwie godziny za wcześnie ;)

  • Możesz użyć po prostu date_default_timezone_set(‚Europe/Warsaw’);
    lub dodać do PHP.ini: date.timezone = „Europe/Warsaw”

  • Jakub Klimczak

    Dzięki.

  • Michał

    Mam problem z $kr, wyświetla mi się „Notice: Undefined variable: kr in F:”

  • Dziwne. Powinno pobierać to ze skrot.php.

    Wpakuj ten $kr w isset()

  • Kirik

    Jak ktoś tu jeszcze zagląda prosiłbym o pomoc. mam taki błąd:

    Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /home/u341938778/public_html/newsy/nowe.php on line 4

  • Wyślij cały Twój spakowany kod na jakiś serwer i zapodaj linka

  • Michał

    Mam inny problem, tekst jest wrzucany do bazy ale ucina go w momencie gdy napotka polskie litery. Kiedy zmieniam kodowanie znaków z utf-8 na utf-16 lub 32 wyświetla pełny tekst ale zamiast polskich znaków symbole. O co chodzi?

  • Michał

    Poradziłem sobie z tym, w pliku polacz.php zmieniłem na mysql_query(„SET NAMES ‚utf16′”); a w tabeli takze dalem utf-16.

    Mam za to inny problem:

    Notice: Undefined variable: naz in F:Programywampwwwnowe.php on line 8

    Wygląd pliku nowe.php :

    1 <?php
    2
    3 include("polacz.php"); // 1
    4 $query = mysql_query("select * from news order by id desc limit 0,5"); // 2
    5
    6 while($rekord = mysql_fetch_array($query))
    7 {
    8 $naz.= '‚.$rekord[1].’ Autor: ‚.$rekord[3].’ –
    9 ‚.$rekord[2].”; // 3
    10 }
    11 echo ”.$naz.”; // 4
    12 ?>