Яндекс.Метрика

    Песочница

    Добавление аватара к пользователю в Joomla 1.7

    Эта статья посвящена разбору стандартного компонента Joomla 1.7 com_users


    Буквально недавно столкнулся с одной из маленьких проблем.
    Делал сайт на Joomla 1.7, но в момент, когда сайт почти был закончен,
    потребовалось поставить пользователю аватар.

    Не найдя решения для стандартного компонента ( не для CB или JoomSocial ) в интернете, я решил разобраться в его работе.

    Первым делом, посмотрим в БД, чтобы разобраться, как храняться данные о пользователе.
    Внутри БД мы увидим 3 таблицы связанные с пользователями.
    Нас будет интересовать одна: jos_users (jos_ — это префикс таблиц, у каждого свой).
    Увидев, что таблица пользователей имеет вполне себе стандартную простую структуру полей, добавим поле avatar к этой таблице с типом текст ( нет особого смысла хранить всю картинку в БД, мы будем хранить там ссылку на файл, который будет лежать на сервере ).
    Как известно, в Joomla 1.7 поля для форм задаются в xml файлах, которые находятся в папке com_users\models\forms найдем там форму информации пользователя, этот файл называется: profile.xml
    Добавим поле ввода аватара
    <field name="avatar" type="file" id="avatar"
    		description="COM_USERS_PROFILE_AVATAR_DESC"
    		label="COM_USERS_PROFILE_AVATAR_LABEL"
    		message="COM_USERS_PROFILE_AVATAR_MESSAGE"
    		required="false"
    		size="30"
    />
    

    Ниже константы, которые находятся в общих языковых файлах.
    Там устанавливается описание, label и всплывающая подсказка
    description="COM_USERS_PROFILE_AVATAR_DESC"
    label="COM_USERS_PROFILE_AVATAR_LABEL"
    message="COM_USERS_PROFILE_AVATAR_MESSAGE"

    Это поле только лишь добавит его в форму.
    Дальше необходимо из формы закачать этот файл на сервер и записать ссылку в БД.
    Сохранением данных занимается модель, но,
    она работает не с массивом $_POST и $_FILES, а с переменной $data,
    которую принимает как аргумент.
    Следует, что необходимо добавить массив $_FILES к переменной $data.
    Для этого идем в контроллер, отвечающий за это.
    Путь к файлу: com_users\controllers\profile.php
    Внутри функции public function save()
    ищем присвоение ПОСТ данных в переменную, выглядит это так:
    $data = JRequest::getVar('jform', array(), 'post', 'array');
    Следующей строкой добавляем:
    $data['avatar']=$_FILES;

    Теперь переходим в модель.
    Путь к файлу: com_users\models\profile.php

    В нем, мы для начала добавим одну функцию перед функцией save():
    private function checkAvatar($avatar,&$data)
    {
    	/*Если поле осталось пустое, то ставить картинку по умолчанию*/
    	if(strlen(trim($avatar))==1)
    			$data['avatar'] = '/images/avatars/no_avatar.gif';
    	else
    		unset($data['avatar']);//чтобы не затирался аватар при изменении
    }
    

    Смысл функции станет понятен ниже.

    Теперь изменим функцию save(), добавив обработку поля $data['avatar']

    $db = JFactory::getDBO(); // подключаемся к базе
    	$query = "SELECT `avatar` FROM `#__users` WHERE `id`='".$user->get('id')."' LIMIT 1;"; // Создаем запрос 
    $db->setQuery( $query);// выполняем запрос
    $avatar=$db->loadResult();
    //Uploading avatar to server		
    if(strlen(trim($data['avatar']["jform"]['size']['name']))==1){
    	$this->checkAvatar($avatar,$data);
    }
    else {
    	$avatar_path='';
    	if($data['avatar']["jform"]['size']['avatar'] > 1024*3*1024)
    	{
    		echo "Размер файла превышает 3МБ";
    		$this->checkAvatar($avatar,$data);				
    	}
    	else if(is_uploaded_file($data['avatar']['jform']['tmp_name']['avatar']))
    	{
    		$avatar_path="/images/avatars/".$data['avatar']['jform']['name']['avatar'];
    		unlink($data['avatar']['jform']['tmp_name']['avatar']);//удаление файла с таким же именем
    		move_uploaded_file($data['avatar']['jform']['tmp_name']['avatar'],JPATH_ROOT.$avatar_path);
    		$data['avatar']='http://www.site_name.net'.$avatar_path;
    	} else {
    		echo "Ошибка загрузки файла на сервер"; 
    		$this->checkAvatar($avatar,$data);
    	}
    }

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

    Суть функций предельно проста, смотрим в файлах аватар, если имя файла не пустое, тогда сравниваем размер с максимально допустимым, если всё хорошо, то файл загружается на сервер, затем перемещается в папку $avatar_path с исходным именем.

    Вариант простого создания уникальных аватарок, который я придумал, состоит в том, что мы сохраняем картинку с именем, которое будет, к примеру логин.jpg, логины ведь у нас в БД уникальны.

    Всё, на сервер загрузили, и в БД запишется:
    $data['avatar']='http://www.site_name.net'.$avatar_path;

    Главную часть мы выполнили, осталось всё красиво вывести.

    Для начала выведем аватар там, где и добавляем, т.е. в форме изменения
    информации пользователя.

    В контроллере, внутри функции public function edit(),
    ищем такой блок (в стандарте стоит в начале функции):
    $app			= JFactory::getApplication();
    $user			= JFactory::getUser();
    $loginUserId	= (int) $user->get('id');
    // Get the previous user id (if any) and the current user id.
    $previousId = (int) $app->getUserState('com_users.edit.profile.id');
    $userId	= (int) JRequest::getInt('user_id', null, '', 'array');
    


    Т.к. тип мы указали файл в xml файле, то стандартное API джумлы для получения полей: $user->get('avatar'); в данном случае нам не подойдет.
    Поэтому используем прямое подключение к базе:
    $db = JFactory::getDBO(); // подключаемся к базе
    $query = "SELECT `avatar` FROM `#__users` WHERE `id`='".$user->get('id')."' LIMIT 1;"; // Создаем запрос 
    $db->setQuery( $query);// выполняем запрос
    $avatar=$db->loadResult();
    

    Этот код вставляем после найденного выше блока. Таким образом, мы сделали переменную с путём к файлу картинки.

    Далее идем в представление (вид)
    Путь к файлу: /public_html/components/com_users/views/profile/tmpl/edit.php

    Здесь проделываем почти то же самое, только еще и отображаем картинку.
    Ниже строки:
    $lang->load( 'plg_user_profile', JPATH_ADMINISTRATOR );
    вставляем код:
    $app 	= JFactory::getApplication();
    $user 	= JFactory::getUser();
    
    $db = JFactory::getDBO(); // подключаемся к базе
    $query = "SELECT `avatar` FROM `#__users` WHERE `id`='".$user->get('id')."' LIMIT 1;"; // Создаем запрос 
    $db->setQuery( $query);// выполняем запрос
    $avatar=$db->loadResult();
    


    Затем, там, где мы хотим увидеть аватар, вставляем код:
    <div class="profile-edit<?php echo $this->pageclass_sfx?>">
    <?php if ($this->params->get('show_page_heading')) : ?>
    	<?php echo $this->escape($this->params->get('page_heading')); ?>
    <?php endif; ?>
    
    <div class="img-avatar">
    	<img src="<?= $avatar;?>" style="width:100px;height:100px;" />
    </div>
    

    Смотрите не вставьте в цикл. Я вставлял сразу перед тэгом form.

    Всё, теперь мы можем увидеть наш аватар при изменении профиля.

    Осталось отобразить его в профиле.
    Путь к файлу: /public_html/components/com_users/views/profile/tmpl/edit.php

    Ниже строки: jimport('joomla.user.helper');
    Определяем наш путь к аватарке.
    $user 	= JFactory::getUser();
    $db = JFactory::getDBO(); // подключаемся к базе
    $query = "SELECT `avatar` FROM `#__users` WHERE `id`='".$user->get('id')."' LIMIT 1;"; // Создаем запрос 
    $db->setQuery( $query);// выполняем запрос
    $avatar=$db->loadResult();
    


    Далее, по аналогии с остальными полями, вставляем код:
    <dt>
    	<?php echo JText::_('COM_USERS_PROFILE_AVATAR_LABEL'); ?>
    </dt>
    <dd>	
    	<img src="<?php echo $avatar; ?>" style="width:100px;height:100px;"/>
    </dd>	
    

    там, где хотим видеть картинку.
    Затем редактируем языковые файлы и всё.
    Готово.