Дмитрий

Дмитрий

С нами с 23 апреля 2015; Место в рейтинге пользователей: #325
Дмитрий
24 июня 2015, 17:17
0
В чем проблема, не понятно.
Дмитрий
22 июня 2015, 19:15
0
Например, я делаю аякс запрос на ресурс со сниппетом. Ресурс должен быть без шаблона, иначе вместе с данными загрузится шаблон. (эдакая матрешка, шаблон в шаблоне). Допустим, содержимое ресурса следующее:
[[!pdoPage?
    &element=`ads_all_pages_pdo`
    &context=`[[*context_key]]`
    &action=sell
    &item_type=all
    &status_filter=online
    &limit=`10`
]]
<div class="pagination">
[[!+page.nav]]
</div>
Значит при выводе данных, странички будут с линком на ресурс который был вызван.
т.е. при переходе на другую страницу, я автоматом получу страницу с данными но без шаблона. :D
Дмитрий
22 июня 2015, 19:08
0
Огромное спасибо! Вот так вроде бы работает:
Линк: warframe.trade/testpages.html
$limit = $scriptProperties['limit'];
if ($page==1) $scriptProperties['offset'] = 0; // иначе не показывает первую страницу
$OFFSET = 'LIMIT '.$scriptProperties['offset'].','.$limit;
...
if ($result_count->num_rows > 0) {
	while($row = $result_count->fetch_assoc()) {
		$sumrows[] = $row;
	}
}
$sum_rows = $sumrows[0]['count'];
...
$number = $scriptProperties['offset']+1;
...
$modx->setPlaceholder('page.total', $sum_rows);
return $SearchResultTableWrapper;
Наверное откажусь от аякса, это не рентабельно + геморно. По крайней мере сделать Get на этой же странице, кажется гораздо проще.

Дмитрий
22 июня 2015, 18:39
0
Однако, вы правы. Теперь я примерно понял как работает pdoPage. Он в считает страницы и выводит саму пагинацию с кнопочками, а контент разумеется обрабатывает мой же сниппет. :)
Дмитрий
22 июня 2015, 18:29
0
Да, не заметил, что речь о выборке с оффсетом.
Дмитрий
22 июня 2015, 18:11
0
Без pdoPage выводит собранный чанк целиком.
Перед тем, как задействовать pdoPage меняю:
$SearchResultTableItems = '';
...
$SearchResultTableItems .= $modx->getChunk('ads_items', Array(
на
$SearchResultTableItems = Array();
...
$SearchResultTableItems[] = $modx->getChunk('ads_items', Array(
и вывожу не
return $SearchResultTableWrapper
а
return $SearchResultTableItems;
Иначе ведь, pdoPage не поймет как нужно разделить цельный html код на страницы?
Дмитрий
22 июня 2015, 16:31
0
Не знаю, как и в прошлый раз получаю вместо строк Array
Дмитрий
22 июня 2015, 08:52
0
К сожалению, все делает один человек.
Что реализовано:
1. Пользователь выбирает из mysql таблицы предмет любого типа, и выставляет его на покупку либо продажу.
2. Данные с id пользователя, id-предмета, его характеристиками (они могут быть разные, скажем уровень раскачки предмета) и ценой идут в таблицу buy либо sell.
3. Допустим 100 пользователей закинуло в эти базы свои заявки, по 20-30 заявок каждый. Итого 2000-3000 заявок.

Что обернуть в pdoTools:
4. Показ сразу всех заявок на странице «Все заявки». На данный момент, я ограничил запрос к выборке buy и sell до 30, иначе, загружается слишком много данных на одну страницу. Настолько, что страница махом отжирает 200мб оперативки, и пользоваться сайтом становится проблематично.
Поэтому нужна многостраничность, т.е. нужен постраничный вывод строк таблицы.

PS:
Почти закончил решение без pdoTools, аля костыль, но понимаю что это не дело. Опробовав однажды запрос по модели, почувствовал такооое облегчение.
Дмитрий
21 июня 2015, 16:23
0
Я так много на быдлокодил, что уже путаюсь при попытке встраивания чего-то стороннего. Пожалуй, откажусь от идеи использовать pdoPage. Потом, когда-нибудь, когда это не будет столь критично по срокам для самого себя.

Когда писал этот топик совсем отчаялся сделать красиво с pdo. И поэтому решил забить на него, и практически разобрался со своим же кодом. Пагинация работает. Осталось продумать алгоритм для вывода страниц like pdoPage.

Простите, за потраченное время. То, что «почти получилось», на деле отказалось работать, видимо я снова что-то упустил. Уже нет сил плавать в чем-то непонятном. И схватиться не за что. Читал про pdoTools на docs.modx.pro/, но так ине понял как это работает. Видимо читатель должен знать какие-то основы, которые я даже не знаю как гуглить. Надо взять в привычку изучать ВСЮ документацию, вероятно тогда и проблем не будет. ;)

Но если интересно, то вот мой быдлокод, приятного чтива xD):
Ссылка на страницу
Ресурс «Все объявления»:
[[!result_tables_new_all?
  &context=`[[*context_key]]`
  &action=buy
  &item_type=all
  &status_filter=online
]]
Сниппет «result_tables_new_all», который используется на разных страницах, с немного разными данными:
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

//id пользователя который запускает сниппет
$user = $modx->getUser();
$real_id = $user->get('id');

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH'])) {
	$context = $modx->context->key;
	$action = $_POST['action'];
	$item_type = $_POST['item_type'];
	$filter_mod_count = $_POST['filter_mod_count'];
	$status_filter = $_POST['status'];
	$ajax = 1;
	if($_POST['from_profile'] == 1){
		$user_name = $_POST['user_name'];
		$user_id = $_POST['user_id'];
		$user_edit = 1;
		$from_profile = $_POST['from_profile'];
	}
}
//Добавим Unixtime для треба онлайна
$mysqli = $modx->runSnippet('mysql');
	switch($action){
		case 'buy':
			$TABLE = '`darvo_a_buy`';
			break;
			
		case 'sell':
			$TABLE = '`darvo_a_sell`';
			break;
	}
	//Проверка статуса Онлайн
	$status = Array();
	switch($status_filter){
		case 'offline':
			$WHERE = '';
			$status['color'] = 'red';
			$status['status'] = 'Offline';
			break;
		case 'online':
			$WHERE = 'WHERE `unixtime`>= unix_timestamp() - 60';
			$status['color'] = 'greenyellow';
			$status['status'] = 'Online';
			break;
	}
	
	$JOIN_UNIXTIME = 'LEFT JOIN `darvo_online_users` ON  '.$TABLE.'.`user_id` = `darvo_online_users`.`id`';
	$JOIN_USERNAME = 'LEFT JOIN `modx_user_attributes` ON '.$TABLE.'.`user_id` = `modx_user_attributes`.`id`';
	$JOIN = $JOIN_UNIXTIME.' '.$JOIN_USERNAME;
	$SELECT = $TABLE.".`id`,".$TABLE.".`user_id`,".$TABLE.".`item_type`,".$TABLE.".`item_id`,".$TABLE.".`item_count`,".$TABLE.".`item_price`,`darvo_online_users`.`unixtime`,`modx_user_attributes`.`fullname`";
	
	$page = $_GET['page'];
	if (!preg_match('/^[0-9]+$/', $page)){
	   $page = 1;
	}
	
	$limit = 10;
	if($page>1){
		$current_page = $page*$limit;
	}else{
		$current_page = 1;
	}
	$OFFSET = 'LIMIT '.$current_page.','.$limit;

	//если запрос идет из пользовательского профиля
	if($from_profile == 1){
		if($item_type=='all'){
			$result = $mysqli->query("SELECT * FROM ".$TABLE." ".$JOIN." ".$WHERE." AND `user_id` = ".$user_id." ORDER BY `id` DESC");
		}else{
			$result = $mysqli->query("SELECT * FROM ".$TABLE." ".$JOIN." ".$WHERE." AND `user_id` = ".$user_id." AND `item_type`='".$item_type."' ORDER BY `id` DESC");
		}
	}else{
		if($item_type=='all'){
			$result = $mysqli->query("SELECT ".$SELECT." FROM ".$TABLE." ".$JOIN." ".$WHERE." ORDER BY `id` DESC ".$OFFSET);
			$result_count = $mysqli->query("SELECT COUNT(*) AS 'count' FROM ".$TABLE." ".$JOIN." ".$WHERE);
		}else{
			$result = $mysqli->query("SELECT ".$SELECT." FROM ".$TABLE." ".$JOIN." ".$WHERE." AND `item_type`='".$item_type."' ORDER BY `id` DESC ".$OFFSET);
			$result_count = $mysqli->query("SELECT COUNT(*) AS 'count' FROM ".$TABLE." ".$JOIN." ".$WHERE." AND `item_type`='".$item_type."'");
		}
	}
	
//Общее количество строк
	if ($result_count->num_rows > 0) {
		while($row = $result_count->fetch_assoc()) {
			$sumrows[] = $row;
		}
	}
	$sum_rows = $sumrows[0]['count'];
	$sum_pages = ceil($sum_rows/$limit);

	$pages = $modx->GetChunk('pages',Array(
		'1'=>intval($page-2),
		'2'=>intval($page-1),
		'3'=>intval($page),
		'4'=>intval($page+1),
		'5'=>intval($page+2),
	));
	//return $pages;
	
	if ($result->num_rows > 0) {
		while($row = $result->fetch_assoc()) {
			$founds[] = $row;
		}
	}
	
//return mysqli_error($mysqli);
$SearchResultTableItems = '';
$number = 1;
foreach($founds as $found){
	if($from_profile != 1){
		$user_name = $found['fullname'];
		$user_id = $found['user_id'];
	}
		
	$result = $mysqli->query("SELECT `img_".$context."`, `title_".$context."`, `count` FROM `darvo_mods_wiki` WHERE `id`= '".$found['item_id']."'");
	if ($result->num_rows > 0) {
		while($row = $result->fetch_assoc()) {
			$item = $row;
		}
	}
	
	$item_maxcount = $item['count'];
	$item_count = $found['item_count'];
	
	switch($filter_mod_count){
		case 'full':
			if($item_count != $item_maxcount){ goto end_f; }
			break;
		case 'null':
			if($item_count != 0){ goto end_f; }
			break;
		default:
			break;
	}
	$item_type = $found['item_type'];

	//объявления с открытой ценой
		$item_price = $found['item_price'];
		if($found['item_price']==0){
			$item_price = 'ваша цена';
		}
		
	//Выведем кнопку удалить, если:
		if(($from_profile == 1)and($real_id == $user_id)){
			$btn_chat = $modx->GetChunk('btn_del',Array(
				'del_id' => $found['id']
			));
		}else{
			$btn_chat = $modx->GetChunk('btn_chat',Array(
				'item_type' => $item_type,
				'item_price' => $found['item_price'],
				'action' => $action,
			));
		}
	
	$SearchResultTableItems .= $modx->getChunk('result_table_items', Array(
		'action' => $action,
		'item_type' => $item_type,
		'status' => $status['status'],
		'status_color' => $status['color'],
		'user_id' => $user_id,
		'user_name' => $user_name,
		'item_id' => $found['item_id'],//для линка на страницу информации
		'item_count' => $item_count,
		'item_price' => $item_price,
		'item_img' => $item['img_'.$context],
		'item_name' => $item['title_'.$context],
		'item_maxcount' => $item_maxcount,
		'part_name' => $part_name['img_'.$context],
		'act_msg' => $act_msg,
		'btn_chat' => $btn_chat,
		'btn_del' => $btn_del,
		'number' => $number,
		'all' => 1,
	));

$number++;
end_f:
}

return_res:
$result = $mysqli->query("SELECT `title_".$context."` FROM `darvo_mods_wiki` WHERE `id`= '".$item_id."'");
if ($result->num_rows > 0) {
	while($row = $result->fetch_assoc()) {
		$item = $row;
	}
}

$SearchResultTableWrapper = $modx->getChunk('result_table_items_wrap', Array(
	'action' => $action,
	'item_name' => $item['title_'.$context],
	'SearchResultTableItems' => $SearchResultTableItems,
	'all' => 1,
	'ajax' => $ajax,
	'user_name' => $user_name,
	'user_id' => $user_id,
	'user_edit' => $user_edit,
	'from_profile' => $from_profile,
));

mysqli_close($mysqli);
return $SearchResultTableWrapper;
Чанк «result_table_items» данные таблицы:
<tr class="[[!+status]]">
<!--<td>[[$icons-sell]]</td>-->
<td class="hidden-xs hidden-sm col-sm-1 col-md-1 text-center"><label>[[+number]]</label></td>
<td class="col-xs-3 col-sm-5 col-md-3 text-left">[[+item_type:is=`mod`:then=`[[+item_count]]/[[+item_maxcount]]`:else=``]] <a href="item/[[+item_id]]/">[[+item_name]]</a></td>
<td class="col-xs-1 col-sm-1 col-md-1 text-center [[+action:is=`trade`:then=`hidden`:else=``]]">[[+item_price]]</td>
<td class="col-xs-2 col-sm-2 col-md-2 text-center"><a href="/users/[[+user_id]]/" title="[[-+region]]ru" style="color:[[!+status_color]]">[[+user_name]]</a></td>
<td class="hidden-sm hidden-xs text-center">[[+btn_chat]]
</td>
</tr>
Чанк «result_table_items_wrap» заголовок таблицы + фильтры:
[[+ajax:is=`1`:then=``:else=`[[+all:is=`1`:then=`<div class="form-inline">
<div class="form-group">
<select id="action" class="searching form-control">
    <option value="buy">Куплю</option>
    <option value="sell">Продам</option>
</select>
</div>
<div class="form-group">
<select id="item_type" class="searching form-control">
    <option value="all">Все</option>
    <option value="mod">Только Моды</option>
    <option value="pack">Только Паки</option>
    <option value="item">Только Прайм части</option>
</select>
</div>
<div class="form-group">
<select id="status" class="searching form-control">
    <option value="online">Только Online</option>
    <option value="all">Все объявления</option>
</select>
</div>
</div>
<div id="search_result" style="position:relative">`:else=``]]`]]
<table id="myTable1" class="myTable table table-hover table-striped">
	<thead>
		<tr>
			<th class="hidden-xs hidden-sm col-sm-1 col-md-1 text-center"><label>№</label></td>
			<th class="col-xs-3 col-sm-5 col-md-3 text-left"><label>Предмет</label></th>
			<th class="col-xs-1 col-sm-1 col-md-1 text-center">
			<label class="hidden-sm hidden-xs">Стоимость</label><label><img src="img/favicon.ico"></label>
			</th>
			<th class="col-xs-1 col-sm-1 col-md-1 text-center [[+item_type_to:is=`mod`:then=``:else=`hidden`]]">
			<label>Ранг</label>
			</th>
			<th class="col-xs-2 col-sm-2 col-md-2 text-center"><label>Игрок</label></th>
			<th class="col-xs-2 col-sm-1 text-center hidden"><label>Статус</label></th>
			<th class="hidden-sm hidden-xs col-md-1 text-center"><label>Связь</label></th>
		</tr>
	</thead>
	[[+SearchResultTableItems]]
	</table>
[[+ajax:is=`1`:then=``:else=`[[+all:is=`1`:then=`</div>
<script>
$(document).ready(function(){
	$('.searching').change(function(){
		search_items($('#action').val(),$('#item_type').val(),$('#status').val());
		//console.log($('#item_type').val()+','+$('#action').val());
		return false;
	});
[[+from_profile:is=`1`:then=`$('.del').click(function(){
		act = 'del_'+$('#action').val();
		var $btn = $(this);
		console.log($btn.closest('tr'));
			$.ajax({
				headers: {'X-Requested-With': 'XMLHttpRequest'},
				method: "POST",
				url: "[[~307]]",
				datatype: "json",
				data: { 'action': act, 'action_id': $btn.attr('alt') },
				beforeSend: function() {
					$('#search_result').append('<div id="loading" style="position: absolute;  top: 0px;  left: 0px;  width: 100%;  height: 100%;  background-color: rgba(255,255,255,0.5);"><div style="margin: 0 auto;  background: url(img/misc/ajaxloader.gif?1) no-repeat; background-size: contain; width: 128px;  height: 128px;"></div></div>');
				}
			})
			.done( function( data ) {
				$('#loading').remove();
				if(data == 'err'){
					alert('Что-то пошло не так. Обратитесь к администратору.');
				}else{
					$btn.closest("tr").addClass('hide');
				}
			})
			.fail( function( data ) {
				alert('Что-то пошло не так. Обратитесь к администратору.');
			});
		});`:else=``]]
});

function search_items(action,item_type,status){
	$.ajax({
		headers: {'X-Requested-With': 'XMLHttpRequest'},
		method: "POST",
		url: '[[~320]]',
		datatype: "html",
		data: {action: action, item_type: item_type, status: status, context: '[[*context_key]]', user_name: '[[+user_name]]', from_profile: '[[+from_profile]]', user_id: '[[+user_id]]'},
		beforeSend: function(){
			$('#search_result').append('<div id="loading" style="position: absolute;  top: 0px;  left: 0px;  width: 100%;  height: 100%;  background-color: rgba(255,255,255,0.5);"><div style="margin: 0 auto;  background: url(img/misc/ajaxloader.gif?1) no-repeat; background-size: contain; width: 128px;  height: 128px;"></div></div>');
		}
	})
	.done( function(data) {
		$('#search_result').html(data);
		
		var client = new ZeroClipboard($(".btn-copy"), {
		  moviePath: "//uzerbar.ru/plugins/zclip/ZeroClipboard.swf"
		});

		client.on("load", function(client1) {  
		  client.on("complete", function(client, args) {
			$('.btn-copy').hide(); // скрываем для наглядности кнопку
		  });
		});
[[+from_profile:is=`1`:then=`$('.del').unbind();
$('.del').click(function(){
		act = 'del_'+$('#action').val();
		var $btn = $(this);
		console.log($btn.closest('tr'));
			$.ajax({
				headers: {'X-Requested-With': 'XMLHttpRequest'},
				method: "POST",
				url: "[[~307]]",
				datatype: "json",
				data: { 'action': act, 'action_id': $btn.attr('alt') },
				beforeSend: function() {
					$('#search_result').append('<div id="loading" style="position: absolute;  top: 0px;  left: 0px;  width: 100%;  height: 100%;  background-color: rgba(255,255,255,0.5);"><div style="margin: 0 auto;  background: url(img/misc/ajaxloader.gif?1) no-repeat; background-size: contain; width: 128px;  height: 128px;"></div></div>');
				}
			})
			.done( function( data ) {
				$('#loading').remove();
				if(data == 'err'){
					alert('Что-то пошло не так. Обратитесь к администратору.');
				}else{
					$btn.closest("tr").addClass('hide');
				}
			})
			.fail( function( data ) {
				alert('Что-то пошло не так. Обратитесь к администратору.');
			});
		});`:else=``]]
	})
	.fail( function() {
		alert('Что-то пошло не так. Обратитесь к администратору.');
	});
}
</script>`:else=``]]`]]
Дмитрий
21 июня 2015, 14:51
0
Пытался так сделать, и наконец-то что-то начало получаться!
Моя ошибка в том, что я считал что передавать нужно обычный массив со значениями. Что затем, pdoPage подставит значения в нужный чанк, где это нужно. Ведь это быстрее? Чем загружать уйму лишнего HTML кода? Это мне казалось логичным, т.к. нечто подобное видел в прочих сниппетах, аля регистрация и т.д.

В действительности же, нужно передавать массив, состоящий из чанков заполненными данными. Какой же у меня был фейспалм… Я снова заблуждаюсь?


Вопрос. Из-за Ajax передачи значений переменных сниппету, думаю, что желательно запускать pdoPage прямо внутри сниппета. Такое возможно?
Дмитрий
15 июня 2015, 21:43
0
Залил траффика, сидит до 50 человек одновременно. И думается мне, они слишком часто «долбят» чужой форум. Каким образом возможно поставить таймер? или как назвать.
Дмитрий
14 июня 2015, 20:48
0
Хотя, можно не ипаться, и указать полный путь.
Испугало то, что придется копаться в UserProfile2, чтобы поменять там пути к аватаркам, но вдруг дошло, что это решается очень просто.
Дмитрий
13 июня 2015, 14:41
0
Но вот если бы вам для одного пользователя нужно было бы слать несколько запросов на один и тот же домен (скажем, сперва авторизовать, потом отправить какие-то данные, потом получить данные с какой-то другой страницы от имени этого авторизованного юзера) и всё это в рамках одного php-процесса и подряд — то да, в keep-alive был бы смысл. Ибо на все эти три запроса не было бы повторных соединений, потому что curl держал бы лишь одно.
По сути так и есть, я логинюсь по 1 ссылке, парсю страницу по 2, и отправляю сообщение по 3.

А поскольку вы уверены в немощности вашего vps, значит (скорей всего) нет у вас на сайте такого количества одновременных пользователей и последний вариант — самый вероятный :)
Простите, перепутал с Shared. У меня почему-то ассоциация V — virtual — и значит слабый.
Именно с Шаред переходил на ВПС, с ростом аудитории.

Текущий проект лежит на шаред, на этапе разработки намного выгоднее держать именно Шаред (на своем компе не держу по некоторым причинам). И присутствует мандраж, что на этапе раскрутки, начнутся тормоза на Шареде.

Впрочем, оставил все как есть, судя по всему не так сильно и грузит, как ни странно уходит около 3 секунд на запрос, что практически не заметно, глядя на ajaxloader.

Планирую переходить на более мощное железо, однако, в то же время не хочу торопиться.
Просто не имею понятия какое железо нужно под определенные цели.
Дмитрий
13 июня 2015, 14:19
0
Хост упирается. Не хочет ставить, обосновывая именно мощностью. Видимо бабала тянет))
Дмитрий
13 июня 2015, 02:55
0
она умеет слать http запросы?
Дмитрий
13 июня 2015, 02:55
0
Нода это конечно хорошо, вот только мой VPS не справится. Есть задумки по оживлению сайта, и избавлению от костылей, при переходе на другой сервер, с обрастанием функционала, однако, слишком рано.
Дмитрий
12 июня 2015, 19:46
0
Спасибо за совет!
Дмитрий
21 мая 2015, 12:25
0
Не стоит) Использую как раз таки pdoMenu)
Фишка в том, что данная проблема наблюдается только на виртуальных страницах.