Статьи

Создание файлового хостинга с помощью CodeIgniter

Я видел несколько вводных руководств для Codeigniter и надеялся показать вам что-то более продвинутое. Из этого туториала вы узнаете, как создать мощное веб-приложение для размещения изображений, используя гибкость Codeigniter. Это руководство должно научить вас философии кодирования MVC, которая является неотъемлемой частью создания обслуживаемых приложений.


Прежде чем мы приблизимся к коду, нам нужно выполнить некоторые настройки. Запустите ваш любимый редактор баз данных (я буду использовать SQLBuddy ) и создайте новую базу данных под названием «uploadr». Внутри этого создайте две таблицы: «пользователи» и «файлы». Настройте пользователей на использование первичного ключа с автоматически нумерованным столбцом «id» и двумя столбцами varchar: «пароль» и «имя пользователя». Таблице файлов нужен еще один столбец id (опять же первичный ключ и автонумерация), а также целочисленный столбец «владелец» и столбец «имя» varchar.

Так как этот урок сфокусирован на изучении программирования на Codeigniter и на MVC, мы собираемся отказаться от всего, что связано со стилем (например, CSS, фотошоп). Для этого я создал для вас специальную установку Codeigniter со всеми созданными файлами и представлениями (в основном) HTML-d и CSS-d. Вам нужно изменить две вещи: настройки и настройки базы данных. Я даже включил марку «Бета», так что это было бы еще больше похоже на веб-стартап!

Теперь на первый кусок мяса! Откройте контроллер ‘login.php’ и создайте функцию с именем ‘register’. Это собирается контролировать весь процесс регистрации. Во-первых, нам нужно проверить, были ли какие-либо запросы POST отправлены на сервер. В этом случае это будет означать, кто-то пытается зарегистрироваться. Мы можем сделать это, проверив, установлен ли $ _POST [‘username’]. Если это так, то мы знаем, что кто-то пытался зарегистрироваться, и можем ввести его в БД.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
     
function register()
{
    if(isset($_POST[‘username’])){
         
        // User has tried registering, insert them into database.
         
        $username = $_POST[‘username’];
        $password = $_POST[‘password’];
         
        $this->users->register($username, $password);
         
        redirect(‘login’);
         
    }
    else{
        //User has not tried registering, bring up registration information.
        $this->load->view(‘register’);
    }
}

Если пользователь еще не попытался зарегистрироваться, он обнаруживает это и автоматически отправляет его в представление «регистрация», которое я для вас кодировал. Вы заметите строку:

1
$this->users->register($username,$password);

Это вызов функции ‘register’ в модели ‘users’. На данный момент это не будет работать, так как мы не загрузили модель. Мы делаем это так же, как и при загрузке представлений, но поскольку мы будем широко использовать эту модель в этом классе, мы загрузим ее в функцию конструктора (функцию с тем же именем, что и у класса), так что всегда загружен и доступен:

1
2
3
4
5
function Login()
{
    parent::Controller();
    $this->load->model(‘users’);
}

Вы, вероятно, заинтересованы в том, что на самом деле содержит функция регистрации. Ну, он просто использует несколько активных функций записи Codeigniter, которые позволяют манипулировать БД. Большим преимуществом использования встроенных функций активной записи Codeigniter (помимо того, что они удобны и просты) является то, что они независимы от базы данных: вы можете легко включать и выключать различные типы баз данных (например, MySQL, SQLite) в Конфигурационный файл БД, не влияющий на приложение. В случае нашей регистрации мы добавляем запись в таблицу пользователей. Создайте эту функцию в модели ‘users.php’:

01
02
03
04
05
06
07
08
09
10
11
function register($username, $password)
{
    $new_user = array (
        ‘username’=>$username,
        ‘password’=>$password
    );
 
    $this->db->insert(‘users’, $new_user);
 
    return true;
}

Единственное, что стоит отметить в представлении регистрации, это функции site_url () и base_url (). Они соответственно дают URL вашего сайта с и без index.php / суффикс. Наибольшим преимуществом для них является то, что вы можете изменить структуру URL вашего сайта без необходимости проходить по всем ссылкам: для этого достаточно одного изменения в вашем конфигурационном файле.

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

Теперь, когда у нас настроено несколько пользователей, нам нужен способ фактически позволить им войти на сайт. Для этого мы будем использовать класс сессий Codeigniter. Хотя на самом деле он использует куки, он работает очень похоже на обычные сеансы PHP, только с большим количеством опций (я рекомендую вам проверить руководство пользователя).

Для начала нам нужно создать функцию, на которую в данный момент указывает кнопка входа, «go». Эта функция должна собрать информацию, которую отправила форма, и затем проверить ее по БД с использованием модели. Если все правильно, он начнет сеанс и перенаправит пользователя к его файлам. Если они неправильно набрали свою информацию, они будут перенаправлены на страницу входа.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
function go()
{
 
    $username = $_POST[‘username’];
    $password = $_POST[‘password’];
 
    //Returns userid if successful, false if unsuccessful
    $results = $this->users->login($username,$password);
     
    if ($results==false) redirect(‘login’);
    else
    {
        $this->session->set_userdata(array(‘userid’=>$results));
        redirect(‘profile’);
    }
 
}

Части этой функции должны казаться вам очень знакомыми из функции регистрации: она собирает $ username и $ password перед отправкой их в модель (на этот раз ‘login’). Однако после этого различия начинают возникать.

Затем он проверяет, не удалось ли войти в систему; если это так, то пользователь перенаправляется обратно на страницу входа. Однако, если вход успешен, тогда сценарий создает сеанс, устанавливая ‘userid’ к идентификатору пользователя. Все, что нам нужно сейчас для работы сценария входа — это модель. Добавьте эту функцию к модели «пользователи», которую мы использовали ранее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
function login($username, $password)
{
 
    $query = $this->db->get_where(‘users’, array(‘username’=>$username, ‘password’=>$password));
     
    if ($query->num_rows()==0) return false;
    else{
        $result = $query->result();
        $first_row = $result[0];
        $userid = $first_row->id;
         
        return $userid;
    }
     
}

Быстрое краткое изложение: сначала он запрашивает базу данных, ища любых пользователей с точно такими же именем пользователя и паролем. Если он не найдет ничего, то число строк будет равно 0, и функция вернет false. Если кто-то был найден, он использует другую функцию активной записи Codeigniter для загрузки его в качестве объекта. Этот объект представляет собой массив строк БД, каждая из которых содержит объект с этой информацией о строках. Поскольку нам нужна первая и единственная строка, мы берем ее из $ result и затем возвращаем из нее идентификатор.

Нам нужно проверить, вошел ли пользователь на странице профиля. Для этого мы просто вставляем две строки кода в конструктор контроллера профиля. Это проверит, что сеанс содержит идентификатор пользователя. Если это не так, то перенаправьте на страницу входа. Если это так, то все в порядке, и он превращается в публичную переменную. Пока мы меняем конструктор, мы загрузим две модели, которые нам понадобятся для страницы профиля:

01
02
03
04
05
06
07
08
09
10
function Profile()
{
    parent::Controller();
     
    $this->load->model(‘users’);
    $this->load->model(‘files’);
 
    $this->userid = $this->session->userdata(‘userid’);
    if (!isset($this->userid) or $this->userid==») redirect(‘login’);
}

Последнее, что нам нужно сделать, это сделать возможным выход из системы. Это достигается просто установкой идентификатора пользователя, удалив его. Все, что для этого требуется, — это одна простая функция:

1
2
3
4
5
function logout()
{
    $this->session->set_userdata(array(‘userid’=>»));
    redirect(‘login’);
}

Тогда мы только что вошли в систему в первый раз. С чем нас встречают?

Не плохо, не плохо, хотя этот «образец файла» не генерируется из нашей базы данных, он статичен. Мы исправим это в ближайшее время, но сначала нам нужно изменить права доступа к папке «file», чтобы Codeigniter мог читать и писать в нее. Я изменил его на 777 Permissions:

Теперь, когда это не так, давайте вернемся к некоторому кодированию! Нам нужно загрузить все файлы пользователей из базы данных, и для этого нам понадобится …

… модель! На этот раз, однако, мы собираемся создать его в модели files.php, поэтому мы разделили нашу пользовательскую таблицу и таблицу файлов. Вставьте эту функцию:

1
2
3
4
5
function get($userid)
{
    $query = $this->db->get_where(‘files’, array(‘owner’=>$userid));
    return $query->result();
}

Это снова опирается на более ранние разделы этого урока, так что вы должны быть в состоянии понять это. По сути, он получает все строки, в которых владелец = идентификатор пользователя, и возвращает их в виде массива объектов. Давайте создадим что-то в контроллере «Profiles», чтобы взаимодействовать с ним и передавать информацию в представление. Изменить функцию индекса следующим образом:

1
2
3
4
5
function index()
{
    $data[‘files’] = $this->files->get($this->userid);
    $this->load->view(‘profile’, $data);
}

Опять же, очень простая функция. Он берет результаты, переданные ему из файловой модели, и упаковывает их в представление. Codeigniter передает данные в представление обычно через массив (в данном случае данные). Затем он автоматически разнесет массив на множество переменных, поэтому, когда мы перейдем к представлению, он сможет получить доступ к результатам базы данных через $ file, а не $ data [‘file’]. Давайте представим этот прекрасный результат базы данных! Вставьте это в ‘profile.php’, заменив код, который вам говорит HTML-комментарий.

01
02
03
04
05
06
07
08
09
10
11
<?php foreach($files as $file): ?>
 
<div class=»section»>
    <span><?=$file->name?>
    <div style=»float: right;»>
        <span><a href=»<?=base_url()?>files/<?=$file->name?>»>View</a>
        <span><a href=»<?=site_url(«profile/delete/».$file->id)?>»>Delete</a>
    </div>
</div>
 
<?php endforeach;

Цикл foreach загружает каждую строку массива по очереди и делает его доступным через объект $ file. Затем, используя образец «section» в качестве шаблона, заполняем все ссылки и имя информацией для нового объекта $ file. Мы расскажем, как работает функция удаления, и как работает ссылка для просмотра после того, как мы что-то загрузили.

Если вы откроете это в своем браузере сейчас, вы ничего не увидите. Это потому, что у нас нет загруженных файлов! Что ж, нам нужно это исправить, поэтому нам нужно сделать форму для загрузки. Давайте сначала сделаем контроллер; Откройте файл profile.php и добавьте эту функцию:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
function upload()
{
    if(isset($_FILES[‘file’])){
        $file = read_file($_FILES[‘file’][‘tmp_name’]);
        $name = basename($_FILES[‘file’][‘name’]);
         
        write_file(‘files/’.$name, $file);
 
        $this->files->add($name);
        redirect(‘profile’);
    }
 
    else $this->load->view(‘upload’);
}

Эта функция добавляет довольно много нового: особенно обработку файлов Codeigniter. Он начинается довольно просто, проверяя, была ли отправлена ​​форма, путем поиска файла. Если файл не существует, он просто показывает представление загрузки (которое мы будем обновлять далее). Если файл существует, он извлекает считанные временные файлы, созданные сервером. Каталог временного файла можно найти в $ _FILES [‘ your_file ‘] [‘tmp_name’], и файл можно прочитать из этого каталога с помощью read_file Codeigniter. Это загружает всю информацию о файлах в переменную $ file.

Следующая строка получает имя файла из глобальной переменной $ _FILES аналогично получению временного каталога. Вооружившись этими двумя частями информации, codeigniter записывает файл в папку files в том же каталоге, что и индексный файл. Наконец, файл должен быть добавлен в базу данных. Опять же, мы собираемся сделать это с моделью, на этот раз функцией «add» в «файлах». Через несколько минут мы увидим, как это работает, но теперь нам нужно создать форму загрузки в представлении. Добавьте это, когда HTML-комментарий upload.php говорит вам:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<form enctype=»multipart/form-data» action=»<?=site_url(‘profile/upload’)?>» method=»post»>
 
    <div id=»boxtop»></div><div id=»boxmid»>
 
        <div class=»section»>
            <span>File:
            <input type=»file» name=»file» />
        </div>
 
    </div><div id=»boxbot»></div>
 
    <div class=»text» style=»float: left;»><p>Before uploading, check out</p><p>the <a href=#>Terms of Service</a>.</p></div>
    <div class=»text» style=»float: right;»>
 
    <input type=»submit» value=»Upload» name=»upload» class=»submit» />
</div>
<br style=»clear:both; height: 0px;»
 
</form>

Замените текущий HTML-код этим. Здесь важно отметить, что при загрузке файлов мы используем тип ввода = файл, который позволяет нам выбрать файл для загрузки. Кроме того, мы должны указать enctype в нашем теге формы, чтобы сервер знал, что он получает файл и сохраняет его. Не слишком интересный для нас, back-end кодеров, но все же решающий Давайте кратко рассмотрим, что мы создали:

Теперь перейдем к последнему фрагменту скрипта загрузки файлов — модели. Это добавит файл в базу данных с его именем и владельцем, чтобы сервер знал, какие файлы кому принадлежат. Давайте взглянем; добавьте это к вашей модели ‘files’:

1
2
3
4
function add($file)
{
    $this->db->insert(‘files’, array(‘owner’=>$this->session->userdata(‘userid’),’name’=>$file ));
}

Опять же используя функциональность активной записи Codeigniter, мы добавляем в базу данных строку с именем файла и владельцем. Мы получаем владельца, находя идентификатор пользователя из данных сеанса, которые мы сохранили ранее при входе в систему. В общем, очень простая функция. Давайте попробуем загрузить красивую фотографию, а?

И вуаля!

Посмотрев в папку «files», мы увидим, что загруженный нами файл появился там, как по волшебству (Codeigniter magic!), И мы видим, почему работает ссылка view, поскольку она просто указывает непосредственно на файл в каталоге , После этого все, что осталось для этого урока, — это удаление файлов.

Хорошо, последний бит. Это не должно занять много времени, так как вы сможете использовать идеи, которые вы узнали ранее, чтобы понять это. Сначала мы добавим этот код в наш контроллер профилей:

1
2
3
4
5
6
7
function delete($id)
{
    //This deletes the file from the database, before returning the name of the file.
    $name = $this->files->delete($id);
    unlink(‘files/’.$name);
    redirect(‘profile’);
}

И этот код нашей модели «файлы»:

1
2
3
4
5
6
7
function delete($fileid)
{
    $query = $this->db->get_where(‘files’,array(‘id’=>$fileid));
    $result = $query->result();
    $query = $this->db->delete(‘files’, array(‘id’=>$fileid));
    return $result[0]->name;
}

Первый контроллер должен быть очень простым для понимания. Он вызывает функцию удаления из модели файлов (которую мы одновременно определили), которая генерирует имя файла. Затем он использует базовую функцию PHP для удаления файла с таким именем в каталоге файлов. Наконец, он отправляет обратно в профиль пользователя (который теперь минус один файл).

Модель немного сложнее. Он должен вернуть имя файла, а также удалить его, поэтому сначала он запрашивает базу данных, чтобы получить сведения о файлах. Он загружает это в переменную $ result и затем удаляет файл. Затем он возвращает столбец name первой строки массива (единственной строки, возвращенной запросом), который затем используется в вышеуказанном контроллере.

Давайте попробуем удалить функцию:

И нажмите удалить …

Ура! Это сработало. Я думаю, что мы все сделали тогда!

Удалить файлы

Конечно, этот код не следует запускать на сервере без серьезных улучшений. Вот несколько основных проблем с этим:

  • Все пароли не зашифрованы. Это означает, что если кто-то проникнет в вашу базу данных, он сможет украсть все данные ваших пользователей с минимальными усилиями. Как я уверен, вы все согласитесь: не хорошо. Это можно легко решить, добавив к паролям простое хеширование.
  • Файлы не являются частными. Пользователь может захотеть убедиться, что загружаемые им файлы видны только им, а не тому, кто просто угадывает несколько URL-адресов. Для этого, вероятно, потребуется другой контроллер для обслуживания файлов (который проверяет данные сеанса).
  • Скрипт не проверяет, существуют ли файлы перед записью файлов. Это может привести к конфликту с вашими файлами или к перезаписи данных файла. Что угодно: не хорошо. Эту проблему можно решить с помощью простой проверки БД, чтобы убедиться, что файл не был взят, и свести к минимуму, предоставив пользователям свои собственные каталоги в папке файлов.
  • Ошибки не генерируются. Это не совсем помогает пользователю понять, что он делает неправильно, и хотя это не слишком большая проблема для такого маленького сайта с такими ограниченными действиями, его все же можно улучшить.

В общем, вы создали довольно мощное небольшое веб-приложение, особенно из-за небольшого количества кода, который вам пришлось написать. Из-за природы Codeigniter его довольно легко расширить как для решения вышеуказанных проблем, так и для добавления новых функций, таких как переименование файлов. Я также надеюсь, что это руководство научило вас немного об использовании концепций MVC и их возможностях: просто скорректировав модели в нашем приложении, мы можем поменять нашу БД на текстовые файлы, XML или что-либо еще, а также изменить представления Мы можем полностью изменить тему без нарушения функциональности. Удивительный!