Send data via POST to API and show response in PHP - php

I have a little problem, I am somewhat new to PHP and I can't get something to work.
I will explain.
I have access to a shipping API (Parcel), it gives me the possibility to track the packages by means of a guide number or a shipping ID and it returns the response in JSON with the status of the shipment.
I have made a small script that performs the tracing functions but I can't get it to show me neither the "main" status nor the "sub-events".
The request is sent via POST and the response looks like this:
{
"status": "SUCCESS",
"enviaya_shipment_number": "N9T30TAC",
"carrier_tracking_number": "9878401142",
"channel": "Api",
"estimated_delivery_date": null,
"expected_delivery_date": "12/01/2022",
"pickup_date": "2021-12-30T10:39:11-06:00",
"shipment_status": "En tránsito",
"event_code": 151,
"event_description": "Llegada al Centro de DHL",
"event": "Llegada",
"status_code": 14,
"sub_event_code": null,
"sub_event": null,
"sub_event_description": null,
"checkpoints": [
{
"code": "PU",
"description": "Envío recibido",
"date": "2022-01-03T12:12:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY-MEX"
},
{
"code": "PL",
"description": "Procesado",
"date": "2022-01-03T14:07:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY-MEX"
},
{
"code": "DF",
"description": "Salida",
"date": "2022-01-03T14:08:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY-MEX"
},
{
"code": "AF",
"description": "Llegada",
"date": "2022-01-03T15:30:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY HUB-MEX"
},
{
"code": "PL",
"description": "Procesado",
"date": "2022-01-03T18:55:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY HUB-MEX"
},
{
"code": "DF",
"description": "Salida",
"date": "2022-01-03T19:04:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MEXICO CITY HUB-MEX"
},
{
"code": "AF",
"description": "Llegada",
"date": "2022-01-03T20:55:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "QUERETARO-MEX"
},
{
"code": "PL",
"description": "Procesado",
"date": "2022-01-03T22:03:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "QUERETARO-MEX"
},
{
"code": "DF",
"description": "Salida",
"date": "2022-01-03T22:31:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "QUERETARO-MEX"
},
{
"code": "AR",
"description": "Llegada",
"date": "2022-01-04T01:52:00.000-06:00",
"postal_code": null,
"city": null,
"country_code": null,
"country": null,
"comments": "MERIDA-MEX"
}
]
}
So I made a form in HTML for the client to send the data, it is something very simple:
<form action="track.php" method="post" enctype="multipart/form-data" accept-charset="UTF-8" id="form-app">
<fieldset class="row">
<!-- Heading -->
<div class="col-xs-12">
<h3 class="legend">Rastreo de Paquetes</h3>
</div>
<!-- Select List -->
<div class="col-xs-12">
<div class="form-group required-control">
<label class="control-label" for="carrier">Paquetería</label>
<select id="carrier" name="carrier" data-alias="" class="form-control" required >
<option value="UPS" >UPS</option>
<option value="Redpack" >Redpack</option>
<option value="Estafeta" >Estafeta</option>
<option value="DHL" >DHL</option>
<option value="99 Minutos" >99 Minutos</option>
<option value="FedEx" >FedEx</option>
<option value="iVoy" >iVoy</option>
</select>
</div>
</div>
<!-- Number -->
<div class="col-xs-12">
<div class="form-group required-control">
<label class="control-label" for="number">Número de guía o ID de Envío</label>
<input type="text" id="shipment" name="shipment" value="" data-alias="" data-integer-only="true" class="form-control" required>
</div>
</div>
<!-- Button -->
<div class="col-xs-12">
<div class="form-action">
<button type="submit" id="button_1" name="button_1" class="btn btn-primary">Enviar</button>
</div>
</div>
This in turn sends to the file that in theory connects with the API through cURL sending the data, receiving the response and decoding the JSON
<?php
include_once "key.php";
$shipment_number=$_POST["shipment"];
$carrier=$_POST["carrier"];
//SEND REQUEST post TO api AND DECODE JSON RESPONSE
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://envios.corporativomarva.mx/api/v1/trackings");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "carrier=".$carrier."&shipment_number=".$shipment_number);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"api_key: ".$API_KEY
));
$response = curl_exec($ch);
curl_close($ch);
$respuesta = json_decode($response);
//Show the response on HTML format with tables
echo "<table border='1'>";
echo "<tr><td>Estado del Envío</td><td>".$respuesta->shipment_status."</td></tr>";
echo "<tr><td>Evento</td><td>".$respuesta->event_description."</td></tr>";
echo "<tr><td>Guía</td><td>".$respuesta->carrier_tracking_number."</td></tr>";
echo "<tr><td>ID de Envio</td><td>".$respuesta->enviaya_shipment_number."</td></tr>";
echo "<tr><td>Fecha de envio</td><td>".$respuesta->pickup_date."</td></tr>";
//Show subevents on HTML format with tables
echo "<table border='1'>";
echo "<tr><td>Evento</td><td>Descripción</td><td>Fecha</td></tr>";
foreach ($respuesta->subevents as $subevent) {
echo "<tr><td>".$subevent->event."</td><td>".$subevent->description."</td><td>".$subevent->date."</td></tr>";
}
echo "</table>";
However, something is obviously wrong since it shows me empty cells, that is, it does not show any data.
According to the var_dump($respuesta); The API key is incorrect but I already verified and it is fine.

I have managed to find the answer:
First I passed the API key as a header and it had to be passed as one more parameter, and then I managed to make it show me the checkpoints in a table, the complete code is:
<?php
include_once "key.php";
$shipment_number=$_POST["shipment"];
$carrier=$_POST["carrier"];
$params = array(
"api_key" => $API_KEY,
"carrier" => $carrier,
"shipment_number" => $shipment_number
);
$headers = array(
"api_key=".$API_KEY
);
curl_setopt_array($ch = curl_init(), array(
CURLOPT_URL => "https://envios.corporativomarva.mx/api/v1/trackings",
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => 1
));
$response = curl_exec($ch);
curl_close($ch);
$respuesta = json_decode($response);
//Show the response on HTML format with tables
echo "<table border='1'>";
echo "<tr><td>Estado del Envío</td><td>".$respuesta->shipment_status."</td></tr>";
echo "<tr><td>Evento</td><td>".$respuesta->event_description."</td></tr>";
echo "<tr><td>Guía</td><td>".$respuesta->carrier_tracking_number."</td></tr>";
echo "<tr><td>ID de Envio</td><td>".$respuesta->enviaya_shipment_number."</td></tr>";
echo "<tr><td>Fecha de envio</td><td>".$respuesta->pickup_date."</td></tr>";
//Show checkpoints data in a table
echo "<tr><td colspan='2'><table border='1'>";
echo "<tr><td>Checkpoint</td><td>Fecha</td><td>Código</td><td>Descripción</td><td>Ciudad</td><td>Estado</td><td>País</td><td>Comentarios</td></tr>";
foreach($respuesta->checkpoints as $checkpoint){
echo "<tr><td>".$checkpoint->description."</td><td>".$checkpoint->date."</td><td>".$checkpoint->code."</td><td>".$checkpoint->description."</td><td>".$checkpoint->city."</td><td>".$checkpoint->state."</td><td>".$checkpoint->country."</td><td>".$checkpoint->comments."</td></tr>";
}
echo "</table></td></tr>";
echo "</table>";

Based on the shared code snippet, you were iterating through subevent. However, I can't find any key called subevent in the response shared.
if subevent exist and it's in form of a list, then a foreach statement should work.
Kindly confirm where the subevent is coming from.
foreach ($respuesta->subevents as $subevent)

Related

How to generate files with a custom module and PHP?

I have a site with Drupal 8. I have created a custom module. Here is its code :
https://github.com/S1BIOSE/generator_website
generator-website-page.html.twig :
<div class="card mb-5 overflow-hidden shadow rounded bg-white">
<div class="card-body">
<form>
<legend>Générateur de site web</legend>
<div class="mb-3">
<label for="TokenUrl" class="form-label">L'URL de votre site web</label>
<input type="text" class="form-control is-invalid" id="TokenUrl" required>
<div class="invalid-feedback">
Ce champ est requis.
</div>
<small id="helpUrl" class="form-text">Entrez l'URL complète de votre site web.</small>
</div>
<div class="mb-3">
<label for="TokenTitle" class="form-label">Nom de l'entreprise</label>
<input type="text" class="form-control is-invalid" id="TokenTitle" required>
<div class="invalid-feedback">
Ce champ est requis.
</div>
<small id="helpTitle" class="form-text">Entrez le nom de votre entreprise.</small>
</div>
<div class="mb-3">
<label for="TokenDescription" class="form-label">Présentation de l'entreprise</label>
<textarea class="form-control is-invalid" id="TokenDescription" rows="5" required></textarea>
<div class="invalid-feedback">
Ce champ est requis.
</div>
<small id="helpDescription" class="form-text">Entrez une description de votre entreprise.</small>
</div>
<div class="mb-3">
<label for="TokenFeed" class="form-label">Fil d'actualité</label>
<input type="text" class="form-control" id="TokenFeed">
<small id="helpFeed" class="form-text">Entrez l'url de votre Flux RSS sur la plateforme S1BIOSE.</small>
</div>
<button type="submit" class="btn btn-primary">Générer</button>
</form>
</div>
</div>
What should I put in my module to generate the 3 files above and replace the words starting with Token ?
In this custom module, I created a form with IDs (I'm not sure if this is the right way to go). For example, the data entered in the TokenTitle field must replace TokenTitle wherever it appears in the files.
When a user submits the form, it must download the 3 files with the correct data (the one entered in the form). If possible in a ZIP archive.
It is unnecessary to keep the information submitted in the form in the database.
manifest.json
{
"orientation":"portrait",
"short_name": "TokenTitle",
"name": "TokenTitle",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#000000",
"description": "TokenDescription",
"lang": "fr",
"icons": [{
"src": "icon-144.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "any maskable"
}, {
"src": "icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
}, {
"src": "icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}],
"start_url": "/?source=pwa",
"scope": "/"
}
sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>TokenUrl/index.html</loc>
<lastmod>TokenDate</lastmod>
</url>
</urlset>
sw.js
const staticCacheName = 'TokenTimestamp';
const filesToCache = [
'/',
'/index.html',
'/CHANGELOG.md',
'/bootstrap.min.css',
'/style.css',
'/bootstrap.bundle.min.js',
'/popover.js',
'/clipboard.min.js',
'/btn-clipboard.js',
'/pwa.js',
'/feed.js',
'/toasts.js',
'/icon-32.png',
'/icon-144.png',
'/icon-192.png',
'/icon-512.png',
'/iphone5_splash.png',
'/iphone6_splash.png',
'/iphoneplus_splash.png',
'/iphonex_splash.png',
'/iphonexr_splash.png',
'/iphonexsmax_splash.png',
'/ipad_splash.png',
'/ipadpro1_splash.png',
'/ipadpro3_splash.png',
'/ipadpro2_splash.png'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(staticCacheName).then(cache => {
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.filter(function(staticCacheName) {
}).map(function(staticCacheName) {
return caches.delete(staticCacheName);
})
);
}));
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request);
})
);
});
self.addEventListener('message', event => {
if (event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});
Don't use standard PHP to make the file, as then you'll need to handle housekeeping/ removing it/ managing it as well. Drupal has BinaryFileResponse for sending files to users and \Drupal\Core\File\FileSystemInterface for creation/ management of files. If it is temporary, then simply set it as this.
Hello ok there are the things you will need to know how todo do:
Learn how to make files with php: https://www.w3schools.com/php/php_file_create.asp
learn how Drupal routing and controllers work:
https://www.drupal.org/docs/drupal-apis/routing-system/introductory-drupal-8-routes-and-controllers-example
learn how Drupal handles forms https://www.drupal.org/docs/drupal-apis/form-api/introduction-to-form-api
once you know these things then you can use on form submit
some php to generate your files and then probably group them for download ...or what ever your doing with them.

Laravel 5.7 validate fields with asterisk, required_if

I have a Vue form that let users add work experience for there profile.
Users can add extra experience by clicking on a button. Clicking on that will add an new item with new input fields. I can't add the whole script because it's quit big. But here is an example to give you an idea:
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title</label>
<input type="text" name="experiences[0][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">Institution</label>
<input type="text" name="experiences[0][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[0][comments]" class="form-control"></textarea>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title </label>
<input type="text" name="experiences[1][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">institution </label>
<input type="text" name="experiences[1][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[1][comments]" class="form-control"></textarea>
</div>
</div>
</div>
After each element there is a button to add a new row. This works fine but I have some validation issues.
I only want to validate the fields if one of the fields has a value. For example:
If experiences[0][institution] has a value, experiences[0][title] and experiences[0][comments] are required.
This has to work in every order. If title has a value, the other fields are required.
I can't really find out a way how to validate this. This is my validation rule:
$this->validate(request(), [
'experiences.*.title' => 'required_if:experiences.*.institution,null',
'experiences.*.institution' => 'required_if:experiences.*.title,null',
]);
Problem here is that it simply doesn't validate. I can't figure out how to make a rule that says, if field X has a value, Y and Z are required.
Hope anyone here can help me finding a solution! :)
Like Azeame said, make a custom validation rule and check if all values are filled or all are empty. Something in de lines of:
public function passes($attribute, $value)
{
$required = ['title','institution','comments'];
$experience = collect($value)->reject(function ($item, $key) {
return empty($item);
});
if (count($experience) == 0) {
return true;
}
foreach ($required as $field) {
if ( !$experience->has($field)) {
return false;
}
}
return true;
}
Maybe there is a beter way, but this should work.
required_if doesn't work with null as it will treat it as a string ("null"), it will work with boolean values though.
Instead you can use the required_without rule:
$this->validate(request(), [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
]);
Example
$experiences = [
[
"title" => "My title",
"institution" => "",
"comments" => "<p>My first description</p>", //passes
],
[
"title" => "",
"institution" => "My title",
"comments" => "<p>My second description</p>", //passes
],
[
"title" => "My title",
"institution" => "My title",
"comments" => "<p>My third description</p>", //passes
],
[
"title" => "",
"institution" => null,
"comments" => "<p>My forth description</p>", //fails
],
];
$rules = [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
];
$validator = Validator::make(compact('experiences'), $rules);
dd($validator->fails());
Write a custom rule with php artisan make:rule and in the passes() function write a check to ensure that all of the array keys are present and also that at least 2 of the array values are not null. I'm thinking something like this:
function passes($attribute, $value){
if(array_keys($value) !== ['title','institution','comments']){
return false;
}
if(empty($value['title']) && empty($value['institution'])){
return false;
}
return true;
}
and in your $this->validate pass the rule as ['experiences.*' =>['array', new CustomRule()] instead of required_if...
I haven't checked this so feel free to edit if it's broken.

How to produce repetitive HTML form fields?

I am using PHP to create a web application where user has to submit a form. Currently I am using simple html to render out the form just like given below.
<?php ?>
<form class='form-horizontal' method='post'>
<div class='form-group mail-right-element'>
<label class='col-sm-12 control-label mail-form-single-line-label' for='name 1'>Label 1</label>"
<div class='col-sm-12'>
<input name='name1' class='form-control validate' maxlength='100' placeholder='placeholder' value='value1'/>");
</div>
</div>
..
..
..// Some 20+ similar form fields
..
<div class='form-group mail-right-element'>
<label class='col-sm-12 control-label mail-form-single-line-label' for='name 20'>Label 20</label>"
<div class='col-sm-12'>
<input name='name20' class='form-control validate' maxlength='100' placeholder='placeholder' value='value20'/>");
</div>
</div>
</form>
This looks really messy and hardly maintainable. So I went the php way as given below.
<?php
function GetFormRowHtml($label, $name, $maxlength, $placeholder, $value)
{
return "<div class='form-group mail-right-element'>"
. "<label class='col-sm-12 control-label mail-form-single-line-label' for='$name'>$label</label>"
. "<div class='col-sm-12'>"
. "<input name='$name' class='form-control validate' maxlength='$maxlength' placeholder='$placeholder' value='$value'/>"
. "</div></div>";
}
?>
<form class='form-horizontal' method='post'>
<?php
echo GetFormRowHtml('Label1', 'Name1', 'abc', 'abc');
echo GetFormRowHtml('Label2', 'Name2', 'abc', 'abc');
echo GetFormRowHtml('Label3', 'Name3', 'abc', 'abc');
?>
</form>
Is there any better approach to do this? I've read that having html in php is a really bad design. So should I go with the html way or continue using this approach? What are the disadvantages of using above method?
You could have the input as a separate PHP file that you'd use for including:
input-template.php
<div class='form-group mail-right-element'>
<label class='col-sm-12 control-label mail-form-single-line-label' for='<?= $name ?>'><?= $label ?></label>"
<div class='col-sm-12'>
<input id='<?= $name ?>' name='<?= $name ?>' class='form-control validate' maxlength='100' placeholder='<?= $placeholder ?>' value='<?= $value ?>'/>");
</div>
</div>
And in your HTML:
<form class='form-horizontal' method='post'>
<?php
$values = [
[ "Label 1", "Name 1", "abc" , "abc" ],
[ "Label 2", "Name 2", "abc" , "abc" ],
[ "Label 3", "Name 3", "abc" , "abc" ],
[ "Label 4", "Name 4", "abc" , "abc" ]
];
foreach ($values as $array) {
list($label,$name,$placeholder,$value) = $array;
include "input-template.php"
}
?>
</form>
The reason I personally Opt for this style is that IDEs generally can analyze the HTML in the template and help with formatting and detecting of errors while string HTML would usually not be treated that way.
The best thing to do when looking at a common problem like this is to look at the some of the PHP frameworks and see how they handle it.
Looking at Laravel or Yii they abstract any inputs or labels into functions which generate the markup. So you're on the right track. The main issue with your code above is that you are combining layout with the label / field markup. Inherently this isn't' a massive issue but doesn't give your code much flexibility.
Markup should be moved into its own partial file so it's easy to maintain, form php functions should be more explicit generally.
This is my approach ...
function GetFormRowHtml($label, $name, $maxlength, $placeholder, $value)
{
/**
* #var array
* Grouping all searches and replaces in one array
*/
$sar = [
'{label}' => $label,
'{name}' => $name,
'{maxlength}' => $maxlength,
'{placeholder}' => $placeholder,
'{value}' => $value
];
/**
* #var $elementTemplate
* Template for a row
*/
$elementTemplate = "
<div class='form-group mail-right-element'>
<label class='col-sm-12 control-label mail-form-single-line-label' for='{name}'>{label}</label>
<div class='col-sm-12'>
<input name='{name}' class='form-control validate' maxlength='{maxlength}' placeholder='{placeholder}' value='{value}'/>
</div>
</div>
";
return str_replace(array_keys($sar), array_values($sar), $elementTemplate);
}
?>
<form class='form-horizontal' method='post'>
<?php
echo GetFormRowHtml('Label1', 'Name1', 'abc', 'abc');
echo GetFormRowHtml('Label2', 'Name2', 'abc', 'abc');
echo GetFormRowHtml('Label3', 'Name3', 'abc', 'abc');
?>
</form>
The approach from apokryfos is another good solution.

POST call's are randomly called as GET (Symofny 2.8)

Error! Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: "No route found for "GET /admin/.../details/save": Method Not Allowed (Allow: POST)" at /.../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php line 180
This error is simple, a url has been triggered not via POST. The problem I have is that, this route is never called with GET.
<form method="POST" action="{{ path('...', {'id': id}) }}">
{{ form_widget(form._token) }}
{{ form_widget(form.id) }}
<div class="form-group">
<label class="col-lg-2 control-label">Password</label>
<div class="input-group col-lg-10">
{{form_widget(form.password, {'attr':{'class': 'form-control'} })}}
{{ form_widget(form.random) }} Random
</div>
</div>
<div class="form-group">
<label class="col-lg-2 control-label"></label>
{{ form_widget(form.notify) }} Notify user?
</div>
<div class="form-group">
<label class="col-lg-2 control-label"></label>
<div class="input-group col-lg-10">
<button type="submit" class="btn btn-primary btn-lg" style="width: 33%;">Save</button>
</div>
</div>
</form>
The problem continues overall in the project. Ajax call's to search are triggered with GET and I can't figure out where the error comes from. No js errors connected to this issue (checked with sentry). Any idea?
More info from emails:
Message:
Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: "No route found for "GET /api-v2/search": Method Not Allowed (Allow: POST)" at /.../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php line 180
Time:
2017-06-08 17:54:31
Channel:
request
Context:
exception:
{
"class": "Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException",
"message": "No route found for \"GET /api-v2/search\": Method Not Allowed (Allow: POST)",
"code": 0,
"file": "/.../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php:180",
"trace": [
"{\"function\":\"onKernelRequest\",\"class\":\"Symfony\\\\Component\\\\HttpKernel\\\\EventListener\\\\RouterListener\",\"type\":\"->\",\"args\":[\"[object] (Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\GetResponseEvent: {})\",\"kernel.request\",\"[object] (Symfony\\\\Component\\\\EventDispatcher\\\\ContainerAwareEventDispatcher: {})\"]}",
"/.../vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php:184",
"/.../vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php:46",
]
}
}
Extra:
request_ip:
46.235.158.196
client_ip:
46.235.158.196
session:
[]
get:
[]
post:
[]
server:
{
"content-type": [
""
],
"content-length": [
""
],
"accept": [
"*/*"
],
"accept-language": [
"en, *;q=0.7"
],
"user-agent": [
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; Trident/7.0; rv:11.0) like Gecko"
],
"host": [
"test.com"
],
"connection": [
"Keep-Alive"
],
"x-php-ob-level": [
1
]
}
attr:
[]
cookies:
[]
files:
[]

Advice for voting form with php and bitrix

Currently working with Bitrix CMS and need to make vote for users from specific group. With knowing id of group i made a form with bunch of radio buttons inside. When someone vote, result shoud be writen in file (or database) and page with "Thank you for voting!" should be displayed.
My question is what is the best way to do it?
I tried a few different ways:
1) this tutorial, not working
2) two another web tutorials, can link if you ask me
3) Voting form from bitrix, but for that module of the system should be change, and that not advised.
Below is page with vote itself, but "poll.php" makes me confused because of not knowing right way to do it. So good advice would be really appreciated.
p.s. you can ignore 'Bitrix' part, most important is php
/*get users from group in array*/
<?$arUsers = CGroup::GetGroupUser(20);
$iCountUsers = 0;
$arUsersbyGroupID = array();
foreach($arUsers as $arUser) {
$arUserbyID = CUser::GetByID($arUser);
$rsUserbyID = $arUserbyID -> Fetch();
$arUsersbyGroupID[] = $rsUserbyID; }
$iCountUsers++;?>
<div class="wrapper">
<div id="poll-container">
<form class="grid" action="poll.php" method="post" accept-charset="utf-8">
/*for each create element with radio button*/
<?$iVoteCount = 0;
$allopt = array();
foreach($arUsersbyGroupID as $Vote) {
$photo = $Vote["PERSONAL_PHOTO"];
if (!empty($photo)) {
$name = "{$Vote["NAME"]} {$Vote["LAST_NAME"]}";?>
<div class="cell">
<div class="cell_img"><?echo CFile::ShowImage($photo)?></div>
<div class="cell_caption">
<input type="radio" value="<?=$iVoteCount?>" name="vote" onclick="getVote(this.value)" />
<label for='opt<?=$iVoteCount?>'><?echo $name?></label>
</div>
</div>
$iVoteCount++;
}
} ?>
<div id="sub"><input type="submit" value="Vote" /></div>
</form>
</div>
</div>
You shouldn't write your fully custom solution for creating polls. In Bitrix Framework we have a module called - vote
With supply of this module you can create standard polls or if they are not fit to your tasks - you can customize them, but you should not be writing all these code from scratch.
For basic polls configuration you can read official online courses (in Russian) - http://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=41&LESSON_ID=2859
Use bitrix api to transfer your array data using $_POST or $_REQUEST global varibles binding them to your custom form name[] . Just add bitrix api code on after submit event. Voting results may be pasted into the custom lead fields that should be previously created in BX manually. Check out this example. It was fully workable and tested.
<?php
$queryUrl ='';
$_SERVER['REMOTE_ADDR'] = $ip;
$queryData = http_build_query($basebitrix24 = array(
'fields' => array(
"TITLE" =>'one',
"NAME" => 'two',
"LAST_NAME" => $leadData['question_one'],
"STATUS_ID" => "NEW",
"OPENED" => "Y",
"UF_CRM_1491235024" => $leadData['question_second'],
"UF_CRM_1491235124" => $leadDataQ1[$answer],
"UF_CRM_1491235376" => $leadData['question_third'],
"ASSIGNED_BY_ID" => 16,
'SOURCE_ID' => $i,
"PHONE" => array(array("VALUE" => $_REQUEST['phone'], "VALUE_TYPE" => "WORK" )),
"EMAIL" => array(array("VALUE" => $_REQUEST['email'], "VALUE_TYPE" => "WORK" )),
),
'params' => array("REGISTER_SONET_EVENT" => "Y")
));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $queryUrl,
CURLOPT_POSTFIELDS => $queryData,
));
$result = curl_exec($curl);
curl_close($curl);
$result = json_decode($result, 1);
?>
The requests are not about voting but there is no very much trouble to use same method for any custom form too. Form code in example purposes.
if (isset($_POST['s_submit'])) {
#$email = strtolower(trim($_POST['email']));
#$name = trim($_POST['name']);
if (isset($_POST) && count($_POST) != 0) {
if (#isset($email) && #$email != '') {
$line = check_record_exist($removelist, $email, $form_type);
if ($line) {
$line--;
delete_line_from_file($removelist, $line);
}
if (!check_record_exist($addlist, $email, $form_type)) {
add_record($addlist, $email, $name);
$sm_res = 1;
} else {
$sm_res = 3;
}
} else
echo '<font color="#FF0000">Please enter e-mail address</font>';
}
}
if (isset($sm_res)) {
switch ($sm_res) {
case '1': echo '<b>You have successfully subscribed</b>';
break;
case '2': echo '<b>You have successfully unsubscribed</b>';
break;
case '3': echo '<b>You are already subscribed</b>';
break;
case '4': echo '<b>You are already unsubscribed</b>';
break;
}
unset($sm_res);
} else {
<form name="contactform" id="sky-form" method="post" action="">
<fieldset>
<div class="row">
<div class="sky-form epochta">
<section class="col col-6" >
<label class="input"><i class="icon-append icon-envelope-alt"></i> <h3>EMAIL </h3><input type="email" name="email" value="<?$_REQUEST['email']?>"> </label>
</section>
<?php if ($form_type != 1) { ?>
<section class="col col-6">
<label class="input"> <i class="icon-append icon-user"></i><h3>NAME<h3> <input type="text" name="name" size="15" value="<?php echo #trim(strip_tags($_REQUEST['name'])); ?>">
</label>
</section>
<?php } ?>
<section class="col col-12" >
<input type="hidden" name="saved" value="yes">
<input type="submit" class="subbutton" name="submit" value="">
<td align="center" colspan="2"><font face="Verdana" size="-2">ePochta Subscription Manager</font>
</section>
</div>
</div>
</fieldset>
</form>
?>

Categories