Доступ к элементам неупорядоченного списка HTML в PHP
Я пытаюсь получить доступ к неупорядоченным элементам списка в php, чтобы я мог вставить их в базу данных, мне нужно иметь возможность получить к ним доступ через позицию, но я не уверен, как это сделать в PHP. Я использую jQuery, чтобы список можно было сортировать на стороне клиента. В Javascript он будет доступен с
alert($("#sortable li:first").text() + ' is first ' + $("#sortable li:eq(1)").text() + ' is second ' + $("#sortable li:eq(11)").text() + ' is last');
Список, который я использую, находится на http://jsfiddle.net/mMTtc/
Я просто ищу справку о том, как сохранить эти элементы списка в переменной php, т.е. предположим, что я хотел 6-й элемент, основанный на том, как пользователь упорядочил список. Как бы я это сделал?
Спасибо
3 ответа
Используя следующий код, вы можете отправлять обновления в бэкэнд PHP, когда пользователь изменяет порядок элементов в интерфейсе:
$("#sortable").on("sortupdate", function() {
var dataArr = [];
$("#sortable li").each(function(idx, elem) {
dataArr[idx] = $(elem).html();
});
var dataStr = '{"newOrder":' + JSON.stringify(dataArr) + '}';
$.ajax({
url: "<url_to_php_file>",
data: dataStr
});
// alert(dataStr);
});
Живой пример (часть интерфейса): здесь
Вам придется заменить <url_to_php_file>
с путем к вашему файлу PHP, который выполняет обработку порядка элементов (т.е. сохраняет их в БД). Файл сможет получить доступ к пользовательскому порядку в обычном массиве PHP, используя json_decode($_POST["newOrder"])
т.е.
...
$newOrder = json_decode($_POST["newOrder"]);
for ($i = 0; $i < count($newOrder); $i++) {
echo("The item labeled '" . $newOrder[$i] . "' is placed by the user at index " . $i . ".\n";
/* 1st item: index 0 */
/* 2st item: index 1 */
/* ... */
}
Пример: вы предоставляете пользователю сортируемый список, содержащий элементы: item1, item2, item3 (в этом порядке).
Пользователь помещает item2 перед item1, после чего выполняется вызов AJAX, передавая серверу массив ["item2", "item1", "item3"]
(обратите внимание на порядок). Вышеприведенный фрагмент будет повторяться:
The item labeled 'item2' is placed by the user at index 0.
The item labeled 'item1' is placed by the user at index 1.
The item labeled 'item3' is placed by the user at index 2.
(Конечно, вместо того, чтобы что-то повторять, вы обновите значение поля индекса в БД для каждого элемента или сделаете что-нибудь полезное.)
Ты можешь использовать DomDocument
проанализировать ваш HTML. Это можно сделать либо через строку, используя loadHTML()
или загрузку внешнего файла HTML с помощью loadHTMLFile()
,
Этот пример использует loadHTML()
:
<?php
$html = '<html>
<body>
<ul id="sortable">
<li class="ui-state-default">1</li>
<li class="ui-state-default">2</li>
<li class="ui-state-default">3</li>
<li class="ui-state-default">4</li>
<li class="ui-state-default">5</li>
<li class="ui-state-default">6</li>
<li class="ui-state-default">7</li>
<li class="ui-state-default">8</li>
<li class="ui-state-default">9</li>
<li class="ui-state-default">10</li>
<li class="ui-state-default">11</li>
<li class="ui-state-default">12</li>
</ul>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>
</html>';
$dom = new DomDocument;
$dom->loadHTML($html);
$li = $dom->getElementsByTagName('li');
// Print first item value
echo $li->item(0)->nodeValue;
// Print third item value
echo $li->item(2)->nodeValue;
Вот что я бы сделал, и это, конечно, не самый чистый способ, но он должен работать.
Это предполагает, что вы работаете со своими собственными страницами, а не со сценарием, когда вы получаете html-страницу через http-запрос к какому-либо внешнему сайту (например, через CURL) и вам нужно его проанализировать. DOMDocument отлично подходит для последнего случая. Это решение для первого, так как я предполагаю, что, поскольку вы работаете с javascript на стороне клиента, это, вероятно, ваша собственная страница (если вы не внедряете этот javascript в страницу после ее загрузки).
Прежде всего, внутри каждого элемента списка я бы включил доступный на стороне сервера тег ввода. Он будет следить за положением и значением и передавать его серверному скрипту при отправке формы.
<form method="POST">
<ul id="sortable">
<li class="ui-state-default">1
<input id="the_list_item_1" name="the_list_item[]" type="text" value="1_0" style="display: none;">
</li>
...
</ul>
</form>
Значение - это фактическое значение элемента (в примере они были в диапазоне от 1 до 12), а его позиция отделена подчеркиванием (значение + "_" + позиция);
Список должен находиться внутри переменной формы, если вам нужно только отправить список на сервер для обработки, когда пользователь завершит работу. Однако, если вы собираетесь использовать Ajax только для передачи этих данных на сервер, это решение на самом деле не нужно (так как вы просто используете jquery для получения каждой пары позиции и значения и отправки их непосредственно в вызове ajax).
Вам нужно будет обработать обновление этих тегов ввода, когда пользователь перетаскивает элементы и изменяет порядок списка. Смотрите здесь, если вам нужно знать, как работать с сортируемыми событиями. Возможно, при обновлении для каждого элемента списка вызовите эту функцию с новой позицией:
function update_pos(value,pos)
{
$("#the_list_item_"+value).val(value+"_"+pos);
}
Итак, при отправке формы мы теперь на стороне PHP.
$list_items = $_POST["the_list_item"]; // This is basically an array of all the list_items, thanks to naming all the list items with "the_list_item[]", note the empty subscript (square braces).
$ordered_list_items = array(); // Let's push them into an associative array.
foreach($list_items as $li)
{
$li_split = explode("_",$li);
if(count($li_split) <= 0)
continue; // maybe you'd want to handle this situation differently, it really shouldn't happen at all though. Here, I'm just ignoring nonsensical values.
$item_id = $li_split[0];
$pos = $li_split[1];
$ordered_list_items[$item_id] = $pos;
}
// Then later you can shoot through this list and do whatever with them.
foreach($ordered_list_items as $item_id => $pos)
{
// postgres perhaps. Insert if not already there, update regardless.
pg_query("insert into the_list_item (item_id,position) select '$item_id','$pos' where '$item_id' not in (select item_id from the_list_item where '$item_id' = item_id limit 1));
pg_query("update the_list_item set position = '$pos' where item_id = '$item_id'");
}
Конечно, все это говорит о том, что в зависимости от ваших потребностей вам может понадобиться перезагрузить эти данные на страницу. Так что, просматривая результаты вашей базы данных (возможно, для этого пользователя), вы выводите каждый list_item на место.
$list_items = pg_fetch_all(pg_query($sql)); // $sql needs to be the query to get the results. Probably should order by position ascending.
$lic = count($list_items);
?>
<html> and stuff
<form method="POST">
<ul id="sortable">
<?php
for($i = 0; $i < $lic; $i++)
{
$li = $list_items[$i];
echo "<li class=\"ui-state-default\">".$li["item_id"]."<input id=\"the_list_item_".$li["item_id"]."\" name=\"the_list_item[]\" type=\"text\" value=\"".$li["item_id"]."_".$li["position"]."\" style=\"display: none;\"></li>";
}
?>
</ul>
</form>