Архив рубрики: PHP

В чем опасность использовать прямую работу с БД если есть API

Жил был скрипт, который использовал вот таакой запрос к БД Zabbix:

select sendto from media where userid in (select userid from (select users_groups.userid from operations inner join opmessage_grp on opmessage_grp.operationid=operations.operationid inner join users_groups on opmessage_grp.usrgrpid=users_groups.usrgrpid where operations.actionid in (select actionid from conditions where conditiontype=2 and value=%s union all select actionid from conditions where conditiontype=0 and value in (SELECT groups.groupid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s) union all select actionid from conditions where conditiontype=1 and value in (SELECT hosts.hostid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s)) union all select opmessage_usr.userid from operations inner join opmessage_usr on opmessage_usr.operationid=operations.operationid where operations.actionid in (select actionid from conditions where conditiontype=2 and value in (select triggers.triggerid from triggers where triggers.triggerid = %s union all select triggers.templateid from triggers where triggers.triggerid = %s) union all select actionid from conditions where conditiontype=0 and value in (SELECT groups.groupid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s) union all select actionid from conditions where conditiontype=1 and value in (SELECT hosts.hostid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s))) as us group by userid union all select userid from users_groups where usrgrpid=18) and mediatypeid=5

Единственной функцией котого было дать список телефонов пользователей по id триггера. И работал бы этот скрипт еще долго, если бы не случилось обновление Zabbix с 3.4 до 4.4 Структура БД изменилась. Запрос работать перестал. Посмотрел я на него, посмотрел.. И понял, я наверное был не в себе когда его писал, и повторить такой подвиг больше не смогу. Решил переписать его использую API Zabbix. Вышло много понятнее 😉

echo "-получаем api-key\n";
$res=$zab->Auth($login, $password);

$triggerid=$options["t"];
$txt=$options["s"];
$users_id_for_sms=array();
echo "-действия по триггеру\n";
$res=$zab->Execute("action.get", ["triggerids"=>$triggerid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
ParseRes($res);
echo "-получаем хост\n";
$hosts=$zab->Execute("host.get", ["triggerids"=>$triggerid]);
foreach ($hosts->result as $host) {
    $hostid=$host->hostid;
    $hostname=$host->name;
    echo "--действия по хосту $hostid $hostname\n";
    $res=$zab->Execute("action.get", ["hostids"=>$hostid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
    ParseRes($res);
    $hostsg=$zab->Execute("hostgroup.get", ["hostids"=>$hostid]);
    foreach ($hostsg->result as $hostg) {
        $groupid=$hostg->groupid;
        echo "--- действия по группе хоста $groupid\n";   
        $res=$zab->Execute("action.get", ["groupids"=>$groupid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
        ParseRes($res);

    }    
};
echo "- пользователи ZABBIX\n";   
var_dump($users_id_for_sms); 
$sms=array();
foreach ($users_id_for_sms as $userid) {    
    $res=$zab->Execute("user.get", ["userids"=>$userid,"output"=>'extend','status'=>0,"selectMedias"=>"extend"]);                     
    foreach ($res->result as $usersinfo) {        
        foreach ($usersinfo->medias as $md) {
            if ($md->mediatypeid==5){
              $sms[]=$md->sendto;  
            };
        };
        
    }
}
var_dump($sms);

function ParseRes($res){
global $zab,$users_id_for_sms;
    if (count($res->result)!=0){
        foreach ($res->result as $oper) {
            foreach ($oper->operations as $vl) {
                echo "---получаю пользователей группы\n";
                foreach ($vl->opmessage_grp as $usergroups) {
                  $usrgrpid= $usergroups->usrgrpid;
                  echo "----$usrgrpid\n";
                  $res=$zab->Execute("user.get", ["usrgrpids"=>$usrgrpid,"output"=>'extend','status'=>0]);                  
                  foreach ($res->result as $user) {
                   $users_id_for_sms[]=$user->userid;
                  };                                                      
//                  $res=$zab->Execute("user.get", ["usrgrpids"=>15,"output"=>'extend','status'=>0]);                  
//                  foreach ($res->result as $user) {
//                   $users_id_for_sms[]=$user->userid;
//                  };                                                                        
                };
                echo "---добавляю просто пользователей\n";                
                 //var_dump($vl->opmessage_usr);
                foreach ($vl->opmessage_usr as $userslist) {
                   $users_id_for_sms[]= $userslist->userid;
                };
                
            };            
        }
    };                             
};

Работа с API Zabbix из PHP

Поискал, поискал, ничего толкового не нашел. Пришлось написать самому. Выложил на GitHub. Описание актуального API Zabbix тут.

Пример использования:

include_once 'zabbix.php';

$url="https://my_zabbix.ru/api_jsonrpc1.php";
$login="weoriufeowiuf";
$password="owerierfoiewroi";

@include_once 'config.php';

// инициализация класса true/false - вывод в режиме debug
$zab=new Tzabbix(false);
$zab->SetCurlOpt(CURLOPT_URL,$url);
echo "-получаем api-key\n";
$res=$zab->Auth($login, $password);
if (isset($res->result)==true){
    if ($res->result!==false){        
        $res=$zab->Execute("host.get", ["output"=>["hostid","host"],"selectInterfaces"=>["interfaceid","ip"]]);
        var_dump($res);
    } else {
        var_dump($res);        
        die(-1);
    };    
} else {
  echo "--не понятная ошибка. попробуйте переключить в debug=true";  
};

Простейшая авторизация на PHP

Иногда проще бывает встроить «базовую» авторизацию в скрипт, чем «пилить» что-то специальное под авторизацию. К счастью протокол HTTP позволяет это сделать — а именно перед открытием страницы можно спросить у пользователя…ну например банальное логин-пароль. Например так:

if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="Enter login and passowrd"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Без авторизации нельзя!';
    exit;
}  else {

if (($_SERVER['PHP_AUTH_USER']=="pavel") and ($_SERVER['PHP_AUTH_PW']=="lkeslek")){

} else {
 die("Логин пароль не верен!");
};

PHPMyAdmin: Warning in ./libraries/sql.lib.php#613 count(): Parameter must be an array or an object that implements Countable

После обновления Ubuntu вдруг стала выходить такая ошибка в PHPNyAdmin в варнингах. Все не доходили руки посмотреть, да вот дошли. Это ошибка в файле /usr/share/phpmyadmin/libraries/sql.lib.php. Нужно найти сточку:

|| (count($analyzed_sql_results['select_expr'] == 1)

И исправить её на:

|| ((count($analyzed_sql_results['select_expr']) == 1)

Не правильно скобочки поставили разработчики  😉

Перенос скриптов с PHP 5.х на PHP 7.x

Чаще всего, основная проблема при переносе заключается в отсутствии в PHP 7.x модуля mysql, вместо него предлагается использовать mysqli. Однако если код достаточно обьемный, то перелопатить его чтобы адаптировать к новой версии PHP достаточно сложно и не всегда возможно. Однако есть выход: можно «эмулировать» устаревший код. Например эмуляция модуля mysql возможна следующим скриптом (достаточно его в код в виде include_once ‘mysql.php’) :

<?php
function mysql_connect($server,$username,$password,$new_link,$client_flags) {
  $GLOBALS['mysql_oldstyle_link']=mysqli_connect($server,$username,$password);
  return $GLOBALS['mysql_oldstyle_link'];
}

function mysql_query($sql) {
  return mysqli_query($GLOBALS['mysql_oldstyle_link'],$sql);
}

function mysql_fetch_row($res) {
  return mysqli_fetch_row($res);
}

function mysql_fetch_assoc($res) {
  return mysqli_fetch_assoc($res);
}

function mysql_fetch_array($res) {
  return mysqli_fetch_array($res);
}

function mysql_fetch_object($res) {
  return mysqli_fetch_object($res);
}

function mysql_affected_rows($link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_affected_rows($link);
}

function mysql_insert_id($link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_insert_id ($link);
}

function mysql_select_db($database_name) {
  return mysqli_select_db($GLOBALS['mysql_oldstyle_link'],$database_name);
}

function mysql_errno($link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_errno($link);
}

function mysql_error($link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_error($link);
}

function mysql_num_rows($res) {
  return mysqli_num_rows($res);
}

function mysql_free_result($res) {
  return mysqli_free_result($res);
}

function mysql_close($link) {
  return mysqli_close($link);
}

function mysql_real_escape_string($sql,$link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_real_escape_string($link,$sql);
}

function mysql_get_server_info($link=NULL) {
  if ($link===NULL) $link=$GLOBALS['mysql_oldstyle_link'];
  return mysqli_get_server_info($link);
}