Статьи

Создайте свой первый пакет администратора для Laravel

Трудно отрицать тот факт, что сообщество PHP заинтересовано в Laravel 4. Помимо прочего, среда использует возможности Composer, что означает, что она может использовать любой пакет или скрипт из Packagist .

Тем временем, Laravel предлагает «Связки», которые позволяют нам модульно кодировать для использования в будущих проектах. Каталог bundle полон отличных скриптов и пакетов, которые вы можете использовать в своих приложениях. В этом уроке я покажу вам, как создать его с нуля!


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

Структура папок

Создать пакет довольно просто. Чтобы проиллюстрировать этот процесс, мы создадим шаблон панели администратора, который мы можем использовать в будущих проектах. Во-первых, нам нужно создать каталог «admin» в нашей папке «bundles». Попробуйте скопировать структуру папок с картинки выше.

Прежде чем мы начнем добавлять что-либо в наш пакет, нам нужно сначала зарегистрировать это в Laravel. Это делается в файле bundles.php вашего приложения. Как только вы откроете этот файл, вы должны увидеть возвращаемый массив; нам просто нужно добавить наш пакет и определить handle . Это станет URI, в котором мы получим доступ к нашей панели администратора.

1
‘admin’ => array(‘handles’ => ‘admin’)

Здесь я назвал мой «админ», но не стесняйтесь называть свои как хотите.

Как только мы получим эту настройку, нам нужно создать файл start.php . Здесь мы собираемся настроить несколько вещей, таких как наши пространства имен. Если вас это не беспокоит, то вам не нужен стартовый файл для работы вашего пакета, как ожидалось.

Класс автозагрузчика Laravel позволяет нам сделать несколько вещей: сопоставить наш базовый контроллер и пространства имен автозагрузки.

1
2
3
4
5
6
7
8
Autoloader::map(array(
    ‘Admin_Base_Controller’ => Bundle::path(‘admin’).’controllers/base.php’,
));
 
Autoloader::namespaces(array(
    ‘Admin\Models’ => Bundle::path(‘admin’).’models’,
    ‘Admin\Libraries’ => Bundle::path(‘admin’).’libraries’,
));

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


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

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

1
php artisan bundle:publish admin

Это скопирует структуру папок и файлы в каталог bundles в нашей public папке в корневом каталоге установки Laravel. Затем мы можем использовать это в базовом контроллере нашего пакета.


Это всегда хорошая идея, чтобы настроить базовый контроллер и расширяться оттуда. Здесь мы можем настроить контроллеры restful, определить макет и включить любые ресурсы. Нам просто нужно вызвать этот файл base.php и base.php его в каталог нашего контроллера.

Во-первых, давайте уберем с дома некоторую уборку. Мы, конечно, захотим использовать спокойные контроллеры Laravel.

1
public $restful = true;

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

1
public $layout = ‘admin::layouts.main’;

Название связки, за которым следуют два двоеточия, — это парадигма в Laravel, которую мы увидим в будущем, так что следите.

При обработке ресурсов в нашем пакете мы можем делать все как положено и указывать путь из корня общедоступной папки. К счастью, Laravel здесь, чтобы сделать нашу жизнь проще. В нашей конструкции нам нужно указать пакет перед добавлением в наши контейнеры активов.

1
2
Asset::container(‘header’)->bundle(‘admin’);
Asset::container(‘footer’)->bundle(‘admin’);

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

Теперь мы можем легко включать наши стили начальной загрузки и сценарии. Наш законченный базовый контроллер должен выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Admin_Base_Controller extends Controller {
 
    public $restful = true;
    public $layout = ‘admin::layouts.main’;
 
    public function __construct(){
 
        parent::__construct();
 
        Asset::container(‘header’)->bundle(‘admin’);
        Asset::container(‘header’)->add(‘bootstrap’, ‘css/bootstrap.min.css’);
 
        Asset::container(‘footer’)->bundle(‘admin’);
        Asset::container(‘footer’)->add(‘jquery’, ‘http://code.jquery.com/jquery-latest.min.js’);
        Asset::container(‘footer’)->add(‘bootstrapjs’, ‘js/bootstrap.min.js’);
 
    }
 
    /**
     * Catch-all method for requests that can’t be matched.
     *
     * @param string $method
     * @param array $parameters
     * @return Response
     */
    public function __call($method, $parameters){
        return Response::error(‘404’);
    }
 
}

Мы также передали общий запрос приложения от базового контроллера приложения для возврата ответа 404, если страница не найдена.

Прежде чем делать что-то еще, давайте views/layout/main.blade.php файл для этого макета, views/layout/main.blade.php , чтобы в дальнейшем не возникало никаких ошибок.


Поскольку мы создаем административную панель, мы будем хотеть не пускать людей. К счастью, мы можем использовать встроенный в Laravel класс Auth чтобы сделать это с легкостью …

Во-первых, нам нужно создать нашу таблицу; Я буду использовать ‘admins’ в качестве имени таблицы, но вы можете изменить его, если хотите. Artisan сгенерирует миграцию и поместит ее в каталог миграций нашего пакета. Просто запустите следующее в командной строке.

1
php artisan migrate:make admin::create_admins_table

Если вы не знакомы со сборщиком схем, я рекомендую вам взглянуть на документацию . Мы собираемся включить несколько столбцов:

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

Мы также включим временные метки по умолчанию, чтобы следовать рекомендациям.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * Make changes to the database.
 *
 * @return void
 */
public function up()
{
    Schema::create(‘admins’, function($table)
    {
        $table->increments(‘id’);
        $table->string(‘name’, 200);
        $table->string(‘username’, 32)->unique();
        $table->string(‘password’, 64);
        $table->string(’email’, 320)->unique();
        $table->string(‘role’, 32);
        $table->timestamps();
    });
}
 
/**
 * Revert the changes to the database.
 *
 * @return void
 */
public function down()
{
    Schema::drop(‘admins’);
}

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

1
2
3
4
5
namespace Admin\Models;
use \Laravel\Database\Eloquent\Model as Eloquent;
 
class Admin extends Eloquent {
}

Выше мы start.php что мы используем пространство имен, которое мы определили в start.php . Кроме того, чтобы мы могли ссылаться на Eloquent правильно, мы создаем псевдоним.

Чтобы наш пакет был полностью автономным, нам нужно расширить auth . Это позволит нам определить таблицу просто для входа в нашу админ-панель, а не мешать основному приложению.

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

1
2
3
4
return array(
    ‘username’ => ‘username’,
    ‘password’ => ‘password’,
);

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

Далее нам нужно создать драйвер. Давайте назовем его «AdminAuth» и включим в нашу библиотеку. Поскольку мы расширяем Auth, нам нужно переписать только пару методов, чтобы все заработало, как мы и предполагали.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
namespace Admin\Libraries;
use Admin\Models\Admin as Admin, Laravel\Auth\Drivers\Eloquent as Eloquent, Laravel\Hash, Laravel\Config;
 
class AdminAuth extends Eloquent {
 
/**
 * Get the current user of the application.
 *
 * If the user is a guest, null should be returned.
 *
 * @param int|object $token
 * @return mixed|null
 */
public function retrieve($token)
{
    // We return an object here either if the passed token is an integer (ID)
    // or if we are passed a model object of the correct type
    if (filter_var($token, FILTER_VALIDATE_INT) !== false)
    {
        return $this->model()->find($token);
    }
    else if (get_class($token) == new Admin)
    {
        return $token;
    }
}
 
/**
 * Attempt to log a user into the application.
 *
 * @param array $arguments
 * @return void
 */
public function attempt($arguments = array())
{
    $user = $this->model()->where(function($query) use($arguments)
    {
        $username = Config::get(‘admin::auth.username’);
 
        $query->where($username, ‘=’, $arguments[‘username’]);
 
        foreach(array_except($arguments, array(‘username’, ‘password’, ‘remember’)) as $column => $val)
        {
            $query->where($column, ‘=’, $val);
        }
    })->first();
 
    // If the credentials match what is in the database, we will just
    // log the user into the application and remember them if asked.
    $password = $arguments[‘password’];
 
    $password_field = Config::get(‘admin::auth.password’, ‘password’);
 
    if ( ! is_null($user) and Hash::check($password, $user->{$password_field}))
    {
        return $this->login($user->get_key(), array_get($arguments, ‘remember’));
    }
 
    return false;
}
 
protected function model(){
    return new Admin;
}
 
}

Теперь, когда мы создали драйвер, мы должны сообщить Laravel. Мы можем использовать метод start.php для этого в нашем файле start.php .

1
2
3
Auth::extend(‘adminauth’, function() {
    return new Admin\Libraries\AdminAuth;
});

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

1
Config::set(‘auth.driver’, ‘adminauth’);

Прежде чем мы сможем что-то направить, нам нужно создать контроллер. Давайте создадим наш контроллер панели мониторинга, который мы увидим после входа в систему.

Поскольку мы хотим, чтобы это отображалось в корне нашего пакета (т. home.php мы определили ранее), нам нужно вызвать этот home.php . Laravel использует ключевое слово «home», чтобы определить, что вы хотите отображать в корне вашего приложения или пакета.

Расширьте свой базовый контроллер и создайте представление индекса. Сейчас просто верните «Hello World», чтобы мы могли убедиться, что все работает хорошо.

1
2
3
4
5
6
7
class Admin_Home_Controller extends Admin_Base_Controller {
 
    public function get_index(){
        return ‘Hello World’;
    }
 
}

Теперь, когда наш контроллер настроен, мы можем направить его. Создайте routes.php в вашем комплекте, если вы этого еще не сделали. Подобно нашему основному приложению, каждый пакет может иметь свой собственный файл маршрутов, который работает идентично.

1
2
3
Route::controller(array(
    ‘admin::home’,
));

Здесь я зарегистрировал домашний контроллер, который Laravel автоматически назначит / . Позже мы добавим наш контроллер входа в массив.

Если вы переходите к /admin (или к тому, что вы определили ранее) в браузере, вы должны увидеть «Hello World».


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

Поскольку мы не расширяемся, нам нужно настроить пару вещей перед началом, а именно: спокойные макеты, правильный драйвер аутентификации и наши ресурсы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
class Admin_Login_Controller extends Controller {
 
    public $restful = true;
 
    public function __construct(){
 
        parent::__construct();
 
        Config::set(‘auth.driver’, ‘adminauth’);
 
        Asset::container(‘header’)->bundle(‘admin’);
        Asset::container(‘header’)->add(‘bootstrap’, ‘css/bootstrap.min.css’);
 
    }
 
}

Давайте также создадим наш взгляд. Мы собираемся использовать Blade — шаблонизатор Laravel — чтобы немного ускорить процесс. В вашем каталоге пакетов создайте каталог ‘login’ и файл ‘index.blade.php’ внутри него.

Мы откроем стандартную структуру HTML-страницы и отобразим ресурсы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<!DOCTYPE html>
<html lang=»en»>
<head>
    <meta charset=»utf-8″>
    <title>Login</title>
    {{Asset::container(‘header’)->styles()}}
    <!—[if lt IE 9]>
    <script src=»http://html5shim.googlecode.com/svn/trunk/html5.js»></script>
    <![endif]—>
</head>
<body>
 
</body>
</html>

Теперь давайте удостоверимся, что представление создается в контроллере. Поскольку мы используем контроллеры restful, мы можем использовать глагол get в нашем методе.

1
2
3
public function get_index(){
    return View::make(‘admin::login.index’);
}

Потрясающие! Теперь мы готовы начать создавать нашу форму, которую мы можем создать с помощью класса Form .

01
02
03
04
05
06
07
08
09
10
11
12
{{Form::open()}}
 
{{Form::label(‘username’, ‘Username’)}}
{{Form::text(‘username’)}}
 
{{Form::label(‘password’, ‘Password’)}}
{{Form::password(‘password’)}}
 
{{Form::submit(‘Login’, array(‘class’ => ‘btn btn-success’))}}
 
{{Form::token()}}
{{Form::close()}}
Форма входа

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

Поскольку мы публикуем форму для себя и используем restful-контроллеры, нам просто нужно создать метод post_index и использовать его для обработки нашего логина. Если вы никогда раньше не использовали Auth, то прежде чем двигаться дальше, посмотрите документацию .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public function post_index(){
 
    $creds = array(
        ‘username’ => Input::get(‘username’),
        ‘password’ => Input::get(‘password’),
    );
 
    if (Auth::attempt($creds)) {
        return Redirect::to(URL::to_action(‘admin::home@index’));
    } else {
        return Redirect::back()->with(‘error’, true);
    }
 
}

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

1
2
3
@if(Session::get(‘error’))
    Sorry, your username or password was incorrect.
@endif

Мы также должны выйти из системы; Итак, давайте создадим метод get_logout и добавим следующее. Это позволит выйти из системы, а затем перенаправить ее при посещении /admin/login/logout .

1
2
3
4
public function get_logout(){
    Auth::logout();
    return Redirect::to(URL::to_action(‘admin::home@index’));
}

Последнее, что мы должны сделать, это добавить контроллер входа в наш файл маршрутов.

1
2
3
4
Route::controller(array(
    ‘admin::home’,
    ‘admin::login’,
));

Чтобы запретить людям обходить наш экран входа в систему, нам нужно отфильтровать наши маршруты, чтобы определить, являются ли они авторизованными пользователями. Мы можем создать фильтр в нашем routes.php и прикрепить его к нашему базовому контроллеру для фильтрации перед отображением маршрута.

1
2
3
Route::filter(‘auth’, function() {
    if (Auth::guest()) return Redirect::to(URL::to_action(‘admin::login’));
});

На данный момент все, что осталось сделать, это вызвать это в конструкторе нашего базового контроллера. Если бы мы расширили наш контроллер входа в систему с нашей базы, то у нас был бы бесконечный цикл, который в конечном итоге истек бы.

1
$this->filter(‘before’, ‘auth’);

Ранее мы создали наш макет main.blade.php ; Теперь мы собираемся сделать что-то с этим. Давайте получим HTML-страницу и наши ресурсы.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang=»en»>
  <head>
    <meta charset=»utf-8″>
    <title>{{$title}}</title>
    {{Asset::container(‘header’)->styles()}}
    <!—[if lt IE 9]>
    <script src=»http://html5shim.googlecode.com/svn/trunk/html5.js»></script>
    <![endif]—>
  </head>
  <body>
    <div class=»container»>
        {{$content}}
    </div>
  {{Asset::container(‘footer’)->scripts()}}
  </body>
  </html>

Вы заметите, что я также повторил несколько переменных: $title и $content . Мы сможем использовать магические методы из нашего контроллера для передачи данных через них. Я также вставил $content в контейнер div , для которого Bootstrap предоставит стиль.

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

1
2
<h1>Hello</h1>
<p class=»lead»>This is our dashboard view</p>

Сохраните это как index.blade.php в index.blade.php views/dashboard внутри вашего пакета.

Теперь нам нужно настроить наш контроллер на использование макета и просмотр файлов, которые мы только что создали. В методе get_index который мы создали ранее, добавьте следующее.

1
2
$this->layout->title = ‘Dashboard’;
$this->layout->nest(‘content’, ‘admin::dashboard.index’);

title — это магический метод, который мы можем затем отобразить как переменную в нашем макете. Используя nest , мы можем включить представление внутри макета прямо из нашего контроллера.


Чтобы ускорить процесс, Laravel предоставляет нам простой способ выполнения кода из командной строки. Они называются «Задачи»; Хорошая идея — создать нового, чтобы легко добавить нового пользователя в базу данных.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use Laravel\CLI\Command as Command;
use Admin\Models\Admin as Admin;
 
class Admin_Setup_Task {
 
public function run($arguments){
 
    if(empty($arguments) || count($arguments) < 5){
        die(«Error: Please enter first name, last name, username, email address and password\n»);
    }
 
    Command::run(array(‘bundle:publish’, ‘admin’));
 
    $role = (!isset($arguments[5])) ?
 
    $data = array(
        ‘name’ => $arguments[0].’
        ‘username’ => $arguments[2],
        ’email’ => $arguments[3],
        ‘password’ => Hash::make($arguments[4]),
        ‘role’ => $role,
    );
 
    $user = Admin::create($data);
 
    echo ($user) ?
 
}
 
}

Laravel пройдет через массив аргументов; мы можем считать их, чтобы гарантировать, что мы получаем именно то, что мы хотим. Если нет, мы повторим ошибку. Вы также заметите, что мы используем класс Command для запуска bundle:publish . Это позволит вам запустить любую задачу командной строки, встроенную в Laravel, внутри вашего приложения или пакета.

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

1
php artisan admin::setup firstname lastname username [email protected] password

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

Пакет может быть любым: от админ-панели, как мы создали сегодня, до анализаторов Markdown — или даже всего Zend Framework (я не шучу). Все, что мы рассмотрели здесь, поможет вам написать замечательные пакеты для Laravel, которые можно опубликовать в каталоге пакетов Laravel .

Узнайте больше о создании пакетов Laravel здесь, на Nettuts +.