How to implement this feature in MVC

Hello everybody, I’m developing a Time Bank ( sorry, cant link it because it’s my first post: en.wikipedia.org/wiki/Time_Banking ) I’ve started for the apprenticeship of IT degree.

I must say this is my first MVC framework and so far it’s far better than i would have expected! Considering that I’m learning MVC architecture and the framework I’m still saving at least half time in developing! :P

I don’t want to bore you so I’m going to the point now: in this time bank, users are supposed to select categories of services they can be helpful in, and those whom they may need help with. There are 20 category by now in my draft, and they are organized in main categories.

I’m now trying to store them in a class, under components folder, in this way:


		$this->category = array(

            'Lezioni'=>array(

                0=>'Informatica',

                1=>'Lingue',

                2=>'Scuola ed universita\'',

                3=>'Musica',

            ),

            'Trasporto ed accompagnamento'=>array(

                4=>'Trasporto',

                5=>'Baby-sitting',

                6=>'Animali domestici',

                7=>'Gite'

            ),

            'Casa'=>array(

                8=>'Fai da te - Riparazioni',

                9=>'Pulizia',

                10=>'Giardinaggio',

                11=>'Cucina - catering',

                12=>'Cucito - maglieria',

                13=>'Estetica - bellezza',

            ),

            'Assistenza'=>array(

                14=>'Informatica',

                15=>'Consulenza',

                16=>'Traduzioni',

            ),

            'Attività'=>array(

                17=>'Sport',

                18=>'Artigianato',

                19=>'Sartoria - abiti',

            ),

        );

These are then needed so that users can select them by check-boxes and store selection in the database, and also select one of them as the category of their offers. The latter one is working pretty good with this method but I’m spending a lot of effort in implementing the first one, specially in the storing and fetching system.

By now I’m trying to use a binary string of 20 booleans and convert it to decimal, then store them in the user table.

The solution is working but looks definitively hackish, fancy and complex. So I wanted to ask if more experts users of this forum have any advice about it.

Thanks and sorry for the length…

You may serialize and save the object(with list of serivices), and unserialize after reading from db.

Is there any particular reason not to store them in the database? It would make things much simpler.

Thanks for your answers! O0

I’m familiar with java serialization, is it a PHP feature?

I skipped that hypothesis because it would need 20 columns at the moment, and i suppose more categories have yet to come! The only thing that i assume for sure is that they will have 2 levels, categories inside main categories!

Maybe I totally misunderstand your data model, but the following (simplified) database structure should work:

table_user

id

name

table_service_category

id

name

table_user_requests_service_category

user_id

service_category_id

table_user_provides_service_category

user_id

service_category_id

As for main categories and subcategories: they can be stored in the same table or in two related tables, both approaches have their pros and cons.

Seems it would work on storing, but what then when I’ll have to generate every checkBoxes and the dropDownList?

My approach works great with the dropDownList as I just have to pass that array to the function.

Maybe I could use serialization and two kind of array:

the first is the one i showed, for the dropDownList (int value to be stored=>label)

the second is a label=>boolean to store choices?

I’ll show you some code in case it may help:

Category class under components




/**

 * Category is the component defining category value=>label pairs

 */

class Category

{

	private $category;

    

    /**

     * Initialize the array

     */

	private function init()

	{

		$this->category = array(

            'Lezioni'=>array(

                0=>'Informatica',

                1=>'Lingue',

                2=>'Scuola ed universita\'',

                3=>'Musica',

            ),

            'Trasporto ed accompagnamento'=>array(

                4=>'Trasporto',

                5=>'Baby-sitting',

                6=>'Animali domestici',

                7=>'Gite'

            ),

            'Casa'=>array(

                8=>'Fai da te - Riparazioni',

                9=>'Pulizia',

                10=>'Giardinaggio',

                11=>'Cucina - catering',

                12=>'Cucito - maglieria',

                13=>'Estetica - bellezza',

            ),

            'Assistenza'=>array(

                14=>'Informatica',

                15=>'Consulenza',

                16=>'Traduzioni',

            ),

            'Attività'=>array(

                17=>'Sport',

                18=>'Artigianato',

                19=>'Sartoria - abiti',

            ),

        );

	}

    

    /**

     * Retrive the value of a label

     */

	public function getValue($label)

	{

		if(!isset($this->category))

            $this->init();

        foreach( array_keys( $this->category ) as $key )

        {

            if(array_search($label, $this->category[$key]))

                return array_search($label, $this->category[$key]);

        }

        return false;

	}	

    

    /**

     * Retrive the label of a value

     */

    public function getLabel($value)

	{

		if(!isset($this->category))

            $this->init();

        foreach( array_keys( $this->category ) as $key )

        {

            if(isset($this->category[$key][$value]))

                return $this->category[$key][$value];

        }

        return false;

	}

    

    /**

     * Retrive the array

     */

    public function getArray()

	{

		if(!isset($this->category))

            $this->init();

        return $this->category;

	}

}



The choice of the category on offer posting




<div class="row">

	<?php echo $form->labelEx($model,'category'); ?>

	<?php echo $form->dropDownList($model,'category', $category->getArray()); ?>

	<?php echo $form->error($model,'category'); ?>

</div>



[b]here comes the nasty one…category choosing by checkboxes

[color="#FF0000"]edit: I’ve just updated this so that’s more logic and works great, now the nasty part is the storing and retriving![/color][/b]




<?php $form->beginWidget( 'CTreeView', array( 'animated' => 'normal', 'htmlOptions'=>array('class'=>'treeview-gray') ) );

echo CHtml::openTag('ul');

foreach( array_keys( $category ) as $key )

{

    echo CHtml::openTag('li').

        CHtml::label($key, false).

        CHtml::openTag('ul').

        CHtml::checkBoxList($key,'',$category[$key],array('template'=>"<li>{input} {label}</li>", 'separator'=>'')).

        CHtml::closeTag('ul').

        CHtml::closeTag('li');

}

echo CHtml::closeTag('ul');

$form->endWidget(); ?>



This is the action in the user controller




    /**

    * allow users to add categories they may be helpful with

    */

	public function actionInsertHelpfulCategory()

	{

	   if(isset($_POST['insert-helpfulcategory-form']))

       {

            $binaryCategory = '';

            $index = 0;

            Yii::import( 'Category' );

            $categoryClass = new Category;

            $category = $categoryClass->getArray();

            foreach( array_keys( $category ) as $key )

            {

            	foreach( $category[$key] as $subCategory )

                {

                    if(isset($_POST['insert-helpfulcategory-form']['category'.$index++]))

                        $binaryCategory = '1'.$binaryCategory;

                    else

                        $binaryCategory = '0'.$binaryCategory;

                }

             }

             $userRecord = User::model()->findByPk(Yii::app()->user->getId());

             $userRecord->helpful_category = bindec($binaryCategory);

             $userRecord->save();

             Yii::app()->user->setState('helpful_category', true);

            if(Yii::app()->user->getState('needful_category') == false)

                $this->redirect(array('user/insertNeedfulCategory'));

             $this->redirect(Yii::app()->user->returnUrl);

       }

       $this->render('insertHelpfulCategory');

	}



Seems like I’ve done it!

Thanks elbek, serialization was the answer! (after a morning of hacking and craking)

I just puts all posted categories in the same array with checkboxlist(), then i obtain selected values with array_values, i serialize and save that array (es: array(0,5,8,9);).

Then I unserialize it and just pass to the view, then to the checkBoxList() and oplà, didn’t even have to touch the rest of the code!

;) thanks :))