RkBlog

Hardware, programming and astronomy tutorials and reviews.

Prosty Blog - Komentarze

Teraz dość nudne zadanie - stworzenie widoku i kontrolera dla dodawania i listowania komentarzy (skopiowanie i edycja kodu Newsów) oraz dodanie do każdego newsa linku do dodania i oglądania komentarzy.
W Kontrolerze Blog mamy jedną metodę listującą newsy. Musimy dodać liczbę komentarzy dla każdego newsa:
<?php
class Blog extends Controller
{
// konstruktor
function Blog()
 {
 parent::Controller();
 $this->response = array();
 }
function index()
 {
 $this->load->model('News');
 $this->load->model('Comments');
 $query = $this->News->get_news();
 $content = '';
 if ($query->num_rows() > 0)
         {
        foreach($query->result() as $item)
                {
                $q = $this->Comments->are_comments_for_news($item->news_id)->result_array();
                $item->comments = $q[0]['comnumber'];
                $content .= $this->load->view('news_loop', $item, True);
                }
        }
 else
        {
        $content = 'Brak newsów';
        }
 $this->response['content'] = $content;
 $this->load->view('index', $this->response);
 }
}
Dla każdego newsa wykonujemy zapytanie i zwracamy wynik do szablonu news_loop:
<h1><?PHP echo $news_title ?></h1>
<p class="date"><?PHP echo date("Y-m-d", $news_date); ?> | <?PHP echo $news_author; ?></p>
<p><?PHP echo $news_text; ?></p>
<p class="date"><B>Słowa Kluczowe</B>: <?PHP echo $news_keywords; ?><BR />
<?PHP
IF($comments == 0)
 {
 echo '<a href="'.site_url('com/add/'.$news_id).'">Dodaj Komentarz</a>';
 }
else
 {
 echo '<a href="'.site_url('com/add/'.$news_id).'">Dodaj Komentarz</a> | <a href="'.site_url('com/show/'.$news_id).'">Zobacz Komentarze ('.$comments.')</a>';
 }
?>
</p>
<div class="rule"></div>
Następnie stworzyłem oddzielny kontroler dla komentarzy, o nazwie Com:
<?php
class Com extends Controller
{
// konstruktor
function Com()
 {
 parent::Controller();
 $this->response = array();
 }
function add()
 {
 $id = $this->uri->segment(3);
 IF(isset($id) and is_numeric($id))
        {
        $data["tytul"] = array('name' => 'tytul');
        $data['tresc'] = array('name' => 'tresc', 'rows' => 5, 'cols' => 50);
        $data['autor'] = array('name' => 'autor');
        
        $rules['tytul'] = "required|max_length[250]|xss_clean";
        $rules['tresc'] = "required|xss_clean";
        $this->validation->set_rules($rules);
        
        if ($this->validation->run() == FALSE)
         {
         $data['tytul']['value'] = $this->input->post('tytul');
         $data['tresc']['value'] = $this->input->post('tresc');
         $data['autor']['value'] = $this->input->post('autor');
         $this->response['content'] = $this->load->view('com_add', $data, True);
         }
        else
         {
         $this->load->model('Comments');
         $this->Comments->add_comment(array('com_title' => $this->input->post('tytul'), 'com_text' => $this->input->post('tresc'), 'com_author' => $this->input->post('autor'), 'com_date' => time(), 'news_id' => $id));
         $this->response['content'] = 'Komentarz Dodany<META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url().'">';
         }
        }
 else
        {
        $this->response['content'] = 'Błędny Link<META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url().'">';
        }
 $this->load->view('index', $this->response);
 }
function show()
 {
 $id = $this->uri->segment(3);
 IF(isset($id) and is_numeric($id))
        {
        $this->load->model('Comments');
        $query = $this->Comments->get_comments_for_news($id);
        $content = '';
        $adm = Com::_check_login();
        if ($query->num_rows() > 0)
         {
         foreach($query->result() as $item)
                 {
                 $item->admin = $adm;
                 $content .= $this->load->view('com_loop', $item, True);
                 }
         }
        else
         {
         $content = 'Brak Komentarzy';
         }
        $this->response['content'] = $content;
        }
 else
        {
        $this->response['content'] = 'Błędny Link';
        }
 $this->load->view('index', $this->response);
 }
function _check_login()
 {
 IF($cookie = $this->input->cookie('cicookie', True))
        {
        return true;
        }
 else
        {
        return false;
        }
 }
}
 ?>
Metody show i add są już nam dobrze znane. Obecna metoda _check_login ma jedynie orientacyjnie sprawdzić czy jesteśmy zalogowani jako admin - potrzebne jest to do wyświetlenia linka kasującego komentarz (który kasowany jest przez metodę kontrolera Admin, który ma pełne sprawdzanie "zalogowania"). Nie dałem tutaj pełnego kodu sprawdzania by nie rozwlekać tego kodu po "całym" skrypcie. $this->input->cookie zwróci True (1) gdy uda mu się odczytać ciacho i na tej podstawie wyświetlamy link w szablonie com_loop:
<?PHP echo $com_title ?>
<p class="date"><?PHP echo date("Y-m-d", $com_date); ?> | <?PHP echo $com_author; ?> | 
<?PHP
IF($admin == 1)
 {
 echo '<a href="'.site_url('admin/com_delete/'.$com_id).'">Skasuj</a>';
 }
?>
</p>
<p><?PHP echo $com_text; ?></p>
<div class="rule"></div>
Szablon com_add wygląda tak:
Dodaj komentarz
<center><?=$this->validation->error_string; ?></center>

<?php echo form_open('com/add/'.$this->uri->segment(3)); ?>
<table width="90%" border="0" cellspacing="3" cellpadding="3">
<tr><td width="180"><B>Tytuł</B></td><td><?php echo form_input($tytul); ?></td></tr>
<tr><td width="180"><B>Treść</B></td><td><?php echo form_textarea($tresc); ?></td></tr>
<tr><td width="180"><B>Autor</B></td><td><?php echo form_input($autor); ?></td></tr>
<tr><td> </td><td><?php echo form_submit('submit', 'Zapisz'); ?></td></tr>
</table>
<?php echo form_close(); ?>

<div class="rule"></div>
Teraz przy newsach mamy link do dowania komentarzy oraz, jeżeli już są - link do ich oglądania:
darmowy hosting obrazków

Każdy może dodawać Komentarze - ochrona przed spamem

Istnieje coś takiego jak Captcha czyli taka mała grafika z jakimś wyrazem, który musimy wpisać poprawnie by formularz przeszedł. Również CI ma wtyczkę generującą taki obrazek. Musimy zmodyfikować metodę add kontrolera Com:
<?php
function add()
 {
 $id = $this->uri->segment(3);
 IF(isset($id) and is_numeric($id))
        {
        $this->load->plugin('captcha');
        $vals = array(
                'img_path'  => './captcha/',
                'img_url'  => 'http://localhost/html/ci/captcha/',
                'font_path'  => './system/texb.ttf',
                'img_width'  => '150',
                'img_height' => 30,
                'expiration' => 1000
         );
        $cap = create_captcha($vals);
        
        $data["tytul"] = array('name' => 'tytul');
        $data['tresc'] = array('name' => 'tresc', 'rows' => 5, 'cols' => 50);
        $data['autor'] = array('name' => 'autor');
        $data['text'] = array('name' => 'text');
        $data['text_ok'] = md5(sha1($cap['word']));
        $data['image'] = $cap['image'];
        
        $rules['tytul'] = "required|max_length[250]|xss_clean";
        $rules['tresc'] = "required|xss_clean";
        $this->validation->set_rules($rules);

        if ($this->validation->run() == FALSE or $this->input->post('text_ok') != md5(sha1($this->input->post('text'))))
         {
         $data['tytul']['value'] = $this->input->post('tytul');
         $data['tresc']['value'] = $this->input->post('tresc');
         $data['autor']['value'] = $this->input->post('autor');
         $this->response['content'] = $this->load->view('com_add', $data, True);
         }
        else
         {
         $this->load->model('Comments');
         $this->Comments->add_comment(array('com_title' => $this->input->post('tytul'), 'com_text' => $this->input->post('tresc'), 'com_author' => $this->input->post('autor'), 'com_date' => time(), 'news_id' => $id));
         $this->response['content'] = 'Komentarz Dodany<META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url().'">';
         }
        }
 else
        {
        $this->response['content'] = 'Błędny Link<META HTTP-EQUIV="Refresh" CONTENT="1; URL='.site_url().'">';
        }
 $this->load->view('index', $this->response);
 }
Oraz widok dodawania komentarza:
[<h1>Dodaj komentarz</h1>
<center><?=$this->validation->error_string; ?></center>

<?php echo form_open('com/add/'.$this->uri->segment(3)); ?>
<table width="90%" border="0" cellspacing="3" cellpadding="3">
<tr><td width="180"><B>Tytuł</B></td><td><?php echo form_input($tytul); ?></td></tr>
<tr><td width="180"><B>Treść</B></td><td><?php echo form_textarea($tresc); ?></td></tr>
<tr><td width="180"><B>Autor</B></td><td><?php echo form_input($autor); ?></td></tr>
<tr><td width="180"><B>Tekst z Obrazka</B></td><td><?php echo form_input($text); echo $image; echo form_hidden('text_ok', $text_ok); ?></td></tr>
<tr><td> </td><td><?php echo form_submit('submit', 'Zapisz'); ?></td></tr>
</table>
<?php echo form_close(); ?>

<div class="rule"></div>
Teraz omawiamy. Kod:
$this->load->plugin('captcha');
$vals = array(
        'img_path'  => './captcha/',
        'img_url'  => 'http://localhost/html/ci/captcha/',
        'font_path'  => './system/texb.ttf',
        'img_width'  => '150',
        'img_height' => 30,
        'expiration' => 1000
 );
$cap = create_captcha($vals);
Tworzy nam owy obrazek. $cap to tablica zawierająca pod kluczem word słowo z obrazka oraz pod kluczem image gotowy tag IMG. Konfiguracja:
'img_path' => './captcha/',
To określa katalog na grafiki generowane przez wtyczkę. Powyższa oznacza katalog "captcha" w głównym katalogu CI. Katalog na grafiki musi mieć chmod 777 lub 666.
'img_url' => 'http://localhost/html/ci/captcha/',
Zawiera adres URL do katalogu z grafikami, zmień na poprawny dla ciebie. Reszty nie musimy zmieniać.
Kolejny dodatek to:
$data['text'] = array('name' => 'text');
$data['text_ok'] = md5(sha1($cap['word']));
$data['image'] = $cap['image'];
Dodaliśmy pole o nazwie "text" na tekst z obrazka, pole "text_ok" będzie ukryte i będzie zawierało hasz ze słowa na obrazku. Później sprawdzimy czy hasz wartości wpisanej przez Użytkownika jest identyczny jak z ukrytego pola. Notka: nie można dać w ukrytym polu "czystego" słowa gdyż można byłoby je zobaczyć w źródle strony, co jest marnym zabezpieczeniem. Hasz nic nie da spamerom czy robotom gdyż do poprawnego działania formularza muszą podać "czyste" słowo. Złamanie hasza jest niemożliwe (md5 i sha1 na raz).
if ($this->validation->run() == FALSE or $this->input->post('text_ok') != md5(sha1($this->input->post('text'))))
Sprawdzamy czy słowo się zgadza. Jeżeli albo walidacja zwróci fałsz albo tekst jest niepoprawny - ponownie ładujemy formularz. Skrypt już działa

Bardziej ludzki tekst na rysunku

Obecnie na rysunku mamy 8 znaków złożonych z losowo wybranych cyfr oraz małych i dużych liter. Trudno to odczytać. Musimy niestety edytować kod wtyczki system/plugins/captcha_pi.php. Znajdź:
<?php
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

        $str = '';
        for ($i = 0; $i < 8; $i++)
Zamień na:
<?php

        $pool = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';

        $str = '';
        for ($i = 0; $i < 3; $i++)
Zapisz i gotowe. Teraz tekst na obrazku będzie miał 3 znaki i składać się będzie wyłącznie z cyfr i dużych liter. Wynik:
darmowy hosting obrazków
RkBlog

Kurs Code Igniter, 14 July 2008, Piotr Maliński

Comment article