У меня есть следующий быстрый код со словарем, и я пытаюсь отправить его на PHP.
Поскольку в PHP нет словарей, я подумал, что мне следует быстро преобразовать словарь в JSON, а затем отправить его как JSON в PHP.
Однако я просто не уверен, как это сделать...
Кроме того, как я могу получить его на стороне PHP?
Быстрый код:
func appl(_ application: UIApplication) {
print("...........................................................")
let group = DispatchGroup() // just to avoid asnc
let mappedViewsArray = DisplayVC.viewsArray.map { ($0,1) } // To count the similirities
let viewsArrayCount = Dictionary(mappedViewsArray, uniquingKeysWith: +) // To add the similirities
print(viewsArrayCount)
do {
let encodedDictionary = try JSONEncoder().encode(viewsArrayCount) // Convert the dictionary to JSON (encode)
// let jsonData = try JSONSerialization.data(withJSONObject: viewsArrayCount)
let urlPath : String = "http://localhost/updateViews.php" // PHP file URL
let url: URL = URL(string: urlPath)!
var request = URLRequest(url: url as URL)
request.httpMethod = "POST" // method
// request.httpBody = encodedDictionary
print(viewsArrayCount)
let postString = "JSONDataEncoded=\(encodedDictionary)" // to get the passed data in PHP
// request.httpBody = postString.data(using: String.Encoding.utf8)
// request.httpBody = encodedDictionary
request.httpBody = postString.data(using: String.Encoding.utf8) // to encode the passed variable
group.enter() // just to avoid asnc
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in defer {group.leave()}
// just to avoid asnc
if error != nil {
print("Failed to update data")
} else {
print("Data updated")
//let responseJSON = try? JSONSerialization.jsonObject(with: data!, options: [])
// if let responseJSON = responseJSON as? [String: Any] {
// print(responseJSON)
// }
}
}
task.resume() // to run the task command
group.wait() // just to avoid asnc
// to print the jsonencoded
print(String(data: encodedDictionary, encoding: .utf8)!)
} catch {
print("fail")
print("Error: ", error)
}
}
PHP:
<?php
// Create connection to database
$con=mysqli_connect("localhost","root","","");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
// $dictionary = [5:1,1:2,3:3,9:4,13:5];
// $json = '{"5":1,"1":2,"3":3,"9":4,"13":5}';
// $json = $con->real_escape_string($_POST['JSONDataEncoded']);
$json = $_POST["JSONDataEncoded"];
$updateViews = json_decode($json, true);
foreach($updateViews as $key => $value) {
$stmt = $con->prepare("UPDATE cars SET views = views + '".$value."' WHERE ID = '". $key ."'");
$stmt->execute();
echo "good";
}
mysqli_close($con);
?>
(Используйте привязку параметров вместо real_escape_string — это намного безопаснее).
Что касается более широкого вопроса, похоже, вы привели пример (в комментарии) того, что содержится в $_POST["JSONDataEncoded"], когда он попадает на прослушиватель PHP. Похоже, вы правильно его расшифровали, и цикл foreach выглядит хорошо. Вы пробовали его запустить? Что случается?
@halfer хороший улов относительно возможности внедрения sql
Вы не отправляете словарь swift на php, и нет никакой связи между словарем swift и тем, что получит PHP, поскольку они общаются через HTTP. В данный момент вы отправляете массив JSON в PHP, чего он и ожидает. Поэтому, если у вас есть проблемы, это, вероятно, из-за того, что вы поместили в этот массив перед его JSON-кодированием — трудно сказать, поскольку мы не знаем, что находится внутри этого массива. Примечание: let group = DispatchGroup() // just to avoid asnc <-- это действительно плохая идея. Не делай этого. Вместо этого используйте async/await или правильный обратный вызов
@akjndklskver это образец данных: [5:1,1:2,3:3,9:4,13:5], при условии, что ключ представляет автомобиль, а значение представляет просмотры. например, 5:1 означает, что автомобиль 5 был просмотрен 1 раз.
В PHP есть словари. Они называются ассоциативными массивами.
@ryantxr, как мне получить словарь на PHP, указанный как ассоциативный массив?
Отправьте данные в формате JSON. Это, вероятно, сработает: {"5":1, "1":2, "3":3, "9":4, "13":5}
@ryantxr хорошо, так что это именно то, что я пытаюсь сделать вместо преобразования словаря в ассоциативный массив. проблема в том, что я не уверен, как отправить этот JSON из быстрого кода в PHP-код. обратите внимание, что у меня уже есть образец в файле PHP $json = '{"5":1,"1":2,"3":3,"9":4,"13":5}'; Я просто застрял в том, как отправить его из Swift и получить в файле PHP, поэтому этот пост
Тогда вам нужна помощь с частью Swift, а не с PHP
@ryantxr наткнулся на этот пост здесь stackoverflow.com/a/49036238/8397835 и похоже, что вот как отправить JSON, закодированный из swift, но не знаю, как обрабатывать его со стороны PHP.
Прошло слишком много времени с тех пор, как я писал код Swift. Я не собираюсь этого делать. Я предполагаю, что вы можете преобразовать свои данные в JSON. Создайте JSON, который выглядит так:
{"5":1, "1":2, "3":3, "9":4, "13":5}
Вы можете использовать HTTP/POST для отправки данных, как показано в вашем коде. Использование переменной POST должно работать. Вы также можете просто отправить JSON в теле и закодировать тип содержимого запроса POST как application/json. Единственная разница в том, что вы должны читать это по-другому.
// Read from post variable
$json = $_POST['JSONDataEncoded'];
Чтение непосредственно из тела
$json = file_get_contents('php://input');
Если у вас есть JSON, его преобразование будет таким же
$data = json_decode($json, true);
foreach ($data as $key => $row ) {
echo "$key, $row"; // just an example
}
Хорошая мысль о чтении JSON непосредственно из тела. Однако, если OP отправляет его в переменной, то PHP, который у них есть, может быть уже правильным. Я не совсем уверен, что они отправляют его правильно, и мне интересно, будет ли это следующей вещью, которую нужно проверить.
Знаете ли вы, как я могу проверить, что я получаю в файле PHP? Я знаю, что если я напишу файл PHP, я могу поместить его на сервер, такой как Apache, и выполнить эхо, чтобы проверить его локально. Тем не менее, я не уверен, передаю ли я JSON из swift в PHP, как я могу повторить, чтобы проверить его/отладить
@Cataster: посмотрите на строку $json = file_get_contents('php://input') — она покажет, какие необработанные данные отправляются.
Лично я бы проверил это в Swift и добавил несколько модульных тестов.
@halfer Значит, мне просто нужно сделать echo $json в PHP, и он должен отображаться? Причина, по которой я хочу протестировать его на стороне PHP, а не быстро, заключается в том, что я хочу проверить, действительно ли я получаю данные, закодированные в json. Сейчас не знаю, получу ли я его. Кроме того, должен ли ввод в php://input быть именем файла? Или это формат получения из PHP? Я знаю, вы упомянули, что прошло некоторое время с момента написания swift, но не могли бы вы рассказать мне, как отправить JSON в теле и закодировать тип содержимого запроса POST как application/json?
Нет, 'php://input' не является заполнителем для имени файла — используйте его явно. Это специфичный для PHP протокол для захвата всего тела HTTP-запроса. Попробуйте, и это даст вам очень четкие указания относительно того, как действовать дальше. Если JSON действителен, код Swift в порядке, а если он недействителен, Swift не в порядке. Убедитесь, что вы пытаетесь настроить код Swift, чтобы он сначала отправлял JSON во всем теле POST (т.е. не как значение JSONDataEncoded).
После того, как вы попробовали это, вы также можете (вместо этого) попробовать отправить JSON в этой POST var. Убедитесь, что вы делаете параллельные настройки в PHP, как указал ryantxr.
@halfer это $json = file_get_contents('php://input'); сработало! Очень ценю помощь, ребята. Другой метод не сработал, потому что кодируется дважды. Когда я декодирую его один раз, я получаю пустой массив.
В вашем PHP есть потрясающая дыра для SQL-инъекций. Кто-нибудь может опубликовать здесь какой-нибудь JSON, который, по крайней мере, запустит UPDATE во всех строках в cars. В зависимости от ваших настроек MySQL они могут даже удалить таблицу.