Создаём виджет для хранения заметок. Часть 1.

Владимир | | MySQL, PHP, Web разработка.

notes widget

Приветствую всех!

В этой статье я хочу показать пример создания собственного виджета, с помощью которого можно будет создавать короткие заметки и просматривать их. Виджет будет свободно перемещаться по странице и, конечно, будет возможность редактировать и удалять заметки.

Код виджета не сложный, но требует использования сразу нескольких технологий: PHP и MySQL на стороне сервера, HTML, CSS, JavaScript – на стороне клиента, поэтому я разбил статью на 2 части. В первой мы рассмотрим серверную часть кода, во второй – клиентскую.

Чтобы лучше понять, что мы получим в результате, взгляните на демонстрационную страничку

Demo

Если задача ясна, приступим к делу.

Начнем с базы данных.

Т.к. виджет предназначен для хранения коротких заметок, структура базы будет максимально простой.

Создаём таблицу notes с тремя полями:
id – первичный ключ;
note_text (тип varchar(300)) – текст заметки (длина не более 300 символов);
note_date (тип datetime) – дата создания заметки.

Теперь напишем PHP скрипты, с помощью которых мы будем читать, создавать, удалять и редактировать записи.

Т.к. пример довольно простой, то в использовании фреймворка я смысла не вижу, а для работы с базой будем использовать PDO.

Создаём скрипт с параметрами подключения к БД (db.inc.php).

<?php

$dbName   = 'database_name';
$dbUser   = 'database_user';
$dbPass   = 'database_password';
$dbServer = 'localhost';

// end of db.inc.php

Его мы будем включать во все скрипты, которые работают с базой.

Теперь напишем скрипт, возвращающий список записей (getnotes.php).

<?php

include_once('db.inc.php');

$results = array();

try {
    $dbh = new PDO('mysql:host='.$dbServer.';dbname='.$dbName, $dbUser, $dbPass);
    $dbh->exec('SET CHARACTER SET utf8');
    $notes = $dbh->query('SELECT * FROM notes ORDER BY note_date DESC');
    $dbh = null;
    
    $results['status'] = 'OK';
    $results['notes'] = $notes->fetchAll(PDO::FETCH_ASSOC);
    
    echo json_encode($results);
}
catch (PDOException $e) {
    $results['status'] = 'ERR';
    $results['message'] = 'Ошибка при работе с БД: '.$e->getMessage();
    
    echo json_encode($results);
}

// end of getnotes.php

Разберём, что здесь происходит.

Прежде всего, мы подключаем файл db.inc.php. И создаём объект PDO (строка 8).

Затем выполняем 2 запроса. С помощью первого (строка 9) настраиваем кодировку, а с помощью второго – получаем список записей, отсортированный по их датам в убывающем порядке. Таким образом, самые новые записи окажутся в начале списка.

После этого, формируем массив с результатами (строки 13 и 14), преобразуем его в JSON формат и отправляем браузеру, строка 16.

С помощью параметра status мы указываем удачно или нет, завершился запрос к базе.

Теперь рассмотрим скрипт сохранения записи (savenote.php). Он немного сложнее, т.к. наш позволяет, как изменять существующие записи, так и создавать новые.

<?php

include_once('db.inc.php');

try {
    $newNote = false;
    if (isset($_REQUEST['bAddNote'])) {
        $newNote = true;
    }
    else {
        $id = $_REQUEST['id'];
        $id = substr($id, 5);
    }
    $text = $_REQUEST['value'];
    
    $dbh = new PDO('mysql:host='.$dbServer.';dbname='.$dbName, $dbUser, $dbPass);
    $dbh->exec('SET CHARACTER SET utf8');
    if ($newNote) {
        $stmt = $dbh->prepare('INSERT INTO notes (note_text, note_date) VALUES (?, NOW())');
        $stmt->execute(array($text));
        echo $dbh->lastInsertId();
    }
    else {
        $stmt = $dbh->prepare('UPDATE notes SET note_text=?, note_date=NOW() WHERE id=?');
        $stmt->execute(array($text, $id));
        echo $text;
    }
    $dbh = null;
}
catch (PDOException $e) {
    echo 'Не могу сохранить запись';
}

// end of savenote.php

Разница между изменением записи и созданием новой в том, что пользователь нажимает на кнопку «Добавить запись». Т.е. скрипту будет передан параметр bAddNote (это значение атрибута name кнопки).

Кроме того, если мы хотим изменить существующую запись, то должны передать два параметра: id (первичный ключ записи в базе) и value (новый текст).

Тут есть один нюанс. Когда мы показываем список записей в виджете, то как-то должны сохранять их номера (поле id в БД). В данном примере для этой цели используется атрибут id элементов списка (теги li), но значение этого атрибута не может начинаться с цифры, поэтому мы будем записывать их в виде note_№ (например, note_1, note_2 и т.д.).

Для того чтобы получить id записи мы удаляем первые пять символов, т.е. note_ из полученного значения (строка 12).

Дальше мы формируем запрос либо на обновление (строка 24), либо на создание новой записи (строка 19).

Что касается возвращаемых значений, то при обновлении мы возвращаем браузеру новый текст записи, а при создании новой записи – её id в базе.

И последний PHP скрипт removenote.php – предназначен для удаления записей.

<?php

include_once('db.inc.php');

try {
    $id = $_REQUEST['id'];
    $id = substr($id, 5);
    
    $dbh = new PDO('mysql:host='.$dbServer.';dbname='.$dbName, $dbUser, $dbPass);
    $dbh->exec('SET CHARACTER SET utf8');

    $stmt = $dbh->prepare('DELETE FROM notes WHERE id=?');
    $stmt->execute(array($id));
    $dbh = null;
    
    echo 'OK';
}
catch (PDOException $e) {
    echo 'Не могу удалить запись';
}

// end of removenote.php

Подробно останавливаться на нем, по-моему, нет смысла. Основное отличие от предыдущих скриптов – в запросе, который выполняется.

На этом этапе серверная часть приложения полностью готова. Мы можем редактировать, создавать, удалять и читать наши записи.

В следующий раз мы рассмотрим клиентскую часть приложения. Там же выложу архив с исходниками.

Если есть вопросы, замечания или предложения, пишите, буду рад ответить.

Интересно почитать.

«Совершенный Ajax» –
новый подход к построению настоящих клиент-серверных web-приложений

Сервис покупки игровой
валюты
практически для любой
онлайн игры. Большое количество способов оплаты — webmoney, sms,
paypal, наличными и др.

  • Serator

    Идея довольно интересна. К примеру возможно применение в панели администрации, аль при заполнении больших форм (написание статьи), чтобы не держать в памяти. Но вот в реализации я бы использовал sqlite как бд, т.к. база-то мизерная + у меня не получилось отредактировать записи (Firefox 3.5 beta 4). При клике вне поля текст сообщения вернулся к состоянию до редактирования.

    P.S. Давненько подписался на ваш блог. Есть довольно интересные заметки. Спасибо 🙂

    • При клике вне поля текст сообщения вернулся к состоянию до редактирования

      Правильно, клик вне поля просто убирает форму. Нажатие на клавишу Enter — сохраняет данные.

      sqlite как бд, т.к. база-то мизерная

      Согласен, база мизерная. Но если движок сайта использует mysql, то проще добавить дополнительную таблицу в основную базу. В любом случае, PDO поддерживает sqlite, поэтому достаточно просто изменить параметры подключения.

  • Serator

    Идея довольно интересна. К примеру возможно применение в панели администрации, аль при заполнении больших форм (написание статьи), чтобы не держать в памяти. Но вот в реализации я бы использовал sqlite как бд, т.к. база-то мизерная + у меня не получилось отредактировать записи (Firefox 3.5 beta 4). При клике вне поля текст сообщения вернулся к состоянию до редактирования.

    P.S. Давненько подписался на ваш блог. Есть довольно интересные заметки. Спасибо 🙂

    • При клике вне поля текст сообщения вернулся к состоянию до редактирования

      Правильно, клик вне поля просто убирает форму. Нажатие на клавишу Enter — сохраняет данные.

      sqlite как бд, т.к. база-то мизерная

      Согласен, база мизерная. Но если движок сайта использует mysql, то проще добавить дополнительную таблицу в основную базу. В любом случае, PDO поддерживает sqlite, поэтому достаточно просто изменить параметры подключения.

  • Big_Shark

    Использование PDO очень усложняет понимание.
    Для тех кто знает PDO данная задача не составит труда.
    А у остальных вызовет кучу непонимания и негодования.

    $_REQUEST думаю лучше заменить на GET или POST смотря что в данном случае требуется.

    • Использование PDO очень усложняет понимание.

      Может и усложняет, но используется ведь всего 4 метода: exec, prepare, execute, lastInsertId. И их названия в общем-то говорят сами за себя. А запрос написан на SQL. Не думаю, что вопросительный знак вместо значения создаст черезмерно усложняет понимание.
      Зато явно видно, что использование библиотек значительно упрощает работу с базой (по сравнению с обычными mysql_ функциями).

      $_REQUEST

      В комментариях к одному из предыдущих постов мне дали точно противоположный совет 🙂
      Честно говоря, я особой разницы не вижу. Для этого примера можно все $_REQUEST спокойно заменить на $_POST.

      • Big_Shark

        $_REQUEST объединяет массивы GET, POST, SERVER и COOKIE в результате чего безопасность понижается и стабильность работы тоже так как куку можно затереть GETом и наоборот.

        Зато явно видно, что использование библиотек значительно упрощает работу с базой (по сравнению с обычными mysql_ функциями).

        На любителя. Мне приятней видеть работу со стандартными функциями mysql_ или AR из CI.

        • Serator

          С PDO решение выглядит более универсальным, т.к. здесь не используются какие-то особенности MySQL и, следовательно, возможно использовать в связке с другими базами.

          Ну а с $_REQUEST полностью с вами согласен, лучше $_POST/$_GET.

        • $_REQUEST

          Для данного примера это в общем-то не принципиально. Авторизацию я все равно не делал.

          AR из CI

          Интересно. Никогда не думал о ActiveRecord как о стандартной функции. Помоему это как раз пример специализированной библиотеки.

  • Big_Shark

    Использование PDO очень усложняет понимание.
    Для тех кто знает PDO данная задача не составит труда.
    А у остальных вызовет кучу непонимания и негодования.

    $_REQUEST думаю лучше заменить на GET или POST смотря что в данном случае требуется.

    • Использование PDO очень усложняет понимание.

      Может и усложняет, но используется ведь всего 4 метода: exec, prepare, execute, lastInsertId. И их названия в общем-то говорят сами за себя. А запрос написан на SQL. Не думаю, что вопросительный знак вместо значения создаст черезмерно усложняет понимание.
      Зато явно видно, что использование библиотек значительно упрощает работу с базой (по сравнению с обычными mysql_ функциями).

      $_REQUEST

      В комментариях к одному из предыдущих постов мне дали точно противоположный совет 🙂
      Честно говоря, я особой разницы не вижу. Для этого примера можно все $_REQUEST спокойно заменить на $_POST.

      • Big_Shark

        $_REQUEST объединяет массивы GET, POST, SERVER и COOKIE в результате чего безопасность понижается и стабильность работы тоже так как куку можно затереть GETом и наоборот.

        Зато явно видно, что использование библиотек значительно упрощает работу с базой (по сравнению с обычными mysql_ функциями).

        На любителя. Мне приятней видеть работу со стандартными функциями mysql_ или AR из CI.

        • Serator

          С PDO решение выглядит более универсальным, т.к. здесь не используются какие-то особенности MySQL и, следовательно, возможно использовать в связке с другими базами.

          Ну а с $_REQUEST полностью с вами согласен, лучше $_POST/$_GET.

        • $_REQUEST

          Для данного примера это в общем-то не принципиально. Авторизацию я все равно не делал.

          AR из CI

          Интересно. Никогда не думал о ActiveRecord как о стандартной функции. Помоему это как раз пример специализированной библиотеки.

  • Big_Shark

    Интересно. Никогда не думал о ActiveRecord как о стандартной функции. Помоему это как раз пример специализированной библиотеки.

    Там написано «или AR из CI»

    С PDO решение выглядит более универсальным, т.к. здесь не используются какие-то особенности MySQL и, следовательно, возможно использовать в связке с другими базами.

    В этом я с вами согласен.

  • Big_Shark

    Интересно. Никогда не думал о ActiveRecord как о стандартной функции. Помоему это как раз пример специализированной библиотеки.

    Там написано «или AR из CI»

    С PDO решение выглядит более универсальным, т.к. здесь не используются какие-то особенности MySQL и, следовательно, возможно использовать в связке с другими базами.

    В этом я с вами согласен.

  • Виктория

    Здравствуйте, мне очень понравился ваш виджет, я хотела бы разместить его на своем сайте.
    Простите, но не могли бы вы мне помочь в этом. Я не очень понимаю про БД (я никогда с ними не работала), просто, если все файлы из архива исходника добавить к моему сайту, всё создается — окошко для записей, но, соответственно, ничего не добавляется. Как я понимаю нужна БД и наверно, что-то нужно подправить потом в коде, но я не знаю, что.
    Пожалуqста помогите мне в этом вопросе. Если можно напишите ответ на е-mail. Заранее большое спасибо!

    • Да, база данных нужна. Исправлять нужно только параметры в первом листинге, т.е. параметры подключения к базе, а их вы можете узнать только у вашего хостера.

      Если будут вопросы, пишите, но на данный момент вам нужно выяснить у хостера параметры подключения. На крайний случай, если хостер по какой-то причине не предоставляет доступ к БД, можно использовать базу sqlite, я помогу зменить скрипт, но поддержка PHP нужна обязательно.

  • Виктория

    Здравствуйте, мне очень понравился ваш виджет, я хотела бы разместить его на своем сайте.
    Простите, но не могли бы вы мне помочь в этом. Я не очень понимаю про БД (я никогда с ними не работала), просто, если все файлы из архива исходника добавить к моему сайту, всё создается — окошко для записей, но, соответственно, ничего не добавляется. Как я понимаю нужна БД и наверно, что-то нужно подправить потом в коде, но я не знаю, что.
    Пожалуqста помогите мне в этом вопросе. Если можно напишите ответ на е-mail. Заранее большое спасибо!

    • Да, база данных нужна. Исправлять нужно только параметры в первом листинге, т.е. параметры подключения к базе, а их вы можете узнать только у вашего хостера.

      Если будут вопросы, пишите, но на данный момент вам нужно выяснить у хостера параметры подключения. На крайний случай, если хостер по какой-то причине не предоставляет доступ к БД, можно использовать базу sqlite, я помогу зменить скрипт, но поддержка PHP нужна обязательно.