Профиль
Информация Управление
Здравствуйте, уважаемый посетитель. К сожалению, Вы не были распознаны форумом, как зарегистрированный пользователь. Для полноценного использования возможностей нашего форума вам необходимо зарегистрироваться. Если вы уже зарегистрированы на форуме, то вам необходимо пройти авторизацию, используя Ваш логин и пароль. Зарегистрированные пользователи получают возможность возможность общения на нашем форуме.


[Новые сообщения · Правила форума · RSS ]
  • Страница 1 из 1
  • 1
[Tutorial] Использование ORM в плагине MySQL
OKStyle Дата: Воскресенье, 12.10.2014, 22:52 | Сообщение # 1
Архивариус
Группа: Администраторы
Зарегистрирован: 19.02.2011
Сообщений: 125
Репутация: 8
Статус: Offline
ORM - облегченный сценарий запросов. Доступен с версии R33 в плагине MySQL от BlueG. ( сейчас разрабатывается Pain123/maddinat0r ).

Первое, что необходимо сделать, это создать ORM экземпляр, идентификатор - id = orm_create(nametable[]) где nametable - название таблицы базы данных, которую мы будем использовать. Теперь некоторые глобальные (или static) переменные должны быть "привязаны" к ORM процессу путем вызова функции.

Для начала, давайте вспомним, какие запросы мы в основном посылаем к БД - SELECT(выборка информации из БД), INSERT(Вставка информации в БД), UPDATE(Обновление уже существующей информации в БД) и в редких случаях - DELETE. Рассмотрим банальный запрос, который существует в большинстве модах:

Код
new mSQL[256+1];  //мутим переменную для запроса
mysql_format(Actconnect,mSQL,"SELECT * FROM `my_user` WHERE Name = %s",his_name);  //составляем запрос
mysql_tquery(Actconnect,mSQL,"PlayerDataLoad","d",playerid);  //обращаемся к серверу


Что-то похожее явно есть у Вас в гейммоде. А вот как выполняется этот же запрос при помощи ORM:

Код
orm_select(PlayerInfo[playerid][ID_ORM],"OnPlayerDataLoad","d",playerid);  //ORM сценарий выборки данных игрока


Компактно, не правда ли? А теперь давайте рассмотрим callback первого и второго варианта. В первом случае, мы будем иметь что-то похожее на это:

Код
forward OnPlayerDataLoad(playerid);
public OnPlayerDataLoad(playerid) {
   new r,f; // кол-во строк и столбцов
    cache_get_data(r,f);   // Обрабатываем запрос, получаем кол-во строк и столбцов
          if(rows) {          //Смотрим, существует ли такая строка в таблице

         PlayerInfo[playerid][pLevel] = cache_get_field_content_int(0,"Level");   // Заполнение переменых
         PlayerInfo[playerid][pAdmin] = cache_get_field_content_int(0,"Admin");   
                 PlayerInfo[playerid][pLeader] = cache_get_field_content_int(0,"Leader");
                 PlayerInfo[playerid][pMember] = cache_get_field_content_int(0,"Member");
                 PlayerInfo[playerid][pSkin] = cache_get_field_content_int(0,"Skin");
                  
          }
          else print("Упс! Мы не нашли такого человека в базе!");  // Игрока нет
    return 1;
}


Второй снова порадует своей компактностью:

Код
forward OnPlayerDataLoad(playerid);
public OnPlayerDataLoad(playerid) {
    switch(orm_errno(Player[playerid][ID_ORM])){
     
         case ERROR_OK: printf("Player with ID:%d data load!"); //Все отлично, сценарий заполнил все данные игрока
         case ERROR_NO_DATA: printf("Player with ID:%d - LOADING ERROR"); //Ошибка, мы не нашли данных на этого игрока!
          
    }
    return 1;
}


Круто, не правда ли? Однако, чтобы давольствоваться такими прелестями нам всё же придется кое-где "заморочиться". Теперь, когда вы

примерно понимаете, в чем разница, начнем сначала и рассмотрим детали.

Для начала, разберемся в ORM-функциях, которые нам предлагают разработчики:

orm_create("название_таблицы") - создание ORM
orm_destroy(id:ORM) - удаление ранее созданного ORM

Код
new ORM:myorm = orm_create("players_table"); //создали
orm_destroy(myorm); //удалили


orm_errno(ORM:id) - проверка на ошибки при обработке. Вызывать в callback'ах основных сценариев.

Код
switch(orm_errno(myorm)) {
     
         case ERROR_OK: printf("Player with ID:%d data load!"); //Все отлично, сценарий заполнил все данные игрока
         case ERROR_NO_DATA: printf("Player with ID:%d - LOADING ERROR"); //Ошибка, мы не нашли данных на этого игрока!
          
    }


Основные сценарии:

orm_select(ORM:id,callback,format,float) и orm_load(ORM:id,callback,format,float) - сценарии идентичны запросу

SELECT (Получение информации)
orm_update(ORM:id) - сценарий идентичны запросу UPDATE (обновление)
orm_insert(ORM:id,callback,format,float) - сценарий идентичны запросу INSERT (вставка строки)
orm_delete(ORM:id) - сценарий идентичны запросу DELETE (удаление строки)
orm_save(ORM:id,callback,format,float) -очень умный сценарий. Комбинация INSERT и UPDATE. Если данной

строки нет в таблицы, то он выполняет INSERT(вставку), если же есть - UPDATE (обновление)

Функции привязки:

orm_addvar_int(ORM:id, &var, varname[]) - привязка целочисленной переменной.
orm_addvar_float(ORM:id, &var, varname[]) - привязка числа с плавающей точкой.
orm_addvar_string(ORM:id, &var, var_maxlen, varname[]) - привязка строки.

И немаловажные:
orm_setkey(ORM:id,varname[]) - относительно каких переменных выполняем поиск.(Что-то вроде конструкции: WHERE ID =)
orm_apply_cache(ORM:id, row) - применить кэширование. Используется при циклической загрузки множества данных.

Практическое применение...

Код
//глобальные переменные   
new kills, Float:kd_ratio, name[MAX_PLAYER_NAME+1];    

// ... структура запросов в функции   
orm_addvar_int(id, kills, "kills"); // orm_addvar_int(ORM:id, переменная, поле в БД[])   
orm_addvar_float(id, kd_ratio, "ratio"); // orm_addvar_float(ORM:id, переменная, поле в БД[])   
orm_addvar_string(id, name, sizeof(name), "name"); // orm_addvar_string(ORM:id, массив[], максимальная длина, поле в БД[])


Эти три запроса считают наши данные. Переменная должна быть либо глобальная либо статическая - другими словами, она не может быть в стеке! Теперь, когда вы поняли, что делает этот макрос, а, если нет, то мне придется показать вам то, что он делает - Он считывает ваши данные из таблицы. Покажу уже на более крупном примере.

Код
#include <a_mysql>   

enum E_PLAYER {   
      ORM:ORM_ID, // создаем идентификатор в енуменаторе.    
      ID,   
      Name[MAX_PLAYER_NAME+1],   
      Money,   
      Level,   
      Float:PosX,   
      Float:PosY,   
      Float:PosZ,   
};   
new Player[MAX_PLAYERS][E_PLAYER];   

public OnPlayerConnect(playerid)    
{   
         
      GetPlayerName(playerid, Player[playerid][Name], MAX_PLAYER_NAME);   
      new ORM:ormid = Player[playerid][ORM_ID] = orm_create("players"); // Создаем наше соединение!   
      // Считываем данные   
      orm_addvar_int(ormid, Player[playerid][ID], "ID");   
      orm_addvar_string(ormid, Player[playerid][Name], MAX_PLAYER_NAME+1, "Name");   
      orm_addvar_int(ormid, Player[playerid][Money], "Money");   
      orm_addvar_int(ormid, Player[playerid][Level], "Level");   
      orm_addvar_float(ormid, Player[playerid][PosX], "PosX");   
      orm_addvar_float(ormid, Player[playerid][PosY], "PosY");   
      orm_addvar_float(ormid, Player[playerid][PosZ], "PosZ");   
         
      orm_setkey(ormid, "Name"); // Устанавливаем имя для нашей дальнейшей проверки   
      orm_select(ormid, "OnPlayerDataLoad", "d", playerid); // Переходим к коллбеку   
      return 1;   
}   

forward OnPlayerDataLoad(playerid);   
public OnPlayerDataLoad(playerid)   
{   
      switch(orm_errno(Player[playerid][ORM_ID])) // Проверяем на ошибки   
      {   
          case ERROR_OK: {   
              ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Авторизация", "Введите ваш пароль", "Login", "Abort");   
          }   
          case ERROR_NO_DATA: {   
              ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Регистрация", "Введите ваш пароль", "Register", "Abort");   
          }   
      }   
      orm_setkey(Player[playerid][ORM_ID], "ID"); // Установим идентификатор игрока для будущих запросов!   
      return 1;   
}

public OnPlayerDisconnect(playerid, reason)    
{   
      if(Player[playerid][ID] != 0) {   
          orm_update(Player[playerid][ORM_ID]);   // Обновляем наши данные   
      }   
      orm_destroy(Player[playerid][ORM_ID]); // Удаляем наш идентификатор который мы создали в енуменаторе   

      for(new E_PLAYER:e; e < E_PLAYER; ++e)   
          Player[playerid][e] = 0; // Обнуляем переменные игрока   
      return 1;   
}


Теперь по-подробнее объясню об этой части:

Код
orm_setkey(ormid, "Имя");   
orm_select(ormid, "OnPlayerDataLoad", "d", playerid);[/php]

Что мы сделали?
1) Установили поле Name для запроса ( путем `Name` (WHERE часть запроса) )
2) Создали запрос: "SELECT `ID`,`Name`,`Money`,`Level`,`PosX`,`PozY`,`PosZ` FROM `players` WHERE `Name`='%s' LIMIT 1" (%s ник игрока)
3) Выполняем запрос ( Это делается в отдельном потоке! )
4) Обновляем данные с запрашиваемой информации.
5) Вызываем OnPlayerDataLoad с playerid в качестве единственного параметра после завершения запроса

При успешном запросе orm_error возвращает 0, при неудачном - 1.
* ERROR_OK (0)
* ERROR_NO_DATA (1)

Так ERROR_OK, для нас в данном случае обозначает, что игрок уже существует в базе данных, и мы можем продолжить нашу проверку пользователя - попросим его авторизоваться.   

Но другое дело здесь в том, что для будущих запросов, мы установили новый ключ в поле для запроса:

[code]orm_setkey(Player[playerid][ORM_ID], "ID");


Это понадобится нам для дальнейших запросов, например, с orm_update (как показано в OnPlayerDisconnect), orm_select или orm_delete. После того, как игрок отключается, мы удалить экземпляр с ORM orm_destroy(ORM:id). До этого, можно назвать все orm-уроженцы кроме orm_select и orm_update. Игрок должен зарегистрироваться на сервере, нам понадобится - orm_insert. Она создает запись в таблице. Синтаксис аналогичен orm_select:

Код
orm_insert(Плеер[playerid][ORM_ID], "OnPlayerRegister", "d", playerid);


Вы заметили, что значение Player[playerid][ID] обновляется. Мы послали запрос INSERT, далее мы должны использовать orm_setkey для идентификатора переменной перед вызовом orm_insert. Если вы этого не сделаете, новый ID будет сохранен в старую переменную переменной, и получится не то что мы хотим. Как обновить существующие данные в базу данных? Вот где мы должны будем использовать orm_update. Этот макрос создает UPDATE-запрос со всеми текущими значениями имеющихся у нас переменных. Например, пользователь User1 имеет ID 65 (не playerid, ID игрока-в таблице!), 4 уровня, имеет 54634$ и находится где-то в Лос-Сантосе. В этом случае, orm_update бы создать такой запрос:

Код
UPDATE `игроков` SET `Name`='User1', `Деньги`='54634', `Level`='3', `PosX`='745.231', `Букет`='-967.1425', `PosZ`='14.2543', ГДЕ `ID`='65'


Использование:
Код
orm_update(ORM:id);


Теперь мы можем генерировать практически все важные типы запросов, только DELETE-запрос отсутствует. Но не беспокойся, мы сейчас рассмотрим - orm_delete. Как вы могли догадаться, этот макрос создает DELETE-запрос. В нашем примере это было бы сформировать и отправить запрос:

Код
DELETE FROM `players` WHERE `ID`='65'


В отличие от orm_insert, orm_delete имеет дополнительный (необязательный) параметр с именем "clearvars". Если задано значение true, orm_delete не только стереть нужную запись в соответствующей таблице, он также восстановит регистрацию путем установки значениям переменных нулю (все зарегистрированные переменные, даже ключ). В этом уроке мы использовали в качестве примера систему аккаунта, но вы не должны ограничивать себя в этом! Вы можете управлять любыми данными, которые вы хотите, например, данные автомобилей или домов. Вот один пример того, как можно было бы загрузить транспортные средства с ORM системой:

Код
new SQL = -1;   

enum e_Vehicle   
{   
      ORM:ORM_ID,   
      VID,   
      ID,   
      ModelID,   
      Color1,   
      Plate[32],   
      Float:Pos[4],   
};   
new Vehicle[MAX_VEHICLES][e_Vehicle];   

public OnGameModeInit()   
{   
      mysql_log();   
        
      SQL = mysql_connect("127.0.0.1", "root", "test", "pass");   
        
      //загружаем автомобили   
      mysql_tquery(SQL, "SELECT * FROM `vehicles`", "OnVehiclesLoad", "");   
      return 1;   
}   

forward OnVehiclesLoad();   
public OnVehiclesLoad()   
{   
      for(new r=0; r < cache_num_rows(); ++r) {   
          new ORM:ormid = Vehicle[r][ORM_ID] = orm_create("vehicles");   

          orm_addvar_int(ormid, Vehicle[r][ID], "ID"); //это наш ключ   
          orm_setkey(ormid, "ID"); //сейчас мы ставим наш ключ для дальнейших запросов   
          orm_addvar_int(ormid, Vehicle[r][ModelID], "ModelID");   
          orm_addvar_int(ormid, Vehicle[r][Color1], "Color1");   
          orm_addvar_string(ormid, Vehicle[r][Plate], 32, "Plate");   
          orm_addvar_float(ormid, Vehicle[r][Pos][0], "PosX");   
          orm_addvar_float(ormid, Vehicle[r][Pos][1], "PosY");   
          orm_addvar_float(ormid, Vehicle[r][Pos][2], "PosZ");   
          orm_addvar_float(ormid, Vehicle[r][Pos][3], "PosA");   

          orm_apply_cache(ormid, r);   

          Vehicle[r][VID] = CreateVehicle(Vehicle[r][ModelID], Vehicle[r][Pos][0], Vehicle[r][Pos][1], Vehicle[r][Pos][2], Vehicle[r][Pos][3], Vehicle[r][Color1], -1, -1);   
      }   

      return 1;   
}


Авторы: georJik, Rex_Doberman


 
  • Страница 1 из 1
  • 1
Поиск:

Сайт управляется системой uCoz