Если вы дочитали цикл про создание компонента с нуля на Joomla до этой статьи, то вы скорее всего уже пробовали что-то создать. И как в любом нормальном программном продукте, в вашем, используется база данных. В базе соответственно есть некие записи. Выводить их мы научились в прошлой статье. А как же их туда вносить? Об этом и поговорим ниже.

о идее, в системах на MVC за такие действия должна отвечать модель. А контроллер лишь передает ей указания. Мы пока не работаем с моделями, поэтому все будем делать в контроллере. Так будет проще и наглядней. И по секрету скажу, что 90% программистов так и делают. А еще 5, хоть и пытаются всю логику с БД засунуть в модель, все равно делают часть работы в контроллере. Это вообще тема отдельной статьи. Как-нибудь напишу, как работать с моделями в Yii и что это вообще такое - модели. Дело в том, что зачастую программисты не читают первоисточники на английском языке, а довольствуются лишь крупицами переведенной информации. Между тем, получить хороший перевод за разумные деньги можно довольно просто, достаточно найти бюро Дока в Москве, и ребята все сделают за вас. Но я отошел от темы. Вернемся к нашему компоненту.

Итак к примеру у нас есть такая табличка

CREATE TABLE IF NOT EXISTS `jml_votes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ip` varchar(30) DEFAULT NULL,
  `contentid` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `contentid` (`contentid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

В таблице содержатся факт голосования, отдал ли пользователь за ту или иную статью свой голос. Голос может быть как положительным так и отрицательным. Один и тот же пользователь, не может отдать два раза голос за одну и ту же статью. Блокировать будем на основе ip пользователя.

Сами голоса, а точнее их количество содержаться в поле votes таблицы jml_content. По умолчанию в Joomla такого поля нет. Сделаем его

ALTER TABLE  `jml_content` ADD  `votes` INT NOT NULL

Теперь нам нужно эти самые голоса отправлять. Вставим в любое место нашего шаблона пару ссылок

<div class="voter">
<a href="javascript:void(0);" onclick="vote.call(this,('up',<?=$id?>);"  class="voter_up">up</a>
<a href="javascript:void(0);" onclick="vote.call(this,'down',<?=$id?>);" class="voter_down">down</a>
<span><?=$votes?></span>
</div>

Как их оформить внешне, решать вам. В своем проекте, я сделал в виде традиционных кулачков, вверх и вниз. 

Теперь надо написать функцию vote

function vote(arrow,id){
	jQuery.post('/index.php?option=com_moy_component&task=vote',{id:id,arrow:arrow},function(resp){
		if(resp.res==1){
			jQuery('.voter a').remove();
			jQuery('.voter span').html(resp.msg);
		}
	}
	,'json');
}

Обратите внимание на последний параметр метода post. Он говорит jQuery, что будет использоваться JSON ответ. Я использую в своем проекте jQuery. Чтобы эта библиотека заработала в Joomla надо подключать ее в режиме

jQuery.noConflict();

Конечно, все зависит от шаблона. Но лишним не будет.

Итак, мы послали данные на сервере. Теперь надо их обработать в контроллере

function vote(){
	if( !uno::exists('content','id='.intval($_REQUEST['id'])) )
		exit(json_encode(array('res'=>0,'msg'=>'content not found')));
	if( uno::exists('votes',array('contentid='.intval($_REQUEST['id']),'ip='.uno::_($this->myip()))) )
		exit(json_encode(array('res'=>0,'msg'=>'you already voted')));
	
	uno::insert('votes',array('contentid'=>intval($_REQUEST['id']),'ip'=>$this->myip()));
	uno::update('content',array('votes=votes'.($_REQUEST['arrow']=='up'?'+':'-').'1'),'id='.intval($_REQUEST['id']));	
	$ball = uno::exists('content','id='.intval($_REQUEST['id']),'votes');
	exit(json_encode(array('res'=>1,'msg'=>$ball)));
}

 Я вновь использовал класс uno. По моему он очень удобен. Что же му туту сделали: проверяем есть ли такой материал, проверяем голосовали ли уже. Если все ок, заносим в votes факт голосования с нашего ip за этот материал, и обновляем общее количество баллов. В ответ вносим новый балл (вдруг, пока мы думали, кто-то проголосовал за эту же статью)

осталось только написать метод myip

private function myIP(){
	$ipa = explode( ',',@$_SERVER['HTTP_X_FORWARDED_FOR'] );
	return isset($_SERVER['HTTP_X_REAL_IP'])?$_SERVER['HTTP_X_REAL_IP']:(isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:(!empty($ipa[0])?$ipa[0]:'92.50.156.138'));
}

Вот и все.

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

Сергей111
# Сергей111 15.06.2015 19:08
Цитата:
И по секрету скажу, что 90% программистов так и делают.
...
Дело в том, что зачастую программисты не читают первоисточники на английском языке, а довольствуются лишь крупицами переведенной информации.
че за бред, если ты так делаешь, то это не означает что большинство так делает
Leroy
# Leroy 16.06.2015 08:22
Если Вы так не делаете, это не значит что все не делают. Среди моих знакомых программистов 95% делают именно так, и это мой блог, и пишу я со своей колокольни.
Сергей111
# Сергей111 15.06.2015 19:10
Цитата:
$_REQUES
$_SERVER
да ты просто гуру по безопасности, про api joomla не слышал?
Leroy
# Leroy 16.06.2015 08:19
Чем intval($_REQUEST['id'])) отличается от jFactory::getApplication()->input->get('id', 0 , 'INT') ?
Открываем доки https://docs.joomla.org/Retrieving_request_data_using_JInput и видим что есть бесполезная регулярка, которая делает ровно то же что и intval
Leroy
# Leroy 16.06.2015 08:21
Даже интересно, где в моем коде есть дыра в безопасности? Все значения без обработки не подставляются, все экранируется. Чем апи поможет в безопасности?