Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM    Subskrybuj kanał ATOM dla tagu mysql Kanał ATOM (tag: mysql)

Autor wpisu: Śpiechu, dodany: 22.04.2011 08:56, tagi: mysql, php

Dzisiaj szybki wpis dotyczący wyłącznie użytkowników Ubuntu. Nie wkurza Was, że wiecznie musimy używać starej wersji PHP? Natty Narwhal oferuje wersję 5.3.2 (wydana 4.03.2010), a Maverick Meerkat zdaje się 5.3.3 (22.07.2010). Widać nie tylko mnie to denerwowało, dlatego powstało prywatne repozytorium PPA, za pomocą którego PHP ładnie zaktualizuje się do wersji 5.3.6.

Wystarczy w Synapticu dodać źródło

ppa:bjori/php5

Z ważnych rzeczy autor repozytorium dodał lepszy sterownik do bazy Mysql: Mysql Native Driver mysqlnd zamiast libmysql. To w ogóle ciekawe jest jakim cudem w oficjalnych repozytoriach mysqlnd nie został wkompilowany (podobno dostępny w oficjalnych źródłach PHP począwszy od wersji 5.3). Więcej na temat mysqlnd w manualu PHP.

W środowiskach produkcyjnych oczywiście przestrzegam przed takimi repozytoriami. Za to podczas developmentu jak znalazł.

P.S.: Czy ktoś oprócz mnie zauważył, że cichaczem dodali do SplFileInfo metodę getExtension() do 5.3.6?

P.S.2: Zanim weźmie Was cholera z okazji tego, że PDO nie chce łaczyć się z bazą danych po aktualizacji PHP, zalecam zamienić localhost na 127.0.0.1. Szkoda nerwów na święta ;-)

Autor wpisu: Śpiechu, dodany: 16.04.2011 19:16, tagi: php, mysql

Ostatnio mnie ostro zjechaliście. Dzięki za komentarze, szczególnie te negatywne (yyy wszystkie?). Wszystkie starannie przeczytałem. Poczytałem co nieco i zdecydowałem się uderzyć z tematem jeszcze raz. Tym razem uwzględniając zadania takie jak „a co jak będę miał kilka serwerów: testowy, produkcyjny, itp.”, „a co jak chcę połączyć się z dwiema bazami na raz”?

Punktem wyjścia stał się Twittee, czyli kontener stworzony w 2009 r. przez Fabiena Potenciera zajmujący 140 znaków (tyle żeby całość dała się przesłać w postaci pojedynczej wiadomości w serwisie Twitter). Podstawą kontenera jest magia __set() i __get(), czyli to co Zyx lubi najbardziej :-) Całość została przeze mnie mocno zmodyfikowana. Dodałem np. rzucanie wyjątkami jeżeli wymagana wartość nie została ustawiona plus obsługę domknięć w przypadku gdy ustawiona wartość jest funkcją anonimową.

Parę linijek dotyczących ustawienia PDO wcisnąłem do funkcji anonimowej plus dodałem możliwość trzymania pojedynczej instancji PDO w razie potrzeby (zwrócę potem uwagę na static w domknięciu). Obiekt PDO „nie wie”, że jest w kontenerze i dobrze. Istotą DI jest to żeby klas nie trzeba było specjalnie dostosowywać do współpracy z kontenerem.

Obsługę wyjątków w całości zrzucam na klientów nie mieszając kompetencji kontenera, który ma ustawiać/zwracać zmienne/fabrykować obiekty.

class DBContainer {
 
  protected $values = array();
 
  public function __construct() {
        $this->loadDefaults();
  }
 
  protected function loadDefaults() {
    $this->pdo_driver = 'mysql';
    $this->pdo_host = 'localhost';
    $this->pdo_dbname = 'nazwabazy';
    $this->pdo_user = 'user';
    $this->pdo_pass = 'haslo';
    $this->pdo_charset = 'SET NAMES utf8';
    $this->pdo_persist = false;
 
    $this->pdo_getpdo = function(DBContainer $cont) {
 
      // static w kontekscie funkcji anonimowej
      static $persistentPDO;
 
      $pdoCreator = function() use ($cont) {
        if (!extension_loaded('PDO')) throw new Exception('Brak modulu PDO');
        $pdo = new PDO(
                    $cont->pdo_driver . ':host=' . $cont->pdo_host . ';dbname=' . $cont->pdo_dbname,
                    $cont->pdo_user,
                    $cont->pdo_pass,
                    array(PDO::MYSQL_ATTR_INIT_COMMAND => $cont->pdo_charset));
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        return $pdo;
      };
 
      if ($cont->pdo_persist && $persistentPDO instanceof PDO) {
        return $persistentPDO;
      }
      elseif ($cont->pdo_persist) {
        $persistentPDO = $pdoCreator();
        return $persistentPDO;
      }
      else {
        return $pdoCreator();
      }
    };
 
    public function __set($key,$val) {
        $this->values[$key] = $val;
    }
 
    public function __get($key) {
        if (!isset($this->values[$key])) {
            throw new Exception("Wartosc {$key} nie istnieje");
        }
        if ($this->values[$key] instanceof Closure) {
            return $this->values[$key]($this);
        }
        else {
            return $this->values[$key];
        }
    }
}

Przykłady użycia:

$c = new DBContainer();
 
// PDO na domyslnych ustawieniach
$pdo = $c->pdo_getpdo;
 
// przestawiam baze danych
$c->pdo_dbname = 'testowa baza';
$nowePDOdlaBazyTestowa = $c->pdo_getpdo;
 
// znowu przestawiam baze danych, przestawiam na zapis PDO na stale
$c->pdo_dbname = 'baza produkcyjna';
$c->pdo_persist = true;
 
// sprawdzam czy na pewno obiekty PDO sa tej samej instancji
echo spl_object_hash($c->pdo_getpdo) . '<br>' . spl_object_hash($c->pdo_getpdo);
// zwroci taki sam hash

Na raz następny pokażę jak można fajnie korzystać z tego dla obiektów korzystających z pdo wewnętrznie.

Osoby nielubiące magii uprasza się o powstrzymanie od wylewania żalu. Po to zrobili __get(), __set() i dynamiczne typy zmiennych żeby z nich korzystać. Dobra dokumentacja wg mnie załatwia sprawę.

Autor wpisu: Śpiechu, dodany: 10.04.2011 19:54, tagi: php, mysql

Tytuł zabrzmiał jak w Matriksie. Chodzi oczywiście o łączenie aplikacji PHP z bazą danych. Dzisiaj pokażę w jaki sposób w niewielkich projektach radzę sobie z przygotowaniem obiektu PDO do pracy z bazą danych. Trudno żebym w niewielkiej „stronce” zaprzęgał jakiś Zend Framework.

Napisałem sobie dawno temu klasę narzędziową do tworzenia obiektu PDO. Implementuję w niej wzorzec projektowy singleton, a więc mam pewność, że gdziekolwiek w kodzie żądam PDO, zawsze dostaję ten sam obiekt. Jeżeli chodzi o sam singleton, to na jego temat można przeczytać zarówno we Wzorcach Projektowych1 jak i w Design Patterns.2 Zresztą to w Googlu wyskoczy pierdylion wyników ;-)

Używanie klasy jest dziecinnie proste. Należy sobie jednorazowo przeedytować stałe klasy dotyczące połączenia z bazą, a następnie w kodzie wywoływać metodę DBHandler::getPDO()

Poniżej podaję kod klasy. Bierzcie i jedzcie ;-)

<?php
class DBHandlerException extends PDOException {
}
 
/**
 * @author Dawid 'Spiechu' Spiechowicz
 * @license see http://spiechu.pl/o-publikowanym-kodzie/
 */
class DBHandler {
 
  /**
   * Dane bazy danych
   */
  const DB_HOST = 'localhost';
  const DB_NAME = 'nazwa bazy';
  const DB_USER = 'nazwa usera';
  const DB_PASS = 'haslo';
 
  /**
   * Sterownik bazy danych
   */
  const DB_DRIVER = 'mysql';
 
  /**
   * Czy wyswietlac dokladne komunikaty bledow
   */
  const DEBUG_MODE = true;
 
  /**
   * @var PDO singleton PDO
   */
  private static $pdo = null;
 
  /**
   * Zwraca singleton PDO lub wyswietla komunikat bledu i zwraca null.
   * @return PDO|null
   */
  public static function getPDO() {
    try {
      if (self::$pdo === null) {
        self::$pdo = self::createPDO();
      }
      return self::$pdo;
    }
    catch (DBHandlerException $e) {
      echo $e->getMessage();
      return null;
    }
  }
 
  /**
   * @return PDO zwraca nowa instancje PDO
   * @throws DBHandlerException
   */
  private static function createPDO() {
    if (!extension_loaded('PDO')) throw new DBHandlerException('Brak modulu PDO');
    try {
      $pdo = new PDO(
         self::DB_DRIVER . ':host=' . self::DB_HOST . ';dbname=' . self::DB_NAME, 
         self::DB_USER, 
         self::DB_PASS,
         array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
      $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
      return $pdo;
    }
    catch(PDOException $e) {
      if (self::DEBUG_MODE == true) {
        throw new DBHandlerException("Blad bazy danych : {$e->getMessage()}");
      }
      else {
        throw new DBHandlerException('Blad bazy danych');
      }
    }
  }
 
  /**
   * Zapobiega tworzeniu obiektu.
   */
  private function __construct() {
    throw new Exception('Nie mozna stworzyc tego obiektu!');
  }
 
  /**
   * Zapobiega klonowaniu obiektu.
   */
  private function __clone() {
    throw new Exception('Nie mozna klonowac tego obiektu!');
  }
}

Powyżej widać kilka sztuczek. Przede wszystkim konstruktor ma zasięg prywatny, co zapobiega stworzeniu instancji klasy z zewnątrz. Mało tego, próba wywołania go z wnętrza klasy spowoduje wyrzucenie wyjątku. To samo z metodą __clone().

Przy konfiguracji obiektu PDO ustawiam tryb błędów na wyjątki, które wyłapuję i w zależności od ustawionej stałej DEBUG_MODE wyświetlam komunikaty błędów PDO lub nie. Fragment $pdo->query('SET NAMES utf8') ustawia kodowanie znaków na Unicode. Niestety nie znalazłem lepszej metody. Rezultaty zapytań domyślnie będą dostępne w postaci tablicy asocjacyjnej.

  1. E. Gamma (i in.) : Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku. Gliwice : Helion, 2010, s. 130–136.
  2. E. Freeman (i in.) : Head First Design Patterns. Gliwice : Helion, 2005, s. 197–216.

Autor wpisu: Śpiechu, dodany: 07.02.2011 21:41, tagi: mysql, php, zend_framework

Kontynuujemy temat zapytań z poprzedniej części. Punktem wyjścia będzie dla nas tablica wyników zapytania dorzuconego przeze mnie LEFT JOINA (w ramach aktualizacji wpisu na samym dole poprzedniej części). Aby nieco utrudnić dorzuciłem kolejnych dwóch powszechnie znanych idoli młodzieży: Antoniego Macierewicza i Stefana Niesiołowskiego, którzy dla odmiany nie będą mieli swoich ksywek. Ponadto dodałem drugą ksywkę towarzyszowi Tuskowi znanemu często na forach Onetu jako Rudy Oszust.

Reasumując: mamy polityka z dwoma ksywkami, jednego z jedną i dwóch bez ksywek. Dążymy do tego aby wyświetlić na liście rozwijanej formularza ich wszystkich. Zarówno oryginalne imię i nazwisko jak i ksywkę. Co jednak zrobić, skoro ksywka i oryginalne imię i nazwisko posiadają to samo id w bazie? Zamienimy je na unikatowe poprzez dodanie jakiegoś dodatku po oryginalnym id, np. 5–1, 5–2 itd.

Najpierw jednak stworzymy super prosty formularz zawierający pole wyboru typu select i przycisk zatwierdzający zmiany. Potrzebujemy klasy dziedziczącej po Zend_Form. Ja pracując w Zendzie zazwyczaj formularze wrzucam do katalogu forms równoległego do controllers, models itd.

class PolitycyForm extends Zend_Form {
 
   public function init() {
      $this->setMethod('post');
      // gdzie ma zostac wyslany formularz
      $this->setAction('/index/index');
 
      // tutaj wstawić zapytanie
      // z aktualizacji wpisu poprzedniej czesci
 
      $stmt = $select1->query();
      $rowset = $stmt->fetchAll();
 
      $wyniki = array();
      $counter = 1;
 
      foreach ($rowset as $row) {
         // tymczasowo kluczami staja sie wyniki zapytania,
         // a wartosciami id i kolejny numer
         $wyniki[$row['imie_nazwisko']] = $row['id'] . '-' . $counter++;
         // sprawdzamy czy ten ktos ma ksywke,
         // jezeli tak to dorzucamy do wynikow
         if ($row['ksywka'] != null) {
            $wyniki[$row['ksywka'] . ' (' . $row['imie_nazwisko'] . ')'] = $row['id']. '-' . $counter++;
         }
      }
      // nastepnie wszystko to sortujemy po kluczach
      // do poprawnego posortowania polskich znakow
      // uzywamy funkcji setlocale
      setlocale(LC_COLLATE, 'pl_PL.utf8');
      ksort($wyniki, SORT_LOCALE_STRING);
      // i zamieniamy miejscami klucze z wartosciami
      $wyniki = array_flip($wyniki);
 
      $formElement = new Zend_Form_Element_Select('politycy');
      $formElement->setRequired(true)
         // blokujemy tworzenie domyslnego walidatora
         // sprawdzajacego czy wynik jest w formie tablicy
         ->setRegisterInArrayValidator(false)
         ->setLabel('Wybierz swojego ulubionego polityka')
         ->setMultiOptions($wyniki)
         // sprawdzamy czy ktos nie robi psikusa
         ->addValidator(new Zend_Validate_Regex('/^[0-9]+\-[0-9]+$/'));   
      $this->addElement($formElement);
      // dodajemy pole typu submit
      $this->addElement('submit','wybierz');
   }   
}

Po wszystkich zabiegach tablica $wyniki przekazywana do obiektu Zend_Form_Element_Select posiada następującą strukturę:

array(7) {
  ["3-7"] => string(18) "Antoni Macierewicz"
  ["1-3"] => string(11) "Donald Tusk"
  ["2-6"] => string(31) "Jareczek (Jarosław Kaczyński)"
  ["2-5"] => string(20) "Jarosław Kaczyński"
  ["1-4"] => string(25) "Rudy Oszust (Donald Tusk)"
  ["1-2"] => string(27) "Słońce Peru (Donald Tusk)"
  ["4-8"] => string(20) "Stefan Niesiołowski"
}

Teraz pozostaje nam odebrać formularz. Żeby zbytnio nie komplikować dane odbierzemy w kontrolerze IndexController w akcji indexAction(). Na przykład tak:

$politycyForm = new PolitycyForm();
if ($this->_request->isPost()) {
   $dane = $this->getRequest()->getPost();
   if ($politycyForm->isValid($dane)) {
      // wyrzucamy szmelc po wlasciwym identyfikatorze
      $filtr = new Zend_Filter_PregReplace(
         array('match' => '/\-[0-9]+/',
               'replace' => ''));
      $przefiltrowane = $filtr->filter($dane['politycy']);
 
      // wykonujemy dzialania na bazie danych
      // co wykracza poza ramy tego wpisu
 
      // zakladamy, ze istenieje akcja panel-uzytkownika
      return $this->_redirect('/index/panel-uzytkownika');
   }
   else {
      // jezeli formularz nie przechodzi walidacji
      // to zostaje uzupelniony o wprowadzone poprzednio dane
      $politycyForm->populate($dane);
   }
}
// wyswietlamy formularz
$this->view->politycy = $politycyForm;

Możecie zapytać po co nam ten _redirect. Otóż zabezpiecza nas przed ponownym wyświetleniem użytkownikowi formularza i przed ewentualnym ponownym wysłaniem danych.

Jeżeli za szybko z czymś pojechałem, składać zażalenia w komentarzach :-)

Autor wpisu: nospor, dodany: 03.02.2011 20:37, tagi: mysql

Na wielu forach i grupach widzę, iż często w kodzie zapytań tabel jest INT(11). Zdaję sobie sprawę, iż czasami jest to spowodowane skopiowaniem zapytania z jakiegoś programu, który automatycznie nam z jakiegoś powodu coś takiego dodaje. Częściej jednak jest to stosowane przez programistów z premedytacją wynikającą poprostu z niewiedzy. Postaram się tutaj tę sprawę wyjaśnić.

Autor wpisu: Śpiechu, dodany: 24.01.2011 20:10, tagi: mysql, php, zend_framework

Ostatnio w ramach sportów wyczynowych majstruję trochę z zapytaniami do bazy danych w Zendzie. Sprawdzam co można wycisnąć z obiektów Zend_Db_Select. Ten wpis zdecydowałem się podzielić na dwie części. W pierwszej pokażę jak wygenerować dosyć złożone zapytanie do bazy danych za pomocą kilku obiektów Zend_Db_Select, a w drugiej zajmiemy się stworzeniem formularza i odebraniem danych.

Naszym celem będzie utworzenie alfabetycznej listy polityków, których wszyscy lubimy wraz z ich powszechnie znanymi pseudonimami, np.

<select>
<option value="1">Donald Tusk</option>
<option value="2">Jareczek (Jarosław Kaczyński)</option>
<option value="3">Jarosław Kaczyński</option>
<option value="4">Słońce Peru (Donald Tusk)</option>
</select>

Najpierw musimy mieć skąd brać naszych wybrańców narodu. Stworzymy sobie bazę danych mniej więcej taką: Obrazek bazy danych polityków zrobiłem fajnym narzędziem online WWW SQL Designer. Schemat jest oczywiście maksymalnie uproszczony. Nie czepiać się, że imiona i nazwiska trzymam w jednym polu. Chodzi nam o relację jeden polityk ma wiele pseudonimów. Macie poniżej trochę kodu SQL wyeksportowanego przez phpMyAdmin plus kilka przykładowych wartości.

CREATE TABLE IF NOT EXISTS `politycy` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `imie_nazwisko` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='tabela zawierajaca imiona i nazwiska politykow' AUTO_INCREMENT=3 ;
 
INSERT INTO `politycy` (`id`, `imie_nazwisko`) VALUES
(1, 'Donald Tusk'),
(2, 'Jarosław Kaczyński');
 
CREATE TABLE IF NOT EXISTS `politycy_ksywki` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ksywka` varchar(20) NOT NULL,
  `polityk_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `polityk_id` (`polityk_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='zawiera popularne pseudonimy politykow' AUTO_INCREMENT=3 ;
 
INSERT INTO `politycy_ksywki` (`id`, `ksywka`, `polityk_id`) VALUES
(1, 'Słońce Peru', 1),
(2, 'Jareczek', 2);
 
ALTER TABLE `politycy_ksywki`
  ADD CONSTRAINT `politycy_ksywki_ibfk_1` FOREIGN KEY (`polityk_id`) REFERENCES `politycy` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Następnie spróbujemy sobie wygenerować dosyć spore zapytanie SQL, które za jednym zamachem wypisze wszystkich polityków, wszystkie pseudonimy i dodatkowo w nawiasie wypisze którego polityka który pseudonim dotyczy. Wszystko oczywiście w Zend Framework.

// adapter bazy umieszczony w rejestrze
$dbAdapter = Zend_Registry::get('db');
$select1 = $dbAdapter->select()
   // podstawowa tabela z politykami
   ->from(array('p' => 'politycy'),
          // ktore pola (lacznie z aliasem)
          array('p.id','p.imie_nazwisko'));
// podzapytanie dla ksywek
$subSelect = $dbAdapter->select()  
   ->from(array('pp' => 'politycy'),
          array('pp.imie_nazwisko'))
   // warunek dla podzapytania
   ->where('pp.id = pk.polityk_id')
   // powinno przyspieszyc duze bazy
   ->limit(1);
$select2 = $dbAdapter->select()
   // tabela z ksywkami
   ->from(array('pk' => 'politycy_ksywki'),
          array('pk.polityk_id', 
                // Zend_Db_Expr konieczny przy wywolywaniu funkcji SQL
                new Zend_Db_Expr("CONCAT(pk.ksywka, ' (', ({$subSelect}) , ')')")));
$selectUnion = $dbAdaptery->select()
   // konstruujemy zapytanie typu union
   ->union(array($select1, $select2))
   // szeregujemy wyniki
   ->order('imie_nazwisko ASC');
$stmt = $select->query();
$rowset = $stmt->fetchAll();

Powyższy kod stworzył niczego sobie zapytanie:

SELECT `p`.`id`, `p`.`imie_nazwisko` FROM `politycy` AS `p` UNION SELECT `pk`.`polityk_id`, CONCAT(pk.ksywka, ' (', (SELECT `pp`.`imie_nazwisko` FROM `politycy` AS `pp` WHERE (pp.id = pk.polityk_id) LIMIT 1) , ')') FROM `politycy_ksywki` AS `pk` ORDER BY `imie_nazwisko` ASC

Zmienna $rowset zawiera wynik zapytania w postaci tablic:

array(4) {
  [0] => array(2) {
    ["id"] => string(1) "1"
    ["imie_nazwisko"] => string(11) "Donald Tusk"
  }
  [1] => array(2) {
    ["id"] => string(1) "2"
    ["imie_nazwisko"] => string(31) "Jareczek (Jarosław Kaczyński)"
  }
  [2] => array(2) {
    ["id"] => string(1) "2"
    ["imie_nazwisko"] => string(20) "Jarosław Kaczyński"
  }
  [3] => array(2) {
    ["id"] => string(1) "1"
    ["imie_nazwisko"] => string(27) "Słońce Peru (Donald Tusk)"
  }
}

Na koniec uwaga: obiekty typu Zend_Db_Select są przydatne tylko wtedy, gdy nasze zapytanie nie ma charakteru stałego, tzn. różne czynniki wpływają na jego kształt, przez co musi być tworzone w locie. Jeżeli wiemy, że zapytanie zawsze będzie takie samo to jest to zwykłe marnotrawstwo zasobów serwera, aczkolwiek ładnie wygląda i szybko się pisze.

Autor wpisu: widmogrod, dodany: 23.01.2011 20:06, tagi: php, mysql

Nie opiszę całości instalacji gdyż już w wielu źródłach jest opisana szczegółowo. Przedstawię tylko szybkie rozwiązanie problemu, który mnie nawiedził już po procesie instalacji.

Po zainstalowaniu MySQL, utworzeniu bazy danych, przypisaniu uprawnień i skonfigurowaniu pierwszego połączenia w PHP – może Cię spotkać ot taki komunikat:

Warning: PDO::__construct() [pdo.--construct]: 
[2002] No such file or directory (trying to connect via unix:///tmp/mysql.sock) in

Rozwiązaniem jest uzupełnienie odpowiedniej sekcji w php.ini. MacPort’s zapisują php.ini w katalogu: /opt/local/etc/php5/php.ini Otwieramy go dowolnym edytorem i odszukujemy sekcję pdo_mysql.default_socket

W moim przypadku ta sekcja była pusta. Teraz wystarczy wskazać socket zainstalowanej lokalnie BD. W moim przypadku:

pdo_mysql.default_socket=/opt/local/var/run/mysql5/mysqld.sock

Można sprawdzić jaka jest lokalizacja soketu, wykonując polecenie w termianlu:

mysql5 -u root -p test

… i odszukaniu fragmentu zaczynającego się od UNIX socket.

Teraz tylko – zapisz plik, zrestartuj serwer i gotowe ;)

Jeden błąd mniej! można iść dalej :)

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.