yakoffka.ru
грабли, костыли и велосипеды php, css, html, js и прочего

Использование SimpleXMLElement для получения данных

ошибки php«Название статьи некорректно отображает ее суть, так как описанное ниже затрагивает в равной степени и SimpleXMLElement и расширение SOAP и библиотеку highcharts. Причем разбор последней занял большую часть времени при подготовке статьи. Но если отображать все, то название будет слишком длинным, по этому, с Вашего позволения, оставлю все как есть..»

И сразу спойлер. Вот то, ради чего все ниженаписанное:

1
изучение wdsl сервиса

Для демонстрации воспользуемся открытым Web-сервисом Центрального банка Российской Федерации:

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

Для примера возьмем метод GetCursOnDateXML - Получение ежедневных курсов валют (как XMLDocument). Смотрим входные параметры и тип ответа сервера:

Code:
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  <wsdl:operation name="GetCursOnDateXML">
    <
wsdl:documentation>
      
Получение ежедневных курсов валют (как XMLDocument)
    </
wsdl:documentation>
    <
wsdl:input message="tns:GetCursOnDateXMLSoapIn"/><wsdl:output message="tns:GetCursOnDateXMLSoapOut"/>
  </
wsdl:operation>
  ...
  <
s:element name="GetCursOnDateXML">
    <
s:complexType>
      <
s:sequence>
        <
s:element minOccurs="1" maxOccurs="1" name="On_date" type="s:dateTime"/>
      </
s:sequence>
    </
s:complexType>
  </
s:element>
  <
s:element name="GetCursOnDateXMLResponse">
    <
s:complexType>
      <
s:sequence>
        <
s:element minOccurs="0" maxOccurs="1" name="GetCursOnDateXMLResult">
          <
s:complexType mixed="true">
            <
s:sequence>
              <
s:any/>
            </
s:sequence>
          </
s:complexType>
        </
s:element>
      </
s:sequence>
    </
s:complexType>
  </
s:element>
  

Из вышеприведенного фрагмента видим, что сервер желает получить параметр 'name="On_date" type="s:dateTime"' - ассоциативный массив с ключом 'On_date' и значением 's:dateTime' (на сайте w3schools.com утверждают, что это тип данных, использующийся для указания даты и времени в формате 'YYYY-MM-DDThh:mm:ss'), а ответ передаст нам как свойство GetCursOnDateXMLResponse->any. Больше нам ничего и не нужно.

2
создание SOAP клиента

На очереди создание SOAP клиента (предварительно необходимо проверить подключение модуля SOAP). В конструктор класса SoapClient необходимо передать URL WSDL-документа и получить объект для работы с нужным веб-сервисом.

Code:
0
$client=new SoapClient("http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL");

Посылаем запрос и принимаем ответ:

Code:
0
1
2
  $On_date=date('Y-m-d\TH:i:s');
  
$result=$client->GetCursOnDate(['On_date'=>$On_date]);// Soap-запрос
  
$any=$result->GetCursOnDateResult->any;// получение ответа

Смотрим, что скрывается за свойством, переданным в качестве ответа:

PHP Code:
0
1
2
  echo "<pre>";
  
var_dump($any);
  echo 
"</pre>";
Result:
string(15476) "<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-...

Мы получили строку с xml-документом. Используем страшное колдунство, и преобразуем полученный ответ в объект класса SimpleXMLElement. Таким образом все элементы xml-документа становятся свойствами объекта.

PHP code:
0
1
2
3
4
  $obj = new SimpleXMLElement($any);

  echo 
"<pre>";
  
var_dump($obj);
  echo 
"</pre>";
Result:
object(SimpleXMLElement)#4 (1) { ["ValuteData"]=> object(SimpleXMLElement)#5 (1) { ["ValuteCursOnDate"]=> array(34) { [0]=> object(SimpleXMLElement)#6 (5) { ["Vname"]=> string(273) "Австралийский доллар " ["Vnom"]=> string(1) "1" ["Vcurs"]=> string(7) "46.8380" ["Vcode"]=> string(2) "36" ["VchCode"]=> string(3) "AUD" } ... [33]=> object(SimpleXMLElement)#39 (5) { ["Vname"]=> string(266) "Японская иена " ["Vnom"]=> string(3) "100" ["Vcurs"]=> string(7) "57.9000" ["Vcode"]=> string(3) "392" ["VchCode"]=> string(3) "JPY" } } } }

обратимся же к свойствам объекта нашего и да получим желаемое:

Code:
00
01
02
03
04
05
06
07
08
09
10
11
12
13

  
echo "По данным Центробанка РФ сегодня, "
    
date('d.m.Y')
    . 
", в "
    
date('H:i')
    . 
$obj->ValuteData->ValuteCursOnDate[1]->Vname
    
" оценивается как "
    
$obj->ValuteData->ValuteCursOnDate[1]->Vnom
    
" "
    
$obj->ValuteData->ValuteCursOnDate[1]->VchCode
    
" : "
    
$obj->ValuteData->ValuteCursOnDate[1]->Vcurs
    
" RUB.<br>";
  
Result:
По данным Центробанка РФ сегодня, 05.10.2018, Азербайджанский манат оценивается как 1 AZN : 39.0283 RUB.

3
Выборка необходимой валюты

Так как количество валют, по которому сервис выдает информацию, непостоянно (проверено!), привязываться к индексу ValuteCursOnDate бесполезно и даже чревато. Поэтому добавим цикл с условием:

PHP Code:
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
  $needCode='USD';
  
$countVal=$obj->ValuteData->ValuteCursOnDate->count();
  for(
$j=1;$j<$countVal;$j++){
    if(
$obj->ValuteData->ValuteCursOnDate[$j]->VchCode==$needCode){
      echo 
"По данным Центробанка РФ сегодня, "
        
date('d.m.Y')
        . 
", в "
        
date('H:i')
        . 
" "
        
$obj->ValuteData->ValuteCursOnDate[$j]->Vname
        
" оценивается как "
        
$obj->ValuteData->ValuteCursOnDate[$j]->Vnom
        
" "
        
$obj->ValuteData->ValuteCursOnDate[$j]->VchCode
        
" : "
        
$obj->ValuteData->ValuteCursOnDate[$j]->Vcurs
        
" RUB.<br>";
    }
  }
Result:
По данным Центробанка РФ сегодня, 05.10.2018, в 13:50 Доллар США оценивается как 1 USD : 66.2115 RUB.

4
Построение графика

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

PHP Code:
000
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

  
// --------------- $php_code ---------------
  // ===============================================================
  // config
  
$res_mess='';

  
define("PATH_JS""/src/highstock/js");
  
define("PATH_JSON""/src/highstock/json");

  
$arr_curr=array('USD','EUR','UAH','AMD',);// необходимые валюты
  
$arr_mrrf7D=array('mrrf',);// Международные резервы Российской Федерации, еженедельные значения

  
define("START_TS"709722060);// временная метка начала графиков /за три дня до начала данных по USD/
  
$q=3;// количество запросов за одно обращение к скрипту
  
$refresh_content='<meta http-equiv="refresh" content="5; URL=' $_SERVER['SCRIPT_URI'] . '">';

  
// /config
  // ===============================================================



  // ===============================================================
  // получение временной метки уже имеющихся данных
  
$arr_i=array();
  foreach(
$arr_curr as $key=>$curr){
    
$path=DIR_PATH_JSON."/all_$curr.json";
    if(
file_exists($path)){
      
$file file_get_contents($path);
      
$arr_json json_decode($file,TRUE);
      
// $res_mess.=__line__ . print_r($arr_json,true)."<br>\n";
      
$arr_i[]=$arr_json[count($arr_json)-1][0];// последняя временная метка
    
}
  }
  
// $res_mess.=__line__ . print_r($arr_i,true)."<br>\n";

  
if(!empty($arr_i)){$i=max($arr_i);// надо бы проверку..
  
}else{$i=START_TS;}
  
// $res_mess.= __line__ . " \$i='$i';<br>\n";
  
unset($key,$curr,$path);
  
// /получение временной метки имеющихся данных
  // ===============================================================



  // ===============================================================
  // получение данных с сервера (Soap-запрос) и их обработка
  
$client=new SoapClient("http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL");// создание SOAP клиента
  // print_r($client->__getFunctions());// получение списка доступных функций

  
$date = new DateTime();
  
$date->setDate(date('Y',$i), date('m',$i), date('d',$i));

  
$no_data=true;
  for(
$n=1;$n<=$q;$n++){ // посылаем на сервер $q запросов

    // инкрементируем временную метку перед следующей итерацией
    
$date->add(new DateInterval('P1D'));//'P1M''P12M''P10D'
    
$i=mktime(13010$date->format('m'), $date->format('d'), $date->format('Y'));// Официальные курсы иностранных валют устанавливаются приказом Банка России каждый рабочий день обычно не позднее 13 часов по московскому времени

    // $res_mess.= "<br>\n";
    // $res_mess.= __line__ . " \$n='$n'; \$i='$i';<br>\n";
    
if($i<=time()){
      
// создаем ежедневный массив для каждой валюты с пустыми значениями
      
foreach($arr_curr as $curr){${'arr_d_'.$curr}=array($i,null,null);}

      
$On_date=date('Y-m-d\TH:i:s',$i);
      
// $res_mess.= __line__ . " \$On_date='$On_date';<br>\n";
      // echo $res_mess;exit;

      
$alert="<div class='mess'>Идет получение данных: " date('Y.m.d',$i) . ".</div></span>";
      
$meta_tag_from_tpl=$refresh_content;

      
$result=$client->GetCursOnDate(['On_date'=>$On_date]);// Soap-запрос
      
$any=$result->GetCursOnDateResult->any;// получение ответа
      
$obj = new SimpleXMLElement($any);// преобразование ответа в объект класса SimpleXMLElement
      // $res_mess.=__line__ . print_r($obj,true)."<br>\n";

      // <ValuteCursOnDate diffgr:id="ValuteCursOnDate1" msdata:rowOrder="0">
      //   <Vname>Австралийский доллар</Vname>
      //   <Vnom>1</Vnom>
      //   <Vcurs>47.6580</Vcurs>
      //   <Vcode>36</Vcode>
      //   <VchCode>AUD</VchCode>
      // </ValuteCursOnDate>
      
if(!empty($obj->ValuteData->ValuteCursOnDate)){
        
$countVal=$obj->ValuteData->ValuteCursOnDate->count();
        for(
$j=1;$j<$countVal;$j++){// перебираем все валюты
          
foreach($arr_curr as $curr){

            if(
$obj->ValuteData->ValuteCursOnDate[$j]->VchCode==$curr){
              
// для каждой валюты из списка создаем массив вида $arr_d_USD=array(845370050=>array(Vnom,Vcurs))
              
${'Vnom_'.$curr}=$obj->ValuteData->ValuteCursOnDate[$j]->Vnom->__toString()*1;
              ${
'Vcurs_'.$curr}=$obj->ValuteData->ValuteCursOnDate[$j]->Vcurs->__toString()*1;
              ${
'arr_d_'.$curr}=array($i,${'Vnom_'.$curr},${'Vcurs_'.$curr});
            }
          }
        }
      }else{
        
// $res_mess.= __line__ . " Err \$obj->ValuteData->ValuteCursOnDate is empty;<br>\n";
      
}

      foreach(
$arr_curr as $key=>$curr){// запись данных ежедневного массива в общий массив валюты
        
${'arr'.$curr}[]=${'arr_d_'.$curr};
      }

    }else{
// $i>time(); - превышено значение временной метки
      // $res_mess.= __line__ . " $i>" . time() . "; break.<br>\n";
      
$alert='';
      
$meta_tag_from_tpl='';
      break;
    }

    if(
$no_data==true and $i<=time()){
      
// $res_mess.= __line__ . ": $n в рассматриваемый момент времени ($i) нет данных о $curr;<br>\n";
    
}
  }
// посылаем на сервер $q запросов
  // /получение данных с сервера (Soap-запрос) и их обработка
  // ===============================================================



  // ===============================================================
  // перезапись файлов all_$curr.json
  
foreach($arr_curr as $key=>$curr){
    if(!empty(${
'arr'.$curr})){
      
$path=DIR_PATH_JSON."/all_$curr.json";
      
// $res_mess.= __line__ . " \$path='$path';<br>\n";
      // $res_mess.=__line__ . print_r(${'arr'.$curr},true)."<br>\n";

      // добавление данных к существующим
      
if(file_exists($path)){
        
$file file_get_contents($path);
        
$arr_json json_decode($file,TRUE);
        ${
'arr'.$curr}=array_merge($arr_json,${'arr'.$curr});// сливаем массивы
      
}unset($file,$arr_json);

      ${
'arr'.$curr}=json_encode(${'arr'.$curr});
      if(
file_put_contents($path,${'arr'.$curr})){
        
// $res_mess.= __line__ . " file_put_contents($path);<br>\n";
      
}else{
        
$res_mess.= __line__ " ERR not file_put_contents($path);<br>\n";
      }
      unset(${
'arr'.$curr});
    }unset(
$curr);
  }

  
// /перезапись файлов all_$curr.json
  // ===============================================================



  // ===============================================================
  // формирование файлов JSON для интеграции в графики highcharts
  // здесь только перезапись!
  
$names='';
  foreach(
$arr_curr as $key=>$curr){
    
$path=DIR_PATH_JSON."/all_$curr.json";
    if(
file_exists($path)){
      
$arr_json json_decode(file_get_contents($path),TRUE);
      
// для удобства просмотра графика воспользуемся номиналом Vnom последнего значения
      
$lastVnom=$arr_json[count($arr_json)-1][1];// последний номинал валюты

      
foreach($arr_json as $key_=>$val){
        
$i=$arr_json[$key_][0];// временная метка
        
$Vnom=$arr_json[$key_][1];// номинал валюты
        
$Vcurs=$arr_json[$key_][2];// курс валюты

        
if(!empty($Vcurs) and !empty($Vnom)){
          
$curs=$Vcurs/$Vnom;// стоимость единицы валюты
          
$curs=$curs*$lastVnom;// стоимость номинала валюты
        
}else{
          
$curs=null;
        }

        
$arr[]=array($i*1000,$curs);
      }unset(
$key_,$arr_json);

      
// создаем файл с указанием номинала $lastVnom в названии
      
$fn="$lastVnom$curr";
      
$path=DIR_PATH_JSON."/$fn.json";
      
$arr=json_encode($arr);
      if(
file_put_contents($path,$arr)){
        
// $res_mess.= __line__ . " file_put_contents($path);<br>\n";
        
$names.="'$fn', ";
      }else{
        
$res_mess.= __line__ " ERR not file_put_contents($path);<br>\n";
      }
      unset(
$arr);

    }unset(
$key,$curr);
  }
  
// /формирование файлов JSON для интеграции в графики highcharts
  // ===============================================================



  // ===============================================================
  // метод mrrf7D Международные резервы Российской Федерации, еженедельные значения
  
$arrSOAP=array(
    
'fromDate'=>date('Y-m-d\TH:i:s'0),
    
'ToDate'=>date('Y-m-d\TH:i:s'time()),
  );

  
$result=$client->mrrf7DXML($arrSOAP);// Soap-запрос mrrf
  
$any=$result->mrrf7DXMLResult->any;// получение ответа

  
$obj = new SimpleXMLElement($any);

  if(!empty(
$children=$obj)){
    
$countVal=$obj->count();
    for(
$j=0;$j<$countVal;$j++){
      
$D0=$obj->mr[$j]->D0;
      
$i=strtotime($D0);
      
$val=$obj->mr[$j]->val;
      
$arr_mrrf7DXML[]=array($i*1000,($val->__toString())*1);
    }
  }

  
// обновление данных в файле JSON.
  
if(!empty($arr_mrrf7DXML)){// массив полученных данных существует и не пуст
    
$path=DIR_PATH_JSON.'/mrrf7DXML.json';
    
file_put_contents($path,json_encode($arr_mrrf7DXML));  // Перекодировать в формат и записать в файл.
  
}
  
// /метод mrrf7D Международные резервы Российской Федерации, еженедельные значения
  // ===============================================================;
  // $res_mess.= __line__ . " end;<br>\n";
  

В html-блок страницы добавим разметку для отображения графиков:

html+js:
000
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  <!-- тело графиков -->

  <
div class='mess'><?php echo $res_mess;?></div>
  <div class='mess'><?php echo $alert;?></div>
    <!-- main_content -->
  <script src="<?php echo LINK_PATH_JS;?>/jquery-3.1.1.min.js"></script>
  <script src="<?php echo LINK_PATH_JS;?>/highstock.js"></script>
  <script src="<?php echo LINK_PATH_JS;?>/exporting.js"></script>
  <script src="<?php echo LINK_PATH_JS;?>/export-data.js"></script>


  <div id='container1' style='height: 600px; min-width: 310px'></div>
  <div id='container2' style='height: 400px; min-width: 310px'></div>


  <!--[if lt IE 9]>
    <script src="https://code.highcharts.com/modules/oldie.js"></script>
    <![endif]-->

  <?php //https://www.highcharts.com/stock/demo/compare?>
  <script type="text/javascript">
    jQuery.noConflict();
    var example = 'compare',
      theme = 'default';
    (function($) { // encapsulate jQuery

      var seriesOptions = [],
        seriesCounter = 0,
        // names = ['MSFT', 'AAPL', 'GOOG' ,'USD'];
        names = [<?php echo $names;?>];

      /**
       * Create the chart when all data is loaded
       * @returns {undefined}
       */
      function createChart() {

        Highcharts.stockChart('container1', {
          title: {
            text: 'График динамики курсов валют'
          },
          subtitle: {
            text: 'Источник <a href="http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL">cbr.ru</a>'
          },

          rangeSelector: {
            selected: 4
          },

          // yAxis: {
          //   labels: {
          //     formatter: function() {
          //       return (this.value > 0 ? ' + ' : '') + this.value + '%';
          //     }
          //   },
          //   plotLines: [{
          //     value: 0,
          //     width: 2,
          //     color: 'silver'
          //   }]
          // },
          xAxis: {
              gridLineWidth: 1
          },

          yAxis: {
            title: {
                    text: 'value'
            },
            type: 'linear',
            labels: {
              formatter: function() {
                // return (this.value > 0 ? ' + ' : '') + this.value + '%';
                return this.value;
              }
            },
            plotLines: [{
              value: 50,
              width: 1,
              color: '#5290a4'
            },{
              value: 100,
              width: 1,
              color: '#5290a4'
            }]
          },

          plotOptions: {
            series: {
              //compare: 'percent',
              showInNavigator: true
            }
          },

          // tooltip: {
          //   pointFormat:
          //  '<div style="color:{series.color}">{series.name}</div>:
          //  <b>{point.y}</b> ({point.change}%)<br/>',
          //   valueDecimals: 2,
          //   split: true
          // },
          tooltip: {
            pointFormat: '<div style="color:{series.color}">{series.name} : {point.y}RUB</div>',
            valueDecimals: 5,
            split: true
          },

          legend: {
              align: 'center',
              verticalAlign: 'bottom',
          },


          series: seriesOptions
        });
      }

      $.each(names, function(i, name) {

        // $.getJSON('https://www.highcharts.com/samples/data/'
        //  + name.toLowerCase()
        //  + '-c.json',    function (data) {

        $.getJSON('<?php echo LINK_PATH_JSON."/";?>' + name + '.json', function(data) {

          seriesOptions[i] = {
            name: name,
            data: data
          };

          // As we're loading the data asynchronously, we don't know what order it will arrive. So
          // we keep a counter and create the chart when all the data is loaded.
          seriesCounter += 1;

          if (seriesCounter === names.length) {
            createChart();
          }
        });
      });
    })(jQuery);

  </script>


  <script type="text/javascript">
    jQuery.noConflict();
    var example = 'line-time-series',
      theme = 'default';
    // https://www.highcharts.com/demo/line-time-series
    (function($) { // encapsulate jQuery

      $.getJSON('<?php echo LINK_PATH_JSON;?>/mrrf7DXML.json',
        function(data) {

          Highcharts.chart('container2', {
            chart: {
              zoomType: 'x'
            },
            title: {
              text: 'График еженедельных значений международных резервов Российской Федерации'
            },
            subtitle: {
              text: document.ontouchstart === undefined ?
                'Источник <a href="http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx?WSDL">cbr.ru</a>
                 Click and drag in the plot area to zoom in' : 'Pinch the chart to zoom in'
            },
            xAxis: {
              type: 'datetime'
            },
            yAxis: {
              title: {
                text: 'млрд долл. США'
              }
            },
            legend: {
              enabled: false
            },
            plotOptions: {
              area: {
                fillColor: {
                  linearGradient: {
                    x1: 0,
                    y1: 0,
                    x2: 0,
                    y2: 1
                  },
                  stops: [
                    [0, Highcharts.getOptions().colors[0]],
                    [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
                  ]
                },
                marker: {
                  radius: 2
                },
                lineWidth: 1,
                states: {
                  hover: {
                    lineWidth: 1
                  }
                },
                threshold: null
              }
            },

            series: [{
              type: 'area',
              name: 'млрд USD',
              data: data
            }]
          });
        }
      );
    })(jQuery);

    // yakoffka
    Highcharts.setOptions({
      lang: {
        months: [
          'января', 'февраля', 'марта', 'апреля', 'мая', 'июня',
          'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'
        ],
        shortMonths: [
          'янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сент', 'окт', 'нояб', 'дек',
        ],
        weekdays:[
          'воскресенье', 'понедельник', 'вторник', 'среда', 'четверг', 'пятница', 'суббота',
        ],
        shortWeekdays:[
          'вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб',
        ],
      }
    });
  </script>

  

Да, кстати, для автообновления страницы по необходимости в голову воткнем вот это:

html:
0
1
2
3
4
  <head>
  ...
    <?
php if(!empty($meta_tag_from_tpl)){echo $meta_tag_from_tpl;}else{echo "<!-- empty -->";}?>
  ...
  </head>