please test my AR Enhancement: automatically sync MANY_MANY table when calling save()

The extension is very useful but, I think you must apply mrbig’s patch. Because the problem when saving. (If you don’t specify any Many Many relation to before save, there will be problem).

Hi all,

nice extension.

I got it to work quite easily, the only problem I had to fix by my own is about the kind of db connection it uses. In my project I have to connect to different databases according to the specific activerecord class I’m working with.

To do this I prepared some customized activerecord master classes (overriding the getDbConnection() method) from which I let my classes inherit accordingly.

However, the main point here is that I cannot always use Yii::app()->db connection, that is exactly the connection used in CAdvancedArBehavior extension.

Thus I simply replaced this:




        public function execute($query) {

		return Yii::app()->db->createCommand($query)->execute();

	}



with this:




        public function execute($query) {

		return $this->owner->dbConnection->createCommand($query)->execute();

	}



This should work in any case, either your class extends the standard CActiveRecord base class or a modified version of it (as in my case).

And of course I had to use mrbig’s patch as well to get everything work:

hope this can help someone else.

Hi everyone,

I noticed that this very usefull extension has absolutely no protection againts mysql injections.

I used this extension in conjuction with CHtml::checkBoxList(). One can easily inspect the page, and edit the value of a checkbox adding his sql code along with the value.

To stay safe, please update the code as follows:




	public function makeManyManyInsertCommand($relation, $value) {

		return sprintf("insert into %s (%s, %s) values (%s, %s)",

				$relation['m2mTable'],

				$relation['m2mThisField'],

				$relation['m2mForeignField'],

				Yii::app()->db->quoteValue(

                        $this->owner->{$this->owner->tableSchema->primaryKey}

                ),

				Yii::app()->db->quoteValue($value)

        );

	}


	public function makeManyManyDeleteCommand($relation) {

		return sprintf("delete ignore from %s where %s = %s",

                    $relation['m2mTable'],

                    $relation['m2mThisField'],

                    Yii::app()->db->quoteValue(

                        $this->owner->{$this->owner->tableSchema->primaryKey}

                    )

				);

	}



I recommend copy pasting this code over the functions you have because I edited the sql too, not only added the quoteValue() function.

Please don’t make other mistakes like this.

Thanks

Hi,

I used to have problems when saving an array of Model objects until I found mrbig’s patch and applied it. Just a heads up since the latest version (version 0.3) still doesn’t contain the patch.

@shark0der:

I believe that the enhancement assumes valid input - so there is no need to sanitize at the “behavior” level. It is up to the user to ensure the integrity of the data that will passed to and used by the behaviors. Let’s take the way you used the extension as an example. You use it in conjunction with a checkbox list - I assume you are not checking if the ids posted indeed correspond to actual/existing record ids. Otherwise, you won’t be needing to apply data sanitation in the behavior.

You forgot the golden rule of web development: NEVER TRUST USER INPUT!.

It’s not about checking if the ids exist in the database, it’s about peeps that insert malicious code instead.

I’ve a problem using this ext.

I’ve 2 Entity ParkingSlot and Street and the Relation ParkingSlot2Street.

I’ve defined 2 Models with MANY_MANY relation and i followerd the examples, and I did care about even the order of the fields in the relations definition.

Howerver If I try to add streets to ParkingSlot (inside the Controller) with:




$parking_slot = $this->loadModel($id);

$parking_slot->street = 1;

// or

$parking_slot->street = Street::model()->findByPk(1);

// or

$parking_slot->street = array(1);



I get the following error:




Property "ParkinSlot.Array" is not defined. (......\framework\base\CComponent.php:131) ....



I also add a $street property into the ParkingSlot Model but still the same!!

Any Hints??

Thanks guys for the work. Looks amazing.

For those of you like me just getting here, this behavior is part of a bigger project yii user management.

The initial repository was an svn one in Google Code. However, the latest one got moved to github.

You may find it here:

CAdvancedArBehavior.php

I’m having some problems with this extensions.

I think it’s all well defined. When i save new objects, the relation registers are created and everything seems ok.

The problem is when i use Table::model()->findByPk($pk) and i try to modify any field of the retrieved register in the main table.

When I save it, I get an error here in CAdvancedArBehavior.writeRelation() at the line:


$foreignobject = $foreignobject->{$foreignobject->$relation['m2mForeignField']};

It says Property "GCategorias.3" is not defined. It seems that the retrieved object by the MANY_MANY relation is not the same as the expected object.

If I print the object before save, this is what i get:


Array

(

    [0] => GCategorias Object

        (

            [_new:CActiveRecord:private] => 

            [_attributes:CActiveRecord:private] => Array

                (

                    [id_g_categoria] => 3

                    [descripcion] => voluntariado

                    [grupo] => 1

                )


            [_related:CActiveRecord:private] => Array

                (

                )

........

)

I have solved this bug changing the write relation method like this:


protected function writeRelation($relation) 

	{

		$key = $relation['key'];


		// Only an object or primary key id is given

		if(!is_array($this->owner->$key) && $this->owner->$key != array()) 		

			$this->owner->$key = array($this->owner->$key);


		// An array of objects is given

		foreach((array)$this->owner->$key as $foreignobject)

		{


			if(!is_numeric($foreignobject) && is_object($foreignobject)){

                            

                            if (is_numeric($foreignobject->$relation['m2mForeignField'])){

                                $foreignobject=$foreignobject->$relation['m2mForeignField'];

                            } else {

				$foreignobject = $foreignobject->{$foreignobject->$relation['m2mForeignField']};

                            }

                        }

			$this->execute(

					$this->makeManyManyInsertCommand($relation, $foreignobject));

		}

	}

Is it a bug or am I doing something wrong?

Do this extension supersede advancedrelationsbehavior?

what about the controller. What should be within the actionCreate?