Николай, привет! Не подскажешь, как правильно обращаться к пивкарте, да и вообще к сайтам на prisma-cms, по API с другого сайта? Если правильно понимаю, то стучаться надо сюда https://pivkarta.ru/api/ , но что обязательно нужно в параметрах указать?
Думаю, что тема будет интересна не только мне:)
Дима, привет!
Здесь все как и с чистым GraphQL. Можно гуглить, к примеру, по запросу "graphql request example". Или вот прямая ссылка на оффдоку: https://graphql.org/learn/serving-over-http/
По сути это стандартный ajax-запрос (в примеру, через fetch) с передачей GraphQL-запроса в теле ajax-запроса с получением ответа в формате json.
Спасибо! Я тогда как разберусь - сюда закину что получится)
Не за что!
ОК.
Проблема в следующем: тестово обращаюсь https://pivkarta.ru/api/?query={beers{name}}, но если вбить в адресную, то показывает http://joxi.ru/8An0bwVczjjabm
То есть в строке не прописывается api/. Не сталкивался?
И соответственно в modx пытаюсь постучать - выдает ошибку
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://pivkarta.ru/api/?query={beers{name}}', '/', 'GET', $params);
$result = json_decode($result, true);
print_r($result);
Дима, как я говорил, надо именно POST-запросы слать. GET-это возвращает HTML самого API-интерфейса. Более того, слать надо с заголовками json. Вот рабочий пример (выполняется через MODX-console)
<?php
print "<pre>";
$query = '
query users (
$first: Int = 3
$orderBy: UserOrderByInput = createdAt_DESC
$where: UserWhereInput
$withPlaces: Boolean = false
){
users(
first: $first
orderBy: $orderBy
where: $where
){
...user
Places(
first: 3
) @include(if: $withPlaces)
{
id
name
}
}
}
fragment user on User{
id
user_id
username
fullname
email
}
';
$params = [
"query" => $query,
"variables" => [
"first" => 1,
"orderBy" => "fullname_ASC",
"withPlaces" => true,
"where" => [
"Places_some" => []
],
],
];
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://pivkarta.ru', '/api/', 'POST', $params, [
"contentType" => "json",
]);
// print_r($result);
$result = json_decode($result, true);
print_r($result);
Обрати внимание, я в запрос прописал параметры $first и $orderBy со значениями по умолчанию. Теперь эти параметры можно передавать в запросе (см. variables).
Я еще улучшил по ходовой запрос, добавив для примера конструкцию @include(if: $withPlaces). Если передать параметр withPlaces = true, то будут получены еще и данные заведений пользователя. Если нет, то соответственно нет. А where в моем примере запрашивает только тех пользователей, которые создали хоть одно заведение.
Супер! Спасибо) Закину запросы и даю ссыль на то, что получится)
Пожалуйста!
Разбираюсь с запросами, но общее направление ясно:) Сейчас сделал вывод данных о заведении и ассортименту пива https://goldpivo.ru/testovaya.html Сколько-то страница повисит, в чуть позже уже нормальный пример будет. На эту страницу планирую вывести все заведения, в которых есть разливной Guinness под статью. На тестовой странице сниппет такой:
<?php
print "<pre>";
$query = '
query {
places ( where : {name: "Grace O’Malley"} )
{
name
address
place_id
url_name
image
beers {
id
Beer {
name
image
}
}
}
}
';
$params = [
"query" => $query,
];
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://pivkarta.ru', '/api/', 'POST', $params, [
"contentType" => "json",
]);
// print_r($result);
$result = json_decode($result, true);
$name = $result['data']['places'][0]['name'];
$address = $result['data']['places'][0]['address'];
$place_img = $result['data']['place'][0]['place_id'].$result['data']['places'][0]['image'];
foreach($result['data']['places'][0]['beers'] as $res) {
$beers .= '
<div class="col-12">
<img class="mx-auto d-block" src="https://pivkarta.ru/images/resized/thumb/'.$res['Beer']['image'].'" />
<h3>'.$res['Beer']['name'].'</h3>
</div>
';
}
$output='
<div class="row">
<div class="col-4">
<img class="mx-auto d-block" src="https://pivkarta.ru/images/resized/thumb/'.$place_img.'" />
</div>
<div class="col-8">
<h2>'.$name.'</h2>
<p>'.$address.'</p>
</div>
<hr/>
'.$beers.'
</div>
';
return $output;
echo '<hr/>';
print_r($result);
Сейчас ты не спрашиваешь, а хвастаешься? :)
Не, нечем: сайт завалил:)))
Восстанавливаю.
А выложил - для информации.
Стало понятно, что поля заведения "Город" не хватает: как думаешь, имеет смысл добавить простое текстовое в карточку или не стоит?
Нет, не стоит. Потому что там завязка с геоданными. Это надо будет по-другому обыгрывать. Я потом придумаю как лучше это сделать.
На замену "потерянной" страницы с примером: ссылка
Код сниппета:
<?php
// [[places_beer? &beername=`Guinness Draught (Гиннесс)`]]
$query = '
query {
beers ( where : {name: "'.$beername.'"} )
{
places (
orderBy: price_ASC
first: 12
)
{
price
Place{
name
address
place_id
url_name
image
}
}
}
}
';
$params = [
"query" => $query,
];
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://pivkarta.ru', '/api/', 'POST', $params, [
"contentType" => "json",
]);
$result = json_decode($result, true);
foreach($result['data']['beers'][0]['places'] as $res) {
$beers .= '
<a href="https://pivkarta.ru/place/'.$res['Place']['place_id'].'/'.$res['Place']['url_name'].'" class="col-6 col-sm-4 col-md-3 col-lg-2 text-center" target="_blank" style="line-height:1;">
<img class="mx-auto d-block" src="https://pivkarta.ru/images/resized/thumb/'.$res['Place']['image'].'"/>
<b>'.$res['Place']['name'].'</b><br/>
'.$res['Place']['address'].'<br/>
Цена: <big>'.$res['price'].' руб</big>
</a>
';
}
$output='
<div class="row">
<div class="col-12">
<h3>В каких заведениях есть пиво '.$beername.'</h3>
</div>
'.$beers.'
</div>
';
return $output;
echo '<hr/>';
print_r($result);
Дима, здесь все хорошо, только переделай where : {name: "'.$beername.'"} на ($where: BeerWhereInput) where: $where. А то ты ограничен в поиске только по имени. А так сможешь передавать "where" => ["name" => "someName"] и не только.
... А не, не все хорошо. Что-то я и не сразу заметил, что ты вставил name: "'.$beername.'" текстовой переменной. Так совсем не надо делать. Посмотри мой пример выше. Должно быть просто name: $beername, а $beername объявлена выше в перечислении параметров запроса как $beername: String, то есть твой запрос должен выглядеть так:
query beers($beername: String) {
beers(where: { name: $beername }) {
places(
orderBy: price_ASC,
first: 12
) {
price
Place {
name
address
place_id
url_name
image
}
}
}
}
А с правильным определением $where вот так:
query beers($where: BeerWhereInput) {
beers(where: $where) {
places(
orderBy: price_ASC,
first: 12
) {
price
Place {
name
address
place_id
url_name
image
}
}
}
}
И несмотря на развернутое объяснение... понимания нет( Код выдает результат, но от "от балды", без привязки к конкретному пиву.
И сразу возник еще вопрос, как отсечь заведения, в которых пиво есть, а цены - нет? Так не прокатит: "where" => ["name" => "Guinness Draught (Гиннесс)", "price:!=" => null ] ?
$query = '
query beers($where: BeerWhereInput) {
beers(where: $where) {
places(
orderBy: price_ASC,
first: 12
) {
price
Place {
name
address
place_id
url_name
image
}
}
}
}
';
$params = [
"query" => $query,
"where" => [
"name" => "Guinness Draught (Гиннесс)",
]
];
Николай, привет! С выдачей таки разобрался и уперся в "тактические" вопросы. Подскажи, пожалуйста, куда копать. Код выдачи:
<?php
//print "<pre>";
$query = '
query beers($where: BeerWhereInput) {
beers(where: $where) {
places(
orderBy: price_ASC,
first: 24
) {
price
Place {
name
address
place_id
url_name
image
}
}
}
}
';
$params = [
"query" => $query,
"variables" => [
"where" => [
"name" => $beername
]
],
];
В выдаче есть заведения с ценами и без (price = null), и вот выбрать только те, у которых нет цены получается, а обратного не выходит (вывести только те заведения, у которых есть цена на нужное пиво). У меня такое ощущение, что решение какое-то настолько тривиальное, что о нем и не пишет никто ничего...
И встал вопрос передачи массива параметра в запрос, например передать несколько названий пива?
Дима, привет!
1. Не придумывай параметры запроса сам. Заходи в API и смотри документацию. Нет запроса типа price:!= (как в модексе), но есть price_not, price_gt и price_gte. http://joxi.ru/Vm6a53Mt43k1kr
2. Твой запрос будет примерно так выглядеть:
query beers {
beers(
where: {
name_in: [
"Spaten",
"Paulaner Hefe-weissbier",
],
places_some:{
price_gt: 0
}
}
) {
id
name
places(
orderBy: price_ASC,
first: 24
where: {
price_gt: 0
}
) {
price
Place {
name
address
place_id
url_name
image
}
}
}
}
Но смотри, тут сразу два условия прописано, потому что выборка идет пива, но цены указаны в связке пиво-заведение, поэтому по первому условию мы находим пиво, у которых цена имеется хоть в одном заведении, но могут быть записи, где цены нет (в одном цена указана, а в другом, это же пиво, нет). Вторым условием мы получаем только те заведения, в которых указана цена для этого пива.
Если указать не places_some, а places_every, то он найдет пиво, у которого во всех заведениях указана цена, и можешь часть выборки потерять.
Николай, спасибо огромное! Вообще не туда смотрел!
Не за что!
Николай, приветствую! Прошу волшебного пинка в нужную сторону:
$params = [
"query" => $query,
"variables" => [
"where" => [
"name_in" => array("Lager Hell Ayinger (Айингер Лагер Хелль) бутылка","Lager Hell Ayinger (Айингер Лагер Хелль) разливное")
]
],
];
print_r($params);
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://pivkarta.ru', '/api/', 'POST', $params, [
"contentType" => "json",
]);
Не могу найти правильное решение, как 2 пива запихать в запрос.
Дима, я что-то не очень понимаю твой вопрос "Не могу найти правильное решение, как 2 пива запихать в запрос.". Что ты имеешь ввиду? По виду у тебя правильный запрос на получение двух видов пива. Где что не так?
Возвращает только по одному: по последнему
По первому пиву точно есть 3 заведения и они не пересекаются, то есть теоретически должно выдать 5 позиций.
Сам запрос:
$query = '
query beers($where: BeerWhereInput) {
beers(where: $where) {
places(
orderBy: price_ASC,
first: 24
where: {
price_gt: 0
}
) {
price
Place {
name
address
place_id
url_name
image
lng
lat
}
}
}
}
';
Нет, он тебе возвращает два. http://joxi.ru/l2ZLnYdHzNaKjr
Это ты уже на уровне php выводишь только одно. Смотри свой вывод.
Точно!! Спасибо огромное) А то вывих мозга уже намечался)))
Не за что:)