Jump to content
Дизайн и модификация IPS Community IPBSkinsBETA
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
TemKa_SD

Node сохранение формы во внешнюю таблицу

Recommended Posts

Здравствуйте. имею две таблицы:

 

wc3_mapcfgs - основная для Node, используется для добавления, редактирования форм: http://prntscr.com/ng4iwq

wc3_mapcfgs_configuration - настройки, которые выбирает хост бот на C++: http://prntscr.com/ng4jbg

 

Задача: связать формы и добавление/изменение из них настроек в таблицу wc3_mapcfgs_configuration.

 

Я всё реализовал кроме сохранения и изменения настроек:

 

public function form( &$form )
{
$form->add( new \IPS\Helpers\Form\Text( 'mapcfg_name', $this->mapcfg_name, TRUE, array(), NULL, NULL, NULL ) );
$form->add( new \IPS\Helpers\Form\Node( 'map_id', isset($this->map_id) ? $this->map_id : NULL, TRUE, array( 'class' => 'IPS\wc3\Map' ) ) );
}

public function formatFormValues( $values )
{
isset($values['map_id']) ? $values['map_id'] = $values['map_id']->_data['id'] : NULL;

$this->updateAsSettings($values);

return $values;
}

public function updateAsSettings( $values )
{
if ( isset( $values['map_id'] ) )
{
	$map = \IPS\wc3\Map::load( $values['map_id'] );

	$values['map_localpath'] = $map->_data['map_name'];
	$values['map_path'] = "Maps\\Download\\" . $map->_data['map_name'];

	unset($values['map_id']);
}

if ( isset( $values['mapcfg_name'] ) )
{
	isset($values['mapcfg_name']) ? $cfg_name = $values['mapcfg_name'] : NULL;

	unset($values['mapcfg_name']);
}
}

 

updateAsSettings() - функция, которая разбирает значения для сохранения, вставки в таблицу: wc3_mapcfgs_configuration

 

Два foreach, для обновления и вставки записей, оно работает всё в порядке:

 

foreach ($values as $key => $value) {
\IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) );
}

foreach ($values as $key => $value) {
\IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) );
}

 

Вопрос в следующем: Как правильно реализовать вставку, обновление полей?

Edited by TemKa_SD

Share this post


Link to post
Share on other sites

Сделал через $this->id

 

if ( !$this->id )
{
foreach ($values as $key => $value) {
	\IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) );
}
} else {
foreach ($values as $key => $value) {
	\IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) );
}
}

 

но оно мне не подходит, дело в том, что, весь конфиг я не хочу записывать, большая его часть использует стандартные значения в C++. Т.е там порядка 15 параметров, а для работы обязательных всего 2, это путь к карте и название карты.

 

Т.е если я запишу два параметра изначально из формы, потом когда захочу отредактировать её - будут редактироваться только старые параметры, которые, вставлялись через insert при создании $this->id, т.е это два параметра из 15. Нужно как-то проверять на наличие параметров во нешней таблице, которая НЕ используется формой.

 

Т.е нужна проверка если параметра нет - insert, иначе update и тут не учитывается $this->id. Помогите кодом плиз, это из формы же нужно делать? выборку.

Edited by TemKa_SD

Share this post


Link to post
Share on other sites
Вопрос в следующем: Как правильно реализовать вставку, обновление полей?

Запросить в бд строку по этому условию, если оно имеется - обновлять. Если отсутствует - вставлять.

Share this post


Link to post
Share on other sites

Ну вот я сделал обновление:

 

foreach ( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) as $k )
{
if ($k == key($values)) {
	foreach ($values as $key => $value) {
		$value ? \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) ) : NULL;
	}
}
}

 

Как теперь вставить? Т.е как написать if foreach else insert.

Share this post


Link to post
Share on other sites

$result = \IPS\Db::i()->select( 'mapcfg_name', 'wc3_mapcfgs', array( 'mapcfg_name=?', $cfg_name ) );
if( $result->count() )
{
foreach( $values as $k => $v )
{
	\IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $v ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $k ) );
}
}
else
{
//INSERT wc3_mapcfgs
//INSERT static::$cfgTable
}

 

Как-то так.

Share this post


Link to post
Share on other sites

Нет, это не то.

 

Давайте заново.

 

Сначала мне нужно выбрать текущие значения, которые есть в БД с where cfg_name = текущее сохраняемое имя конфига.

 

Т.е как в моем запросе:

 

foreach ( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) as $k )

 

Здесь я выбираю массив с текущими значениями: http://prntscr.com/ngnz7x т.е select cfg_key from static::$cfgTable where cfg_name=map1

 

Дальше сравниваем найденные значения в БД с теми, которые сохраняем в данный момент:

 

if ($k == key($values)) {

 

Т.е если КЛЮЧ в бд равен Ключу сохраняемого значения (map_localpath) то выполняем обновление, значит данные нужно обновить в этом поле а не вставить.

Иначе, нужно выполнить insert.

 

Т.е код рабочий, мне в него просто insert Нужно добавить ЗА foreach, так как если резульатов в нем не будет, внутри условия не будут выполнены.:

 

		foreach ( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) as $k )
		{
			if ($k == key($values)) {
				foreach ($values as $key => $value) {
					$value ? \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) ) : NULL;
				}
			}
		}

Share this post


Link to post
Share on other sites

Тест: Создаем конфиг: http://prntscr.com/ngo96s (правильно), добавляем в него новое значение (редактируем): http://prntscr.com/ngo9ic здесь вот добавились уже существующие значения и новое (не правильно), должно быть только новое значение.

 

$result = \IPS\Db::i()->select( 'mapcfg_name', 'wc3_mapcfgs', array( 'mapcfg_name=?', $cfg_name ) );
// Если конфиг уже существует, вы полняем условия.
if( $result->count() )
{	// Выбираем текущие значения ключи из БД
foreach ( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) as $k )
{	// Если ключ БД равен срхраняемому, выполняем обновление
	if ($k == key($values)) {
		foreach ($values as $key => $value) {
			$value ? \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) ) : NULL;
		}
	}
	// Иначе insert
	else {
		foreach ($values as $key => $value) {
			$value ? \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) ) : NULL;
		}
	}
}
}
// Если конфига нет, только создаем, записываем все данные.
else
{
foreach ($values as $key => $value) {
	$value ? \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) ) : NULL;
}
}

Edited by TemKa_SD

Share this post


Link to post
Share on other sites

	if ( $this->id )
	{
		foreach ( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) as $k )
		{   // Если ключ БД равен срхраняемому, выполняем обновление
		    if ($k == key($values)) {
				foreach ($values as $key => $value) {
					$value ? \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $value ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) ) : NULL;
				}
		    }
		    // Иначе insert
		    else {
		    	// здесь должен быть insert, и вставленны те данные, еоторые не равны выше, которые не обновляются и вставляются.
		    }
		}
	} else {
		foreach ($values as $key => $value) {
			$value ? \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) ) : NULL;
		}
	}

 

Вот так, только дописать insert.

Share this post


Link to post
Share on other sites

Обновлять нужно если в бд отсутствует такой ключ, а не если он чему-то равен. Ничего сравнивать, тем более таким образом не нужно.

 

$result = iterator_to_array( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) );
if( $result )
{
$keys = array_map( function( $a ){ return $a['cfg_key']; }, $result );

foreach( $values as $k => $v )
{
	if( $v )
	{
		if( in_array( $k, $keys ) )
		{
			\IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $v ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $key ) );
		}
		else
		{
			\IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $k, 'cfg_value' => $v ) );
		}
	}
}
}
else
{
//INSERT mapеtable
//INSERT static::$cfgTable
}

  • Upvote 1

Share this post


Link to post
Share on other sites

Спасибо большое, работает!!!!!!!!!!

 

Добавил this->id

 

Исправил баг: return $a['cfg_key']; // здесь возвращалась строка, нужен массив.

 

Да, для меня это сложно еще, с array_map совсем не знаком.

 

Финальный код:

if ( $this->id )
{
$result = iterator_to_array( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) );
if( $result )
{
    $keys = array_map( function( $a ){
    	return $a;
    }, $result );

    foreach( $values as $k => $v )
    {
        if( $v )
        {
            if( \in_array( $k, $keys ) )
            {
                \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $v ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $k ) );
            }
            else
            {
                \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $k, 'cfg_value' => $v ) );
            }
        }
    }
}
} else {
foreach ($values as $key => $value) {
	$value ? \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) ) : NULL;
}
}

Share this post


Link to post
Share on other sites

Исправил баг: return $a['cfg_key']; // здесь возвращалась строка, нужен массив.

Это не баг. Его суть в том, чтобы из многомерного результат создать одномерный массив со всеми ключами. Только если выбирать одно поле в запросе, результат будет одномерный массив. Так что в принципе он здесь не нужен. Можете удалить. А в условие использовать in_array( $k, $result )

Share this post


Link to post
Share on other sites

	if ( $this->id )
	{
		$result = iterator_to_array( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) );
		if( $result )
		{
		    foreach( $values as $k => $v )
		    {
		        if( $v )
		        {
		            if( \in_array( $k, $result ) )
		            {
		                \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $v ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $k ) );
		            }
		            else
		            {
		                \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $k, 'cfg_value' => $v ) );
		            }
		        }
		    }
		}
	} else {
		foreach ($values as $key => $value) {
			$value ? \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $key, 'cfg_value' => $value ) ) : NULL;
		}
	}

 

Верно?

Share this post


Link to post
Share on other sites

Здравствуйте. Я хочу удалить строку, если её значение 0. Т.е http://prntscr.com/nhi2k6 тут 0, я хочу удалить эту строку, так как 0 и так берется в приложении на C++ изначально, и хранить это в конфиге нет смысла, чище бд будет.

 

Во первых, здесь дописываю если значение не равняется NULL, чтобы проходили нули в проверку: http://prntscr.com/nhi2uu.

 

Вставляем условие в если id уже есть и если его еще нет. В моем случае 0 передает как строку, наверно потому что у меня в форме RADIO:

 

$form->add( new \IPS\Helpers\Form\Radio( 'map_loadingame', isset($settings['map_loadingame']) ? $settings['map_loadingame'] : 0, FALSE, array(
'options' => array
(
	0 => 'Загрузка карты с заставкой',
	1 => 'В игре'
)
), NULL, NULL, NULL, 'map_loadingame' ) );

 

Где бы мне тут в форме указать что это int, не хочется делать новое условие для этого, лучше прям в форме?

 

public function updateAsSettings( $cfg_name, $settingValues )
{
if ( $this->id )
{
	$result = iterator_to_array( \IPS\Db::i()->select( 'cfg_key', static::$cfgTable, array( 'cfg_name=?', $cfg_name ) ) );
	if( $result )
	{
	    foreach( $settingValues as $k => $v )
	    {
			if ($v != '0')
			{
				if( \in_array( $k, $result ) )
				{
				    \IPS\Db::i()->update( static::$cfgTable, array( 'cfg_value' => $v ), array( 'cfg_name=? AND cfg_key=?', $cfg_name, $k ) );
				}
				else
				{
				    \IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $k, 'cfg_value' => $v ) );
				}
			}
			else
			{
				\IPS\Db::i()->delete( static::$cfgTable, array( 'cfg_name=? AND cfg_key=?', $cfg_name, $k ) );
			}
	    }
	}
} else {
	foreach ($settingValues as $k => $v) {
		if ($v != '0')
		{
			\IPS\Db::i()->insert( static::$cfgTable, array( 'cfg_name' => $cfg_name, 'cfg_key' => $k, 'cfg_value' => $v ) );
		}
	}
}
}

 

Вроде всё правильно?

 

P.S.: Для NULL тоже самое надо сделать, только я че-то не понял, почему оно так перестает вообще работать:

 

if ($v != '0' OR $v != NULL)

 

А так работает:

 

if ($v != '0' AND $v != NULL)

 

Условие должно выполнятся: Если V не равно 0 ИЛИ V не равно NULL. // Неужели я что-то не так думаю, сейчас оно должно искать оба параметра, т.е если V 0 и нулл тогда выполняется.

Edited by TemKa_SD

Share this post


Link to post
Share on other sites

Добавил, чтобы нельзя было редактировать имя конфига:

 

$this->mapcfg_name ? $disabled = TRUE : $disabled = FALSE;

$form->add( new \IPS\Helpers\Form\Text( 'mapcfg_name', isset($this->mapcfg_name) ? $this->mapcfg_name : NULL, TRUE, array( 'disabled' => $disabled ), NULL, NULL, NULL, 'mapcfg_name' ) );

 

Вроде всё правильно.

Share this post


Link to post
Share on other sites

Здравствуйте. Переписываю сохранение настроек, хочу реализовать через ActiveRecord. Я сейчас напишу задачу и проблемы.

 

Начнем по порядку, допустим, я подключил форму и всё остальное, выглядит это так:

 

<?php

namespace IPS\wc3\Bot;

class _Settings extends \IPS\Patterns\ActiveRecord
{
protected static $multitons;
public static $databaseTable = 'wc3_bots_configuration';
public static $databaseColumnId = 'cfg_botid';

public function form( &$form )
{
	$form->addTab( 'wc3_bots_settingsBot', 'cogs' );
	$form->add( new \IPS\Helpers\Form\Text( 'autohost_gamename' ));
}
}

 

_Settings - через этот класс сохраняются настройки, проблема в том, что, значения полей - это данные в базе данных а не ячейки.

 

Выглядит это так: http://prntscr.com/nz4yhe

 

cfg_name = это id поля формы.

cfg_value = значение поля формы.

 

т.е нужно сделать что-то вроде такого:

 

if ( $values = $form->values() )
{
foreach ($values as $key => $value) {
	$values['cfg_botid'] = 1;
	$values['cfg_name'] = $key;
	$values['cfg_value'] = $value;
}
}

 

Какой самый правильный способ для реализации этой задачи?

 

Может как-то через $form->saveAsSettings(); переопределив таблицу сохранения?

Edited by TemKa_SD

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...