Yii Framework Forum: Reading and saving properties in INI files. - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Reading and saving properties in INI files. How to store page setting under INI files? Rate Topic: ***** 1 Votes

#1 User is offline   KEo 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 16-October 09
  • Location:Cracow, Poland

Posted 25 October 2009 - 07:05 AM

I just wonder to store some of the setting outside Db and keep them in flat files (eg. properties ini files). There is already support for handling such file in php with standard parse_ini_file function. But what are you think about building some model for that purpose (e.g. extending CFormModel). Any solutions? Ideas?
0

#2 User is offline   lucifurious 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 184
  • Joined: 15-March 09
  • Location:Atlanta, GA.

Posted 25 October 2009 - 09:53 AM

Good idea, but has no business being in the Yii core. Better suited for Zii or just a standalone extension.
0

#3 User is offline   KEo 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 24
  • Joined: 16-October 09
  • Location:Cracow, Poland

Posted 25 October 2009 - 04:08 PM

Here you are my first approach to this matter. This solutions is quite specific to what I need at the moment, but could be easly tailored to any other ;).
From functional point of view we need:
  • Retrieve setting stored in external file by its name
  • Editing settings values from website level

From technical point following tasks needs to be done:
  • Reading and parsing given Ini file
  • Fetching all settings set
  • Retrieving setting stored in fetched set
  • Creating form to change settings values and save them in the same ini file.

So, lets to the work.

First lets extend CFormModel, put class attributes, validation rules and meaningful labels. Next lets implement load method for reading INI file and save for update it. Finally make this class implementing singleton pattern (optionally, but recommended).

<?php
class EasySettingsForm extends CFormModel {

	/**
	* According to CFormModel convention all public attributes will be treated as modelled one.
	*/
	public $pageTitle;
	public $itemsPerPage;
	public $topMenu; // 1 - will be displayed, 0 - will not
	public $footer; // 1 - will be displayed, 0 - will not
	
	private static $instance;
	
	public function getInstance(){
		Yii::trace('getInstance() request','org.maziarz.test');
		if (is_null(EasySettingsForm::$instance)) {
			EasySettingsForm::$instance = new EasySettingsForm;
			EasySettingsForm::$instance->load(); 
			Yii::trace('New instance has been created', 'org.maziarz.test');
		}
		return EasySettingsForm::$instance;
	}
	
	public function rules(){
		return array(
			array('pageTitle, itemsPerPage', 'required'),
			array('itemsPerPage, topMenu, footer' , 'CNumberValidator'),
		);
	}

	public function attributeLabels(){
		return array(
			'itemsPerPage' => 'Items per page',
			'topMenu' => 'Display top menu',
		 	'footer' => 'Display footer items',
		);
	}
	
	public function load(){
		$ini_array = parse_ini_file(Yii::getPathOfAlias('webroot')."/protected/config/site.ini");
		$this->setAttributes($ini_array);	
	}
	
	public function save(){
		$configFile = Yii::getPathOfAlias('webroot')."/protected/config/site.ini";
		file_put_contents($configFile, ";config.ini");
		foreach ($this->getAttributes() as $name=>$value) {
			file_put_contents($configFile, "\n".$name." = ".$value, FILE_APPEND);
		}
		
	}

}


Now lets create some action for displaying and editing settings:

	public function actionSettings(){
		$settings = new EasySettingsForm;
		$settings->load();
		if (isset($_POST['EasySettingsForm'])){
			$settings->attributes=$_POST['EasySettingsForm'];
			if ($settings->validate()){
				$settings->save();
				Yii::app()->user->setFlash('settings', 'Site settings has been successfully saved.');
			}
		}
		
		$this->render('easySettings', array('settings'=>$settings));
	}


and relevant view:

<?php if(Yii::app()->user->hasFlash('settings')): ?>
<div class="confirmation">
	<?php echo Yii::app()->user->getFlash('settings'); ?>
</div>
<?php endif;?>

<?php echo CHtml::errorSummary($settings); ?>

<?php echo CHtml::beginForm('','post',array('enctype'=>'multipart/form-data')); ?>

<div class="row">
	<?php echo CHtml::activeLabel($settings,'pageTitle'); ?>
	<?php echo CHtml::activeTextField($settings,'pageTitle'); ?>
</div>

<div class="row">
	<?php echo CHtml::activeLabel($settings,'itemsPerPage'); ?>
	<?php echo CHtml::activeTextField($settings,'itemsPerPage'); ?>
	<?php echo CHtml::error($settings,'itemsPerPage'); ?>
</div>

<div class="row">
	<?php echo CHtml::activeLabel($settings,'topMenu'); ?> <br></br>
	<?php echo CHtml::activeRadioButtonList($settings, 'topMenu', array("1"=>"Yes", "0"=>"No"));?>
	<?php echo CHtml::error($settings,'topMenu'); ?>
</div>

<div class="row">
	<?php echo CHtml::activeLabel($settings,'footer'); ?> <br></br>
	<?php echo CHtml::activeRadioButtonList($settings, 'footer', array("1"=>"Yes", "0"=>"No"));?>
	<?php echo CHtml::error($settings,'footer'); ?>
</div>

<div class="row">
	<?php echo CHtml::submitButton('Save'); ?>
</div>

<?php echo CHtml::endForm(); ?>


Finally we can use our settings object wherever we want. Almost wherever ;) - at least we can use it in view files -> in particular layout view is good example where you will can easily disabling or enabling different stuff (menus, portlets, stylesheets, etc.).

Example:
..
<title><?php echo EasySettingsForm::getInstance()->pageTitle ?></title>
</head>

<body>
	<div id="container" class="c">
		<div id="header" class="c is_container">
			<div id="headerTop"></div>
			
			<div id="headerBody"></div>
			<?php if (EasySettingsForm::getInstance()->topMenu): ?>		
			<div id="headerMenu">
				<?php $this->widget('EWTopMenu'); ?>
			</div>
			<?php endif; ?>
		</div>
..


I hope some of you found this solution helpful or even interesting. I am also sure some will find here a field for enhancements - you welcome.
0

#4 User is offline   cmx 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 21-November 09
  • Location:California USA

Posted 20 December 2009 - 06:22 PM

View Postxx666xx, on 25 October 2009 - 09:53 AM, said:

Good idea, but has no business being in the Yii core. Better suited for Zii or just a standalone extension.


I'm not sure about that. If you need to integrate other applications with Yii, then a IConfig interface might be nice. This might allow a developer to create multiple config files in config/, allowing a third-party application to use a format other than PHP arrays. Then third-party developers can handle the integration using a common methodology by writing abstract classes for the various configuration formats (ini, xml, yaml, db, etc.). There is already an effort underway to store params in a database by Jonah and Konstantin.

Edit: The Claw framework stored on Tigris.org includes an IConfig interface with two abstract classes for supporting two different formats. If anyone is interested, Checkout the Claw version in SVN, not the most recent download.
0

#5 User is offline   cmx 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 42
  • Joined: 21-November 09
  • Location:California USA

Posted 20 December 2009 - 06:33 PM

View PostKEo, on 25 October 2009 - 04:08 PM, said:

I hope some of you found this solution helpful or even interesting. I am also sure some will find here a field for enhancements - you welcome.


This would probably make a good cookbook article.
0

#6 User is offline   wartur 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 21-May 12

Posted 25 October 2013 - 03:36 PM

this is Good class for simple application config.

Here is a more modern version of the code for Yii 1.1.14 from 2013 year :)

this is code:
model:
<?php

/**
 * Iniconf class file.
 *
 * @author		Krivtsov Artur <gwartur@gmail.com> | Made in Russia
 * @copyright	No copyright, Public domain
 * @link		wartur.ru
 * @license		Public domain
 */

/**
 * @property string $filename finename
 */
class Iniconf extends CFormModel {
	const FILENAME = '/data/config.ini';
	
	/**
	 * @var string admin email
	 */
	public $adminEmail = 'my@email.ru';	// this is public property and default value

	/**
	 * @return string ini file name
	 */
	public function getFilename()
	{
		// i think what config has only static files, all dynamic put into /data
		return Yii::getPathOfAlias('application').self::FILENAME;
	}

	/**
	 * Yii init
	 */
	public function init()
	{
		// on init only try load
		$this->load();
	}
	
	/**
	 * Yii rules
	 * @return type
	 */
	public function rules(){
		return array(
			array('adminEmail', 'required'),
			array('adminEmail', 'email'),
		);
	}
	
	/**
	 * Yii attr labels
	 * @return type
	 */
	public function attributeLabels(){
		return array(
			'adminEmail' => 'Admin Email',
		);
	}

	/**
	 * load ini
	 */
	public function load(){
		// has file?
		if(is_file($this->filename))
		{
			$ini_array = parse_ini_file($this->filename);
			
			// has any data?
			if(!empty($ini_array))
				$this->setAttributes($ini_array);
		}
	}

	/**
	 * Buffered save
	 * @return boolean
	 */
	public function save(array $data){
		$this->attributes = $data;
		
		if(!$this->validate())
			return false;
		
		$writeBuffer = ';config.ini'.PHP_EOL;
		
		foreach ($this->getAttributes() as $name=>$value)
			$writeBuffer .= "$name = $value".PHP_EOL;
		
		// return number, it can >= 12, need check result in other code
		return file_put_contents($this->filename, $writeBuffer);	// rewrite
	}
}


controller:
<?php

class SettingsController extends BaseAdminController
{
	
	/**
	 * Index
	 */
	public function actionIndex()
	{	
		$data = new Iniconf();
		
		if(Yii::app()->request->isPostRequest)
		{
			if($_POST['Iniconf'])
			{
				if($data->save($_POST['Iniconf']))
				{
					Yii::app()->user->setFlash('success', 'ini save');
					$this->redirectHimself();		// e.g $this->redirect('/settings/index');
				}
			}
		}
		
		$this->render('index', $data);
	}
}


view:
<!DOCTYPE html>
<html lang="ru">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>{this->pageTitle}</title>
</head>
<body>
	do not worry this part not layout.
	this is THP templater if you need =) thp.wartur.ru
	also i'm build application with bootstrap www.cniska.net/yii-bootstrap
<!--// BEGIN --><!--<? $this->layout = 'base_admin' ?>-->

<div class="row">
	<div class="span11">
		<h2>Config</h2>
		<?php $this->widget('bootstrap.widgets.TbAlert', array(
			'block'=>true, // display a larger alert block?
			'fade'=>true, // use transitions?
			'closeText'=>'&times;', // close link text - if set to false, no close link is displayed
		)); ?>
		<?php $form = $this->beginWidget('bootstrap.widgets.TbActiveForm', array(
			'type' => 'horizontal',
			'htmlOptions' => array(
				'class'=>'well'
			),
		)); ?>

			<?php echo $form->textFieldRow($data, 'adminEmail', array(
				'class'=>'span3',
				'placeholder' => 'my@email.ru'
			)); ?>

			<div class="form-actions">
				<button class="btn btn-danger" type="submit">Save</button>
			</div>
		<?php $this->endWidget(); ?>
	</div>
</div>

<!--\\ END -->
</body>
</html>


I warn you that the data storage in the ini file is not safe

I wish you all good luck :rolleyes:
1

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users