Нестандартные решения: № 2.1. Платформа 1С и веб-сервис на PHP. (Массивы данных. Составные типы данных)

Автор: Программист Зуй Богдан

 

Предыдущая статья (Нестандартные решения: Статья №01. Платформа 1С и веб-сервис на PHP)
 

В этой статье научимся передавать массивы простых данных, а также составные данные. Во второй части статьи объединим полученные знания и разработаем  внешнюю обработку и небольшой скрипт для веб сервера, позволяющие легко и просто размещать актуальную информацию о вакансиях компании на собственном сайте, а также собирать резюме соискателей работником кадровой службы.

 
Часть 1
 

Рабочий компьютер:

  • ОС: Ubuntu Desktop 14.04.1 LTS
  • IDE: Eclipse Luna
  • Система контроля версий: Subversion
  • Веб-сервер: Apache2 + PHP
  • 1C: Платформа 8.3.5.1186 + Пустая конфигурация (и желательно 1С: Зарплата и управление персоналом, ред. 2.5)
 
Создадим новое хранилище.
Создадим новый проект.
Подключаем проект к хранилищу.

Создадим рабочий файл index.php

Подключаем нашу библиотеку и объявляем основные настройки.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class CONFIG {
public static $wsnamespace = "http://192.168.1.157/article02/";
public static $wsservicename = "TestService";
}

// Подключаем библиотеку
require_once 'libs/nusoap/nusoap.php';
// Обявляем основные настройки
$server = new soap_server ();
$server->configureWSDL ( CONFIG::$wsservicename, CONFIG::$wsnamespace, CONFIG::$wsnamespace );
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';
// Регистрируем метод
$server->register ( 'Hello', array ( 'str' => 'xsd:string'
), array (
'return' => 'xsd:string'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#Hello', 'rpc', 'encoded', 'Простая функция для проверки работы с 1C.' );
function Hello($str = "Guest") {
return "Привет, {$str}!";
}
$HTTP_RAW_POST_DATA = isset ( $HTTP_RAW_POST_DATA ) ? $HTTP_RAW_POST_DATA : '';
$server->service ( $HTTP_RAW_POST_DATA );

Разберем несколько примеров без особого практического применения, чтобы заложить фундамент.

1. Получение массива
Добавим в веб-сервис метод без параметров возвращающий массив строк, например версию веб-сервиса, название, время на сервере.
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php
class CONFIG {
public static $wsnamespace = "http://192.168.1.157/article02/";
public static $wsservicename = "TestService";
public static $wsversion = "1.0";
}

//
require_once 'libs/nusoap/nusoap.php';

//
$server = new soap_server ();

$server->configureWSDL ( CONFIG::$wsservicename, CONFIG::$wsnamespace, CONFIG::$wsnamespace );
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';

// Составные типы данных. Опишем массив строковых данных
$server->wsdl->addComplexType(
'StringsArrayOut',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')),'xsd:string'
    );

// Регистрируем методы
$server->register ( 'Hello', array ( 'str' => 'xsd:string'
), array (
'return' => 'xsd:string'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#Hello', 'rpc', 'encoded', 'Простая функция для проверки работы с 1C.' );

$server->register ( 'getInfo', array (), array (
'return' => 'tns:StringsArrayOut'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#getInfo', 'rpc', 'encoded', 'Информация о сервере.' );

function Hello($str = "Guest") {
return "Привет, {$str}!";
}

function getInfo() {
$result = array();
$result[] = CONFIG::$wsversion;
$result[] = CONFIG::$wsservicename;
$result[] = date('d-m-Y H:i:s');
return $result;
    }

$HTTP_RAW_POST_DATA = isset ( $HTTP_RAW_POST_DATA ) ? $HTTP_RAW_POST_DATA : '';
$server->service ( $HTTP_RAW_POST_DATA );


Отправим изменения в хранилище (Team->Commit) и обновим скрипты на веб-сервере (см. предыдущую статью).
Если не разобрались как использовать хранилище, не беда. Можно просто скопировать файлы из рабочей папки на веб-сервер.

Сделаем обработку для запроса информации с сервера.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//
ВыбПутьПубликацииСервиса = "http://192.168.1.157/article02/?wsdl"; 
// в веб-сервисе мы прописали wsnamespace 
ВыбURIПространстваИменСервиса = "http://192.168.1.157/article02/"; 
// там же имя сервиса wsservicename 
ВыбИмяСервиса = "TestService";

// имя точки подключения совпадает с именем сервиса + слово Port 
ВыбИмяТочкиПодключения = "TestServicePort"; 
// Теперь объявим подключение 
Определение = Новый WSОпределения(ВыбПутьПубликацииСервиса); 
Сервис = Новый WSПрокси(Определение, ВыбURIПространстваИменСервиса, ВыбИмяСервиса, ВыбИмяТочкиПодключения); 
// Ну и наконец-то вызовем наш метод 
value = Сервис.getInfo();

Версия = value.list.Получить(0);
ИмяСервиса = value.list.Получить(1);
ДатаНаСервере = value.list.Получить(2);

Сообщить(Версия);
Сообщить(ИмяСервиса);
Сообщить(ДатаНаСервере);


Запустим обработку и проверим. Если появились три сообщения значит сделали все правильно и можете двигаться дальше, если не получилось попробуйте начать с начала.

2. Передадим массив на сервер
Добавим метод получающий в качестве параметра массив, например версия клиента, название конфигурации, время на клиенте.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
class CONFIG {
public static $wsnamespace = "http://192.168.1.157/article02/";
public static $wsservicename = "TestService";
public static $wsversion = "1.0";
}

//
require_once 'libs/nusoap/nusoap.php';

//
$server = new soap_server ();

$server->configureWSDL ( CONFIG::$wsservicename, CONFIG::$wsnamespace, CONFIG::$wsnamespace );
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';

// Составные типы данных
$server->wsdl->addComplexType ( 'StringsArrayOut', 'complexType', 'array', '', 'SOAP-ENC:Array', array (), array (
array (
'ref' => 'SOAP-ENC:arrayType',
'wsdl:arrayType' => 'xsd:string[]' 
) 
), 'xsd:string' );

$server->wsdl->addComplexType ( "StringsArrayIn", "complexType", 'array', 'sequence', '', array (
'item' => array (
'name' => 'item',
'type' => 'xsd:string',
'minOccurs' => '0',
'maxOccurs' => 'unbounded' 
) 
), array (), "xsd:string" );

// Регистрируем метод
$server->register ( 'Hello', array ( 'str' => 'xsd:string'
), array (
'return' => 'xsd:string'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#Hello', 'rpc', 'encoded', 'Простая функция для проверки работы с 1C.' );

$server->register ( 'getInfo', array (), array (
'return' => 'tns:StringsArrayOut' 
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#getInfo', 'rpc', 'encoded', 'Информация о сервере.' );

$server->register ( 'sendInfo', array (
'array' => 'tns:StringsArrayIn' 
), array (), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#sendInfo', 'rpc', 'encoded', 'Отправить информацию о клиенте на сервер.' );

function Hello($str = "Guest") {
return "Привет, {$str}!";
}

function getInfo() {
$result = array();
$result[] = CONFIG::$wsversion;
$result[] = CONFIG::$wsservicename;
$result[] = date('d-m-Y H:i:s');
return $result;
}

function sendInfo($array) {
file_put_contents('result.txt', print_r($array, true));
    }

$HTTP_RAW_POST_DATA = isset ( $HTTP_RAW_POST_DATA ) ? $HTTP_RAW_POST_DATA : '';
$server->service ( $HTTP_RAW_POST_DATA );


Снова и далее после каждого шага обновим файлы на веб-сервере.
Реализуем в нашей обработке команду которая выполнит отправку данных на сервер.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
ВыбПутьПубликацииСервиса = "http://192.168.1.157/article02/?wsdl"; 
// в веб-сервисе мы прописали wsnamespace 
ВыбURIПространстваИменСервиса = "http://192.168.1.157/article02/"; 
// там же имя сервиса wsservicename 
ВыбИмяСервиса = "TestService";

// имя точки подключения совпадает с именем сервиса + слово Port 
ВыбИмяТочкиПодключения = "TestServicePort"; 
// Теперь объявим подключение 
Определение = Новый WSОпределения(ВыбПутьПубликацииСервиса); 
Сервис = Новый WSПрокси(Определение, ВыбURIПространстваИменСервиса, ВыбИмяСервиса, ВыбИмяТочкиПодключения); 

ТипВхПараметра = Сервис.ФабрикаXDTO.Тип("http://192.168.1.157/article02/", "StringsArrayIn");
ВходПар = Сервис.ФабрикаXDTO.Создать(ТипВхПараметра);

ТипВхПараметраItem = Сервис.ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "string");
ВходПарItem = Сервис.ФабрикаXDTO.Создать(ТипВхПараметраItem,"1.0"); 
ВходПар.item.Добавить(ВходПарItem);

ТипВхПараметраItem = Сервис.ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "string");
ВходПарItem = Сервис.ФабрикаXDTO.Создать(ТипВхПараметраItem, Метаданные.Имя); 
ВходПар.item.Добавить(ВходПарItem);

ТипВхПараметраItem = Сервис.ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema", "string");
ВходПарItem = Сервис.ФабрикаXDTO.Создать(ТипВхПараметраItem, ТекущаяДата()); 
ВходПар.item.Добавить(ВходПарItem);

Сервис.sendInfo(ВходПар);


После запуска новой команды обработки на веб-сервере должен появиться файл http://192.168.1.157/article02/result.txt

Array
(
    [item] => Array
        (
            [0] => 1.0
            [1] => ЗарплатаИУправлениеПерсоналомБазовая
            [2] => 2014-10-16T23:56:33
        )

)


3. Получение составного типа с сервера
Изменим метод getInfo будем возвращать вместо массива структуру с полями ВерсияСервера (тип строка), Название (тип строка), ВремяНаСервере (тип дата и время).


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
class CONFIG {
public static $wsnamespace = "http://192.168.1.157/article02/";
public static $wsservicename = "TestService";
public static $wsversion = "1.0";
}

//
require_once 'libs/nusoap/nusoap.php';

//
$server = new soap_server ();

$server->configureWSDL ( CONFIG::$wsservicename, CONFIG::$wsnamespace, CONFIG::$wsnamespace );
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';

// Составные типы данных
$server->wsdl->addComplexType(
'Info',
'complexType',
'struct',
'all',
'',
array(
'version' => array(
'name' => 'version',
'type' => 'xsd:string'
),
'name' => array(
'name' => 'name',
'type' => 'xsd:string'
),
'datetime' => array(
'name' => 'datetime',
// ВАЖНО! При объявлении типа важен регистр символов
'type' => 'xsd:dateTime'
)

)
    );

// Регистрируем метод
$server->register ( 'Hello', array ( 'str' => 'xsd:string'
), array (
'return' => 'xsd:string'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#Hello', 'rpc', 'encoded', 'Простая функция для проверки работы с 1C.' );

$server->register ( 'getInfo', array (), array (
'return' => 'tns:Info' 
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#getInfo', 'rpc', 'encoded', 'Информация о сервере.' );

function Hello($str = "Guest") {
return "Привет, {$str}!";
}

function getInfo() {
return array('version' => CONFIG::$wsversion, 'name' => CONFIG::$wsservicename, 'datetime' => (new DateTime("now"))->format("Y-m-d\TH:i:s"));
    }

$HTTP_RAW_POST_DATA = isset ( $HTTP_RAW_POST_DATA ) ? $HTTP_RAW_POST_DATA : '';
$server->service ( $HTTP_RAW_POST_DATA );


Так же поправим наш метод обработки результата вызова метода getInfo.


 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//
ВыбПутьПубликацииСервиса = "http://192.168.1.157/article02/?wsdl"; 
// в веб-сервисе мы прописали wsnamespace 
ВыбURIПространстваИменСервиса = "http://192.168.1.157/article02/"; 
// там же имя сервиса wsservicename 
ВыбИмяСервиса = "TestService";

// имя точки подключения совпадает с именем сервиса + слово Port 
ВыбИмяТочкиПодключения = "TestServicePort"; 
// Теперь объявим подключение 
Определение = Новый WSОпределения(ВыбПутьПубликацииСервиса); 
Сервис = Новый WSПрокси(Определение, ВыбURIПространстваИменСервиса, ВыбИмяСервиса, ВыбИмяТочкиПодключения); 
// Ну и наконец-то вызовем наш метод 
value = Сервис.getInfo();

Версия = value.version;
ИмяСервиса = value.name;
ДатаНаСервере = value.datetime;

Сообщить(Версия);
Сообщить(ИмяСервиса);
Сообщить(ДатаНаСервере);


4. Отправим составной тип

Изменим метод setInfo, в качестве параметра будем передавать структуру с полями ВерсияКлиента (тип строка), НазваниеКонфигурации (тип строка), ВермяНаКлиенте (тип дата и время).


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?php
class CONFIG {
public static $wsnamespace = "http://192.168.1.157/article02/";
public static $wsservicename = "TestService";
public static $wsversion = "1.0";
}

//
require_once 'libs/nusoap/nusoap.php';

//
$server = new soap_server ();

$server->configureWSDL ( CONFIG::$wsservicename, CONFIG::$wsnamespace, CONFIG::$wsnamespace );
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';

// Составные типы данных
$server->wsdl->addComplexType(
'Info',
'complexType',
'struct',
'all',
'',
array(
'version' => array(
'name' => 'version',
'type' => 'xsd:string'
),
'name' => array(
'name' => 'name',
'type' => 'xsd:string'
),
'datetime' => array(
'name' => 'datetime',
// ВАЖНО! При объявлении типа важен регистр символов
'type' => 'xsd:dateTime'
)

)
);

// Регистрируем метод
$server->register ( 'Hello', array ( 'str' => 'xsd:string'
), array (
'return' => 'xsd:string'
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#Hello', 'rpc', 'encoded', 'Простая функция для проверки работы с 1C.' );

$server->register ( 'getInfo', array (), array (
'return' => 'tns:Info' 
), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#getInfo', 'rpc', 'encoded', 'Информация о сервере.' );

$server->register ( 'sendInfo', array (
'value' => 'tns:Info'
), array (), CONFIG::$wsnamespace, CONFIG::$wsnamespace . '#sendInfo', 'rpc', 'encoded', 'Отправить информацию о клиенте на сервер.' );

function Hello($str = "Guest") {
return "Привет, {$str}!";
}

function getInfo() {
return array('version' => CONFIG::$wsversion, 'name' => CONFIG::$wsservicename, 'datetime' => (new DateTime("now"))->format("Y-m-d\TH:i:s"));
}

function sendInfo($value) {
file_put_contents('result.txt', print_r($value, true));
    }

$HTTP_RAW_POST_DATA = isset ( $HTTP_RAW_POST_DATA ) ? $HTTP_RAW_POST_DATA : '';
$server->service ( $HTTP_RAW_POST_DATA );


Так же поправим обработку.


 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//
ВыбПутьПубликацииСервиса = "http://192.168.1.157/article02/?wsdl"; 
// в веб-сервисе мы прописали wsnamespace 
ВыбURIПространстваИменСервиса = "http://192.168.1.157/article02/"; 
// там же имя сервиса wsservicename 
ВыбИмяСервиса = "TestService";

// имя точки подключения совпадает с именем сервиса + слово Port 
ВыбИмяТочкиПодключения = "TestServicePort"; 
// Теперь объявим подключение 
Определение = Новый WSОпределения(ВыбПутьПубликацииСервиса); 
Сервис = Новый WSПрокси(Определение, ВыбURIПространстваИменСервиса, ВыбИмяСервиса, ВыбИмяТочкиПодключения); 

ТипВхПараметра = Сервис.ФабрикаXDTO.Тип("http://192.168.1.157/article02/", "Info");
ВходПар = Сервис.ФабрикаXDTO.Создать(ТипВхПараметра);

ВходПар.version = "1.0";
ВходПар.name = Метаданные.Имя;
ВходПар.datetime = ТекущаяДата();

Сервис.sendInfo(ВходПар);


После выполнения проверим, что в файле на сервере.
 
Array
(
    [version] => 1.0
    [name] => ЗарплатаИУправлениеПерсоналомБазовая
    [datetime] => 2014-10-19T23:41:12
)
        
 
Объединив полученные знания мы можем теперь обмениваться массивами структур (данных объектов).
 
(продолжение - скоро)