Одновременная множественная загрузка данных в CakePHP

Добавлено: 25/11/2014 01:16 |  Обновлено: 03/09/2017 09:09 |  Добавил: nick |  Просмотры: 6525 Комментарии: 0
Вводная часть
Речь пойдет о множественной загрузке информации из файла в БД. Понимаю, что смысл сразу понять трудно, поэтому поясню на примере. Представим, у вас есть текстовый файл с данными из какой-то программы. Например это может быть электронный каталог книг. И данные каждой книги (автор, название, аннотация и т.д.) разделены каким-то набором символов. А в базу нам нужно внести отдельно каждую книгу в свою строку. CakePHP предоставляет нам возможность сделать это просто загрузив файл на сервер, а дальше фреймворк раскидает данные по нужным строкам. Пример выполняется в CakePHP 2.5.6.
Речь пойдет о множественной загрузке информации из файла в БД. Понимаю, что смысл сразу понять трудно, поэтому поясню на примере. Представим, у вас есть текстовый файл с данными из какой-то программы. Например это может быть электронный каталог книг. И данные каждой книги (автор, название, аннотация и т.д.) разделены каким-то набором символов. А в базу нам нужно внести отдельно каждую книгу в свою строку. CakePHP предоставляет нам возможность сделать это просто загрузив файл на сервер, а дальше фреймворк раскидает данные по нужным строкам. Пример выполняется в CakePHP 2.5.6 - Метод, который отвечает за одновременное множественное сохранение строк в модель, называется "saveMany(array $data)". Подробнее об этом методе можно посмотреть на сайте http://book.cakephp.org/2.0/. Как вы могли заметить методу нужно скормить массив с данными, причем это должен быть массив определенной структуры. А именно нумерованный массив следующего вида:
array(
	(int) 0 => array(
		'title' => 'Пост из файла',
		'body' => 'Пост 1 из файла'
	),
	(int) 1 => array(
		'title' => 'Пост из файла',
		'body' => 'Пост 2 из файла'
	),
	...
)
То есть наша задача сформировать такой массив. Приступим к практической части.

В качестве заготовки используем пример простого блога, который представлен на сайте http://book.cakephp.org/2.0/. Спасибо разработчикам, что они расписали весь ход работы по созданию блога. Если вы ни разу не работали с CakePHP рекомендую начать именно с этого примера. Итак начнем.

Загружаем фреймворк на сервер и далее делаем как указано на странице создания блога.

Создаем таблицу "posts" с первыми тремя записями:
/*Создаем таблицу posts: */
CREATE TABLE posts (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(50),
    body TEXT,
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
);

/* Затем вставляем 3 тестовые записи: */
INSERT INTO posts (title, body, created)
    VALUES ('The title', 'This is the post body.', NOW());
INSERT INTO posts (title, body, created)
    VALUES ('A title once again', 'And the post body follows.', NOW());
INSERT INTO posts (title, body, created)
    VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());
Напоминаю, пока мы работаем с учебным блогом на сайте http://book.cakephp.org/2.0/.

Далее подключаемся к БД в файле приложения (app/Config/database.php.default). Переименовываем его в "database.php". Если все сделано правильно, то перейдя на страницу приветствия фреймворка вы должны увидеть запись: "CakePHP is able to connect to the database.".

Раздел "Optional Configuration" можно пропустить.

Сразу переходим к разделу "Create a Post Model". Создаем модель в папке приложения (app/Model), называем файл "Post.php". Вставляем в него следующее:
<?php
// app/Model/Post.php
class Post extends AppModel {
}
Далее создаем контроллер в папке приложения (app/Controller), называем файл "PostsController.php".

Внимание! На этом этапе, на пример простого блога, который представлен на сайте http://book.cakephp.org/2.0/ можно уже не смотреть, так как в следующие файлы мы будем вставлять свое содержимое.

Итак, в файл контроллера вставляем следующее:
<?php
class PostsController extends AppController {
    public $helpers = array('Html', 'Form');

    public function index() {
        $this->set('posts', $this->Post->find('all'));
    }

    public function add() {
    	if ($this->request->is('post')) {
            $this->Post->create();
			$pattern = "/---/";
			if (!empty($this->request->data)) {
				$file = $this->data['Post']['file'];
				$f = trim(file_get_contents($file['tmp_name']));
				$split = preg_split($pattern, $f, -1, PREG_SPLIT_NO_EMPTY);
			}	
			foreach ($split as $key => $value) {
				$data[$key] = array("title" => "Пост из файла", 
									"body"  => $value);
			}
			if ($this->Post->saveMany($data)) {
                $this->Session->setFlash(__('Данные были успешно добавлены в базу.'));
                return $this->redirect(array('action' => 'index'));
            }
            $this->Session->setFlash(__('Данные добавить в базу не удалось.'));
        }    	
    }    
}
Скажу немного о коде. Во-первых подключаем хэлперы. Они нам нужны будут для представлений. Во-вторых создаем два экшена: "index" и "add". Экшен "index" отвечает за вывод всех постов блога по адресу: адрес_вашего_сервера/posts/. Экшен "add" отвечает за вставку данных в базу, которые контроллер получит со страницы: адрес_вашего_сервера/posts/add, где мы разместим форму для загрузки файлов. Именно в экшене "add" и работает метод "saveMany(array $data)".

Кстати, надо сказать о структуре файла данных, который мы будем загружать на сервер. Это текстовый файл следующего содержания:
Пост 1 из файла
---
Пост 2 из файла
---
Пост 3 из файла
---
То есть разделитель между постами у нас "---". Именно по этому разделителю мы разбиваем посты, добавляем их в массив $data, которые затем добавляются в БД с помощью метода "saveMany(array $data)".

С контроллером все. Теперь нужно создать два вида (представления) для экшенов. В папке приложения (app/View) создаем папку "Posts" и затем в ней создаем файлы видов: "add.ctp" и "index.ctp".

В файл "index.ctp" добавляем следующее:
<!-- File: /app/View/Posts/index.ctp -->
<?php echo $this->Html->link('Добавить записи', array('controller' => 'posts', 'action' => 'add')); ?>
<h1>Blog posts</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Body</th>
        <th>Created</th>
    </tr>

    <!-- Проходим по всем постам и выводим их один за другим -->

    <?php foreach ($posts as $post): ?>
    <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
            <?php echo $post['Post']['title']; ?>
        </td>
        <td>
            <?php echo $post['Post']['body']; ?>
        </td>        
        <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>
    <?php unset($post); ?>
</table>
Файл "add.ctp" попроще:
<!-- File: /app/View/Posts/add.ctp -->

<h1>Add Post</h1>
<?php
echo $this->Form->create('Post', array('enctype' => 'multipart/form-data',
	'inputDefaults' => array('label' => false, 'div' => false)));
echo $this->Form->input('file', array('type' => 'file'));
echo $this->Form->end('Добавить записи');
?>
В этом файле у нас форма для загрузки файлов на сервер.

Все. Теперь можно создать текстовый файл с указанным выше содержанием и загрузить его на сервер.

Для удобства выкладываю папку приложения (app).

Оставьте свой комментарий

Комментариев нет