newbie questions

Hi

I’m David and I’m from Portugal.

I’m a PHP programmer but I’m a newbie with Yii. I started to use Yii about 2 months ago and I had a hard time to understand all the potential of Yii.

Because I was used to program all from the begginning (without a framework), now it is hard to me to do simple things that in the past I took only 5 minutes to do. Now, sometimes, I take 2 hours just to find that exists another property that I have to give a value to make it works.

For example:

I have a form that has a field that I didn’t have any rule to apply. All the fields that are “required” were working, but that field that I didn’t want to require didn’t work. I almost make it “required” just to get it to work, but if I am using a top class framework, the idea is to do things “by the book” and with no workarounds. So, I spent a lot of time to find the reason for that doesn’t work and finally I found the property “safe”.

All this just to say that it is hard to find many things in Yii documentation.

For example, how can I find all the properties that I can use on fields of CActiveForm, starting on the page of CActiveForm (http://www.yiiframework.com/doc/api/1.1/CActiveForm)? Starting on this page, how many clicks do I have to do to get one page with all that properties of rules (safe, unsafe, required, compare, email, etc)?

now that I already made my complaints ;) , the real big question (probably another one with a simple answer but I can’t find that answer).

I am working on a multi-language site, with all the words, phrases and sentences of each language being on a database. I have this working well, but with many workarounds. The problem is I can’t find a file where I can’t put the code to access to that table, copy that the values of the fields to a variable and that variable to be known in “all” files of Yii.

The code that I’m using is this:


<?php 

	$myLang="";

	$is_cookie = !empty(Yii::app()->request->cookies['cookieLang']->value);

	if(isset($_POST['Language']['chooseLanguage'])){ 

		$myLang = $_POST['Language']['chooseLanguage'];

	}else{

		if($is_cookie){

			$myLang = Yii::app()->request->cookies['cookieLang']->value;

		}

	}


	$connection=Yii::app()->db;

	if($myLang==""){

		$sql = "SELECT * FROM miscelanea LIMIT 0,1";

	}else{

		$sql = "SELECT * FROM miscelanea WHERE idLingua='$myLang'";

	}

	$command=$connection->createCommand($sql);

	$dataReader=$command->query();

	foreach($dataReader as $row) {

		$dataLang = $row;

	}

?>



The problem is, even that I put this code on main.php or index.php or column1.php, that variable $dataLang is not seen on my "view files", or on "controller files", or on "model files". My workaround was to put this code in all these files where I need it.

I know that this is bad, awful coding, but I can’t find a way that my variable $dataLang to be known on all files.

Worst, the example that I refered about CActiveForm was a hidden field that I sent by _POST to SiteController.php with a localized string to be passed to setFlash, just because I can’t find a way to access to my variable $dataLang.

View File


	<?php $form=$this->beginWidget('CActiveForm'); ?>

	

		<p class="note"><?php echo $dataLang['campos_obrigatorios_1']; ?> <span class="required">*</span> <?php echo $dataLang['campos_obrigatorios_2']; ?></p>

	

		<?php echo $form->errorSummary($model); ?>

	

		<div class="row">

			<?php echo $form->labelEx($model,$dataLang['Nome']); ?>

			<?php echo $form->textField($model,'nome'); ?>

		</div>

	

		<div class="row">

			<?php echo $form->labelEx($model,$dataLang['Email']); ?>

			<?php echo $form->textField($model,'email'); ?>

			<?php echo $form->hiddenField($model,'NewsletterInscrito', array('value'=>$dataLang['newsletter_ok'])); ?>

		</div>

	

		<div class="row buttons">

			<?php echo CHtml::resetButton($dataLang['Limpar'],array('id'=>'resetButton')); ?>

			<?php echo CHtml::submitButton($dataLang['Enviar'],array('id'=>'submitButton')); ?>

		</div>

	

	<?php $this->endWidget(); ?>



Model File


class ReceberNewsletter extends CFormModel

{

	public $nome;

	public $email;

	public $NewsletterInscrito;


	/**

	 * Declares the validation rules.

	 */

	public function rules()

	{

		return array(

			// NewsletterInscrito não precisa de regras

			array('NewsletterInscrito', 'safe'),

			// name, email are required

			array('nome, email, NewsletterInscrito', 'required'),

			// email has to be a valid email address

			array('email', 'email'),

			// verifyCode needs to be entered correctly

//			array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()),

		);

	}

}

Controller File


	public function actionReceber_Newsletter()

	{

		$model=new ReceberNewsletter;

		if(isset($_POST['ReceberNewsletter']))

		{

			$model->attributes=$_POST['ReceberNewsletter'];

			if($model->validate())

			{

				$headers="From: {$model->email}\r\nReply-To: {$model->email} Subject: Subscrever Newsletter";

				$myMensagem = "Nome:{$model->nome}\neMail:{$model->email}\n";

				mail(Yii::app()->params['adminEmail'],'Subscrever Newsletter',$myMensagem,$headers);

				Yii::app()->user->setFlash('receber_newsletter',$model->NewsletterInscrito);

				$this->refresh();

			}

		}

		$this->render('receber-newsletter',array('model'=>$model));

	}



As you can see, “NewsletterInscrito” field is just a hidden field to send a localized string to setFlash. I did this awful workaround because in the Controller File I can’t access to my variable $dataLang.

Any help, please.

P.S.: This will be the topic where I will put all my questions. Be careful. This topic will grow fast. :D

P.S.2: Sorry about my english. Without much practice on a daily basis it is hard to find the correct build of sentences or the right words.

If a piece of data and logic associated with it needs to be available globally, create an application component.

For translations stored in the database Yii already has a built-in component called CDbMessageSource . (guide)

I suggest you start a new topic for each new question.

Hi phtamas

Thanks for the answer… :)

I already saw CDbMessageSource, but unfortunally now is too late. I have the application almost finished and the solution that I got to multi-language is now dificult to change to CDbMessageSource, because I do not have much time to deliver the app to the client.

But, at least, I want to improve the code and start to became closer to Yii way of doing things, so the next project I can do all by the book.

Meanwhile, I really need to have a variable that will be known in all files of application (controllers, models, views, layout, etc). That variable is a simple unidimensional array that is populated with the content of a table from database.

I saw the link to application component, but I will be sincere. Without a sample, I’m strugling to understand the content of that page. Worst, even if I understand how to create that application component, I will not know where (in which file) I need to create it.

Can you give me an example of how to do that?

Thanks in advance

Cheers

Take a look at this wiki.

P.s: welcome to the forum!

A possible implementation:




class TranslationComponent extends CApplicationComponent implements ArrayAccess

{

	private $_translations;


	public function init() // this method will be called by the framework automatically, no need to call it in your code

	{

		// retrieve translation data from database and store it in $this->_translations

	}


	public function offsetExists($offset)

	{

		return isset($this->_translations[$offset]);

	}


	public function offsetGet($offset)

	{

		return isset($this->_translations[$offset]) ? $this->_translations[$offset] : null;

	}


	public function offsetSet($offset, $value)

	{

		throw new Exception('Can\'t set translation data directly.');

	}


	public function offsetUnset($offset)

	{

		throw new Exception('Can\'t unset translation data directly.');

	}


}



Save it as TranslationComponent.php in protected/components.

Modify your configuration (main.php):




'components' => array(

	'translation' => array(

		'class' => 'TranslationComponent',

	),

),



In your view script:




$dataLang = Yii::app()->translation;



Hi again

Sorry for late answer but on the first day on the forum I was restricted to 3 posts. :D

zaccaria: thanks for the link. It was the guide to achieve my needs. :)

phtamas: thanks for your example. Meanwhile, after seeing the link that zaccaria post, and before seeing your example, I advance to a solution. I don’t know if this is the better way of doing, but since that I already had done the rest of the site, I made this code:


<?php 

 

class dataLang extends CApplicationComponent

{

		public function getmyLang(){

			$myLang="";

			$is_cookie = !empty(Yii::app()->request->cookies['cookieLang']->value);

			if(isset($_POST['Language']['chooseLanguage'])){ 

				$myLang = $_POST['Language']['chooseLanguage'];

			}else{

				if($is_cookie){

					$myLang = Yii::app()->request->cookies['cookieLang']->value;

				}else{

					$sql = "SELECT idLingua FROM linguas WHERE Activada='1' LIMIT 0,1";

					$connection=Yii::app()->db;

					$command=$connection->createCommand($sql);

					$dataReader=$command->query();

					foreach($dataReader as $row) {

						$myLang = $row['idLingua'];

					}

				}

			}

			return $myLang;

		}

		public function getDataLang(){

			$myLang=$this->getmyLang();

		

			$connection=Yii::app()->db;

			if($myLang==""){

				$sql = "SELECT * FROM miscelanea LEFT JOIN linguas ON miscelanea.idLingua=linguas.idLingua WHERE Activada='1' LIMIT 0,1";

			}else{

				$sql = "SELECT * FROM miscelanea WHERE idLingua='$myLang'";

			}

			$command=$connection->createCommand($sql);

			$dataReader=$command->query();

			foreach($dataReader as $row) {

				$dataLang = $row;

			}

			return $dataLang;

		}

}

?>

And on the files where I need the translation, I did this way:


	

        $dataLang = Yii::app()->dataLang->dataLang;

	$myLang = Yii::app()->dataLang->myLang;



$myLang (bad name for a variable, I know) is the variable that contains the actual language

$dataLang is the array with the translations

The best way is the way that works best for your application :)

One note on your code:

In order to avoid SQL injection, unescaped input data ($myLang) should never be used in SQL queries. Please read the guide about parameter binding.