There is already a great extension called YiiMongoDBSuite out for Yii so why make another? YiiMongoDBSuite has certain flaws which I wish to address:

Does not support $or natively

Very large and complicated code base

Does not support the later versions of the PHP driver (1.3.x series) that well

Obscured the MongoDB query language, layering a query language over the top

After some spare time I decided that I would take the liberty to make a MongoDB extension for Yii. It is basically a "glue" between MongoDB and
Yii and it is designed to be quite free form in that respect.

There are a few points of design I wished to enforce:

expose the MongoDB query language in its raw form

make the programming of this extension simple and easy to maintain for all parties

make sure this extension worked with both the new and old versions of the MongoDB driver

attempt to make things a little more performant

try to follow Yiis own CActiveRecord API as much as possible without compromising MongoDB "semantics" such as the name for query operators and the use of a MongoCursor

Okay, so we have got some of the rationale in place it is time to actually talk about the extension.

In order to use the extension you first need to set it up. The first thing to do is to download the source code and place it somewhere accessible within your applications structure, I have chosen
protected/extensions/MongoYii.

Once you have the source code in place you need to edit your main.php configuration file (console.php will need modifying too if you intend to use this extension in the console) with
the following type of configuration:

You will notice that I use a EMongoClient. This is a bit deceptive since it actually represents MongoClient and MongoDB combined. This means that whenever you call the magic __call
on the EMongoClient like so:

Yii::app()->mongodb->getSomething();

It will either try and call a function of getSomething in EMongoClient or, if the function does not exist, try and call it within the MongoDB class.

If you wish to call a function on the MongoClient or Mongo class you will need to retrieve the connection object like so:

Yii::app()->mongodb->getConnection()->getSomething();

EMongoClient is also designed to handle full write concern and read preferences in a compatible manner with all versions of the driver.

Note: The models will by default seek a mongodb component within your configuration so please make sure that unless you modify the extension, or use it without active record, to
make your default (master) connection be a component called mongodb.

If you wish to setup the log to insert entries into MongoDB (like in CDbLogRoute) you can add the following to your 'log' component configuration:

Each EMongoDocument or EMongoModel inherited class, i.e. your models will have a overrideable function called getMongoComponent(). You can simply override this to
return your custom application component, for example:

As an additional side note posted by @ujovlado on a related issue;
if you are only using Composer for Yii extensions then you can set a more blanketed solution of simply changing your vendor-dir to protected/extensions:

{
"config": {
"vendor-dir": "protected/extensions"}
}

However to have automatic handling of loading MongoYii using Composer you would require to downgrade to 1.0.3 where the Yii installer is not deprecated.
Failing both of those options you can also make your own script to handle what the removed installer used to.

Currently MongoYii does not handle namespaces and this is unlikely to change in Yii1.

This extension uses the new w variable globally to handle the level of write concern you wish to impose on MongoDB.

By default the extension will assume acknowledged writes, this means safe=true or w=1 depending on the version of your driver. To change this simply add w to your mongodb component configuration
and give it a value according to the PHP documentation.

For those using the 1.3.x series of the driver there is also a j option which can be set to either true or false within the configuration which allows you to control
whether or not the write is journal acknowledged.

Note: Write Concern is abstracted from the driver itself to make this variable compatible across all versions of the driver so please use the configuration or the EMongoClientw and
j class variables to set the write concern when you need to, otherwise that write concern will not be used within active record.

Note: Write Concern works differently when you touch the database directly and the write concern issued within the EMongoClient class will have no
effect. Instead you should always ensure in this case you specify the write concern manually according to your driver version.

This may change in the future but at the moment when you want the active record to go away it just will.

For those using the old driver there is only one extra configuration variable available to you, setSlaveOkay. Set this to either true or false in your configuration to make it
possible to read from members of a replica set.

For those using the 1.3.x series of the driver you have the RP configuration variable. The RP configuration variable is a 1-1 relation to the options of setReadPreference
on the MongoClient class with one exception. The first parameter is not a constant but instead the name of the constant. An example of using read preferences in your configuration
would be:

'RP' => array('RP_SECONDARY'/* The name of the constant from the documentation */,
array(/* Would normally be read tags, if any */))

You will recognise a lot of this from Yiis own active record, in fact a lot is the same. We define a name for the relation as a key and then we define either one or many in text
(constants seemed useless with only two types) and then we define a class name, Other in this case, and then we define the foreign key in that class, otherId.

The default behaviour of relations is to attempt to use the primary key, _id, of the current model to query the foreign key. This is a problem for EMongoModel
since it has no primary key. Make sure that if you use this in EMongoModel you define a on clause to replace the primary key of the current model.

The on clause supports multiple field types. It can take a DBRef or an ObjectId or an array of ObjectIds depending on how you define your document.

You can also, just like in Yii, define a where clause. This is a 1-1 relation to the syntax used within normal querying in MongoDB and the extension will basically merge this
clause with the primary key field you define in order to query for the relation.

As of 5.x relation caching in MongoYii is turned ON by default. This means that all relations are now cached. If you wish to make sure a relation is not cached you can explicitly add
'cache' => false to the relation definition like so:

The EMongoDocument extends EMongoModel and implements all of its features along with the needed features for database accession. It also implements as much as possible of
CActiveRecord.

Note: The functions that allow database usage are not defined within this section of the documentation. Instead those functions are actually defined within the "Querying" section.
Please move to the "Querying" section if you wish to read about this part of the EMongoDocument.

If you are using a primary key that IS NOT a ObjectId (otherwise known as a MongoId in the PHP driver) then you should override the getPrimaryKey function of the EMongoDocument
to not return a MongoId:

As you will notice the _criteria variable within the EMongoDocument which would normally be a EMongoCriteria object is actually completely array based.

This applies to all scope actions; they are all array based.

To help you in not having the EMongoCriteria object the EMongoDocument provides a helper function for merging criteria objects called mergeCriteria. Using this function will
have no impact on the model itself and merely merges criteria to be returned. As an example of using the mergeCriteria function:

It is normally best not to use this but instead to use the extension wrapped editions - updateAll and deleteAll. The only difference of said functions
from doing it manually on getCollection() is that these functions understand the write concern of the extension.

It is important, nay, imperative that you understand exactly how, by default MongoYii assigns integers. Since MongoDB has no strict handling of field types it is very easy
for boolean integers from the likes of checkboxes etc to end up as strings breaking your application and causing you to have to cast objects repeatedly or change the way you query
(since, of course, MongoDB is type aware when querying).

MongoYii will convert any number, real integer (otherwise known as "positive" or "unsigned" integer), not starting with 0 and not possessing a letter to an int.

This is important because the largest integer MongoDB can natively store is only 32bit. In order to make MongoDB store larger integers you must use the
native_long configuration variable available within the driver.

If you are on a 32bit system you will need to add another configuration variable to the stack: long_as_object.

Note: Integers greater than the systems limit will be left as strings. This means that on a 32bit system the maximum int you can assign from form data is 2147483647 while on a 64bit system it is 9223372036854775807.
If you wish to use int data types from forms past your systems limits you will be required to process the fields yourself, either within the CHttpRequest handler or using a validator.

Notice how I have added the addresses field despite not needing to? I do this due to the way that PHP uses magic functions.

If you access an array magically you cannot, in the same breath, manipulate it since it is an indirect accession of the variable. So a good tip here: if you plan on having subdocuments
it might be good to explicitly declare the field as a variable within the class.

Querying attempts to expose the native MongoDB querying language as much as possible. A EMongoCriteria class is provided, however, it is not required and does not provide any more functionality
than just doing it via arrays. The EMongoCriteria class is not relied on anywhere and is not needed.

find() is really simple. It is essentially a 1-1 to the drivers own find() function and implements the same specifics. Just like the drivers edition, it also returns a cursor
instance (EMongoCursor) which can be used to lazy load results from the database.

It will return a cursor irrespective of whether it finds results or not. However if it cannot find results then count will return 0 and the iterator will not have any iterations
to it.

Note: The cursor does not eager load documents, instead if you wish to accomplish this please wrap the call to find in a call to iterator_to_array.

findOne, just like findBy_id is a straight 1-1 implementation of the drivers own findOne method and returns an active record record model if something was found, otherwise null.

The findBy_id function takes either a hexadecimal representation of a ObjectId in string form or wrapped in the MongoId class and will seek out a record with that _id using
the findOne function, returning the exact same. It is basically a helper for findOne to make your life a little easier.

This validator was added as a easy, yet flexible, method to automate the conversion of hexidecimal representation of MongoIds (for example: addffrg33334455add0001) to the
MongoId object for database manipulation. This validator can also handle arrays of strings that need converting to MongoIds.

array('ids,id', 'EMongoIdValidator'), // ids is an array while id is a single string value

Subdocuments are, mostly, not automatically supported by this extension. There a couple of reasons, firstly due to performance - automating subdocument usage requires a lot of
loaded classes to handle different subdocuments and their validation.

The other main reason is that, in any project I have done, whenever I tried to automate subdocuments through active record it has always resulted in me actually ditching
it and doing the process manually. It has been proven many times that you rarely actually want automated subdocuments and normally you want greater control over their storage than
this extension could provide.

So that is a brief understanding of the rationale behind the idea to ditch automatic subdocument handling within the active record.

This does not mean you cannot embed subdocument classes at all; when saving, the active record class will iterate the document and attempt to strip any EMongoModel or EMongoDocument
classes that have sprung up.

This all aside, there is a subdocument validator and technically it can even accept multi-level nesting. Please bare in mind, though, that it will cause repetition
for every level you use it on. This WILL have a performance implication on your application.

type defines the type of subdocument, as with relations this is either one or many.

The validator will evaluate the rules as though they are completely separate from the originating model so in theory there is nothing stopping you from using any validator you want.

The error output for the validator will differ between the one and many types of subdocument. With one the validator will output the model errors directly onto the field
however with many it will create a new element for each model (row) with embedded errors in that new element in the field on the parent, for example:

Note: In order to get filters working on 1.1.4 the validator will now, by default, overwrite what you send into it with the results of the validator output. This means that if your
rules are not defined correctly you will lose fields within your subdocuments. You can combat this by setting the strict parameter of this validator to false.

Note: While on the subject, to avoid the iteration every time you save the root document (since validation is run by default in Yii on save) you should confine your subdocument
validators to specific scenarios where they will be actively used.

As we already know MongoYii does not handle subdocuments automatically for you. if you wish to have an automatic handler for subdocuments it is normally considered good advice to make
your own based on the scenarios you require. One reason for this is because many people have many different document setups and since there is no predefined schema for the subdocuments I
cannot provide automated usage without short of taking every single possibility of subdocument existence into account.

For this explanation we will assume you do not wish to make your own subdocument handler, but instead, are fine using MongoYiis and PHPs own built in abilities. Handling subdocuments depends heavily upon how you intend to manage and use them.

Okay, let's start at the top; are you using a class for these subdocuments? If the answer is "Yes sir!" then chances are that your subdocuments are quite complex and has a section in your
application all to itself with its own controller and everything like, for example, comments on a bog post.

Now the second question you must ask yourself; are you replacing these subdocuments every time you save them or do you want to use modifiers such as $push, $pull, $pullAll, $pushAll,
$addToSet ectera?

If you wish to use modifiers each time then the best way to manage these type of documents is to make the subdocument singular class extend EMongoModel, for example, Comment
would extend EMongoModel.

And you would use relatively similar behaviour for most other operations you need to perform. In this case MongoYii merely acts as a helper and glue for you to make life a little easier,
however, at the end of the day it will not auto manage subdocuments for you.

If you are not using a class then chances are your subdocuments are quite primative and most likely are just detail to the root document and you are replacing them each time. This scenario
also applies if you are using complex classes but you are replacing the subdocument list on each save.

If this is the case you can either use the subdocument validator mentioned above to process your subdocuments or you can actually programmably do this:

The EMongoCriteria class can help build modular queries across many segments of your application providing an abstracted layer with helper functions enabling you to better create complex
queries.

A brief, yet complete, example of using the EMongoCriteria would be:

$c = new EMongoCriteria();
User::model()->find($c
->addCondition(array('name' => 'sammaye')) // This is basically a select
->addOrCondition(array(array('interest' => 'Drinking'), array('interest' => 'Clubbing'))) // This is adding a $or condition to our select
->skip(2) // This skips a number of rows
->limit(3) // This limits by a number of rows
);

So you can see that quickly we can build very complex queries with ease.

Just like with CDbCriteria you can also set all of these properties of the query straight from the constructor like so:

You simply enter column, value and matchPartial parameter values (in that order) and the EMongoCriteria class will create a condition and merge it into your current condition
based upon the entered data. As examples:

$c->compare('name', 'sammaye');
$c->compare('i', '<4');

The compare funtion, as seen in the second example, will accept a certain number of operators. The operators supported are: <>, <=, >=, <, >, =.

It is good to note that the function currently only accepts AND conditioning.

And second, as a parameter injected into the read functions of the active record model, as an example:

User::model()->find(array(),array('_id'=>0,'d'=>1));

These will return partial=trueEMongoDocument instances, either eagerly or in a cursor object. This specification is implemented within all currently existing read functions such as
findOne and findBy_id and findByPk however, they are not accepted within the write functions (update, insert, save etc).

When a document is returned as partial it will only save the root level fields that are included within the result of the query.

Note: When using $elemMatch projection you must bare in mind that MongoYii will treat that result as the definitive result for that field. In other words when you go to save the
root document MongoYii will consider that single projected subdocument the complete field value and will erase all other subdocuments within that field.

Note: If _id is omitted via '_id' => 0 from the root document then you will not be permitted to save the document at all. The extension will instead throw an exception about the
_id field not being set.

MongoYii has a GridFS handler called EMongoFile. This class is specifically designed as a helper and is in no way required in order to use GridFS with MongoYii. What it does is
make it easy to upload, save and then retrieve files from GridFS. It is specifically oriented around uploading files from a form.

Let's go through an example of its usage as taken from the example in the test repository.
To upload a new file from a form you simply call the populate static function on the class like so:

EMongoFile::populate($model,'avatar')

This essentially says: "Get the uploaded file from the model user and the field avatar" The rest works much the same as a normal upload form. If populate returns anything except
null then it has found something.

To save the file to GridFS simply call save(). The class directly extends EMongoDocument as such this means that you have access to all the normal active record stuff as in
other classes.

If you wish to add a validator for the file object itself you must point it to the file variable of the class; be sure to only allow validators for the file object on create
otherwise Yii will not know how to handle the MongoGridFSFile object.

Note: Currently if you choose to call save on update it will overwrite the previous file. No versioning has been implemented.

Retreiving the file later is just as easy as saving it and is no different to finding any other record:

EMongoFile::model()->findOne(array('userId'=>Yii::app()->user->id))

This code snippet assumes we wish to find a file whose metadata field userId is of the current user in session.

The verisoning ability of a document cannot be changed during runtime once it has been set, in other words you cannot do $doc->removeVersion() to stop versioning from having
an effect for a certain insert.

After the documents model has been setup versioning works behind the scenes, there is no need for you to do anything else, everytime save is called it will make sure the
version you have is upto date.

Even though MongoDB is schemaless, you sometimes may need to modify your records. To do so, you may use the yiic mongomigrate command.
It works exactly like yiic migrate. For detailed usage, please refer to the yii docs.

To enable the command in your application, add a commandMap entry in your config file:

the aggregation framework does not fit well with active record as such it is not directly supported within the models, however, there is an aggregate helper on each model but
it will not return a model instance but instead the direct result of the MongoDB server response.

I am sure there are more but that is the immediate flaws you need to consider in this extension.

Please look to the tests folder for further examples of how to use this extension, it is quite comprehensive.

There is also a demonstration application built using MongoYii. It is effectively mimicking a Wikipedia type website and allows for user (including sessions) and article management.
It is not a good place to start if you are still learning Yii, however, it is a good place to start if you are learning MongoYii.

When adding extensive functionality to MongoYii please try and provide the corresponding unit tests. Without the unit tests your functionality, the very same your project most
likely relies on, may break in future versions.

If you are intending to contribute changes to MongoYii I should explain my own position on the existance of the EMongoCriteria class. I, personally, believe it is not needed.

There are a number of reasons why. In SQL an abstraction is justified by, some but not all, of these reasons:

Different implementations (i.e. MySQL and MSSQL and PostgreSQL) creates slightly different syntax

SQL is a string based querying language as such it makes sense to have an object oriented abstraction layer

SQL has some rather complex and difficult to form queries that would make an abstraction layer useful

MongoDB suffers from none of these problems; first it has an OO querying interface already, secondly it is easy to merge different queries together simply using CMap::MergeArray()
and most of all it has only one syntax since MongoDB is only one database. On top of this, due to the way MongoDBs querying is built up this class can actually constrict your querying
and make life a little harder and maybe even create unperformant queries (especially due to how difficult it is to do $ors in this class).

As such I believe that the EMongoCriteria class is just dead weight consuming memory which I could use for other tasks.

This extension does not rely on EMongoCriteria internally.

So I expect all modifications to certain parts of MongoYii to be compatible with and without EMongoCriteria.

The util folder contains general awesome extensions to MongoYii that people may find useful. The sort of things that count as part of this folder are replacements for internal pieces
of Yii that might seem outside of the scope of the root of this repository.

currently the quey parameter of this class only accepts the parts to be shown as parsed above, it does not currently allow you to actually grab the cursor directly.

Note: Do not put a cursor into this class, it will not save to your datastore in a manner that the PHP driver for MongoDB will be able to use it. Instead you will be
told that the MongoCursor was not correctly inited by its parent class(es).

I think me comparing this extension to YiiMongoDBSuite was probably a bad idea, there is none of their coding in this; it was done from the ground up from the beginning, nor was it based upon another project; it is completely new.

I did consider working with YiiMongoDBSuite people but it was too mature to change it to the point I would have wanted to.

This extension also works on some very different principles to YiiMongoDBSuite.

I don't think Yii making an inbuilt MongoDB handler would change much, making this extension has made me find numerous "flaws" which I do not agree with in the active record impementation and I would actually write a new extension to "resolve".

Few months ago, I spent lot of time finding which extension should I use to work with Mongo - and it was because of many forks of mongorecord, then mongosuite ... and so on.
I choosed YiiMongoDbSuite and through that time I thought about forking, rewriting ... and that's because that extension is so old. I have to rewrite some parts (add MongoClient, WriteConcern, remove safe).

It'll be pleasure to have one officially maintained extension, you know.

Could you open a topic in the forum for your extension (for discussion and support) and link to it from the description. Sadly it became common lately to use the comment section as support section - But for the good old sake I think there should be a topic in the forum.

An example of a bare CMongoDocument class would be great (or a simple notice that the model() and collectionName() methods are mandatory)

While you mention that you override set in CMongoModel to have a different behavior - you might as well should mention that you override CMongoClient::get() in a fashion that it prevents to act as usual (i.e. Yii::app()->mongodb->connection can not be used as shortcut for Yii::app()->mongodb->getConnection() [which is totaly fine - but a notice would be great])

You also mention that the component within the configuration MUST be called mongodb otherwise one has to feed the component in manually into each of the models. This is a bit missleading as it sounds like the extension does not support multiple mongo database connections. But as it turns out the component CAN be called anyway you want as long as you keep it consistent with the models (or don't even use models)

Coding related stuff:

In EMongoDocument::collectionName the comment states that the method should return "user" by default. In fact it returns NULL.

Why do you use methods without visibility modifier (public/protected/private). To me this is quite confusing. E.g. in your documentation you state that EMongoDocument::primaryKey() is private and can not be overridden. Since the method has in fact no modifier it is public by default and, at least technicaly, can be overridden. Would be great if you could add them, to ease reading / understanding the code :).

That beeing said: I appreciate your extension and you were right to rewrite it! Like it very much in terms of the approach that you used in order to support the original driver syntax and methods!

I noticed that you use annotations for making attribute virtual, but only for that? Parsing annotations just to get that one is IMHO not worth overhead. You should use annotations for more model details like embedding. I found such pattern extremly efficient in defining complex mongo models (with my fork of YMDS:P). And it is very clean too, as you dont have loads of methods in model, like: rules(), attributeLabels(), embeddedDocuments() etc. Also, to avoid disambigulations with phpdoc i think annotations should be started from great letter.

As addendum of my comment i recommend my extension yii-addendum for annotations, it even support get/set on public properties.

I didn't want to use annotations at all really but it was the cleanest way to provide a flexible, non-predefined, schema with attributes that should not be saved to the database in Yiis current form (maybe this will change in 2.0?).

Annotations are an extremely complex subject to get into and also require heavy amounts of reflection, regexing and much more which does weigh a program down.

Until PHP gets a good method of parsing annotations without needing to use PHP, instead its core C programming I would personally try and stay away from annotation overuse, or use at all.

From personal benchmarking I found that annotation use resulted in much worse performance for an application in all areas from memory to CPU to response time, significant enough that I tried to avoid them.

The code I use to grab the annotation of @virtual is small and cached enough to make it disappear from the rest of the application so it was ok i my books.

I thought about that too but it didn't work out too well in performance and also you might want virtual attributes outside of the rules of the model, like aggregation fields etc and doing that would require me looking at the rules every time to internally set attributes.

Not only that but then it requires yet another validator class unless you retro-fitted the validation functions.

defining a virtual attributes array didn't seem very clean way of doing it, plus you could suffer fro indirect accession due to it if you used virtual arrays so I didn't do that.

I saw your fix, but I don't think is the right approach because I want to save a number as a string or as an integer. I think we should manage in other ways, for example based on the rules of validation or creating an array in the model

Indeed I was thinking about rule based, the only problem I saw was that it would mean physically parsing pieces of the rules twice, it saw it as a bit of a performance problem, but I'll look into it more tomorrow.

Ah yea I left that function out because I preferred MongoDBs own way of doing it through arrays tbh, it is exactly the same it is just abstracted because of different implementations in different SQL techs for certain operators

As for gridfs: I have been thinking about how best to handle it. The YiiMongoDBSuite way of dong it wasn't the best i my opinion. I am think of making a CFile object that is sourceable and saveable to gridfs so it has abilities to take uploaded files straight from $_FILES and just slap it into MongoDB, but atm that is all theory.

I have been doing a little work with this extension and having some problems hosting on appfog. This is the appfog code to get the necessary info which I located at the top of the main.php config file...

I use zii.widgets.grid.CGridView with coloumn search. My data source is:

$orders=array(
'contact'=>array(
'email'=>'{email}'
)
);

I can determine the value of email field, but I don't know hot to determine the name because it is a sub document. If I write contact.email it is a relation, but I write contact["email"] is wrong same.

Yes, thanks for your comments. So the conclusion is that:
CGridView search field only work if i use top level fields in the collection, because the subdocument is not searchable. I have to simpify data structura. (but my business logic unfortunately a little different...) I hope something expert who understand the zii and chtml codes give some tipps later ...

I am unsure what you expect me to do with a single line and no explanation so can you tell me exactly what yiic command you was running and your script. That line relates to $cname::model(); which is perfectly valid PHP syntax and works for me.

My only guess is that you are using an old PHP version that does not allow for variable static names like $cname::

MongoYii extension is a very smart and cool tool. I have finished one hybrid e-commerce-system (with MySQL and MongoDB) yet and I'm writing a clear mongo-e-commerce system. This extension and the Mongo work very comfortable. The development process increase. I'll test in production environment as soon. Thanks Sammaye! ;)

Also you will have to setup the logroute in your cofig but also if you want execution times the YiiLog collection won't actually give you that. The only place in MongoDB (due to how queries are run) where that is stored is in the system.profile collection, you will need to query that collection from within your app and filter it as needed.

I want to setup some dbs like: db1, db2, db3 ..., over 20. Every db has many collections, about 20 or more.
they has same data format, but not relative.
Can I use multi-db in mongoyii, and how?
Thank you very much!

I'm having some troubles using a many relation. I have a model "User" which has a relation to the model "Comments".

'comments' => array('many','Comments', '_id', 'on' => 'user_id')

It's working well using a one relation or even with subdocuments but I need a separated collection for comments model. I checked documentation, tests and MongoYii Test but I can't make it work. Could you provide me an example?.

There hasn't been one made, I am quite surprised but I guess very few people use Gii in reality when posed with either making an ext for it or just having a few templates they copy around.

Even in Yii2 I don't use Gii so...yeh, if your up for making a Gii ext then I am welcome to add it but it isn't high on my list of things to do since I have mostly moved to Yii2 (adding big new features in general).

I think this will work on simple passwords. But what, if the password contain an : or @, like that (if password is m/&@:q!):http://username:m/&@:q!@localhost:27017
This results is: MongoClient::__construct(): php_network_getaddresses: getaddrinfo failed: Name or service not known
Do you know, if there is an way to mask the problematic characters??

Thank you. That works. I did not know, that I can pass the connect options by using that config-parameter in main.php

Is it possible, that mongoyii (or some model related things) need to read or write the admin db?
Because normally if you use mongodb-authentication, you like or need to use an restricted user. In my case I choose a user which only have rights for one specific database.
But by using that user I get an error like that:Failed to connect to: localhost:27017: Authentication failed on database 'admin' with username 'sam': auth fails
But I did not specify the admin-db. My application did not use that db. :-/
So why or what needs to authenticate on database 'admin' ?

i have "productcategory" sub-document for the document "Product"..
class productcategory extends EMongoModel
{

public$main;
public$other;

}
function rules()
{

returnarray(
array('main,other','required')
);

}

now i want to save the subdocument attributes in the $category_ref = array() attribute of product model...

i have saved successfully the product document, but when i set productcategory attributes to $_POST[productcategory] and assign the it to $model->$category_ref = $productcategorymodel, i get empty result for category_ref attribute.

This should be done by Yii automatically, you can call regenerateID in the session class (i.e. EMongoSession/CDbHttpSession) but you shouldn't need to call this, the main user class will handle this stuff for you.

Also, in developing e-commerce cart, how would you prefer to handle wishlist, cart and session. we have done development considering session but, wish list, cart data are inaccessible after login as sessionid changes login action..please suggest.

I have actually built a e-commerce solution using Yii2, I cannot delve too much into it since it is a real project used for a real site however; Wishlist, if like Amazon, will be per registered user so that would be databased based on the user_id of the user it was created under.

The session, I would rely on the standard Yii session, no need to extend it unless you have to consider affiliates and the tracking of partner orders and what not. In which case I would create a base controller which would be able to manipulate and understand the data in the URL/session on every page load, in case.

As for the cart you will have two carts. One will be cookie based and only on that computer and the other will be user based. If a user creates a basket when they are not logged in it will not (just like your solution) persist across computers, it doesn't need to and might actually make the user uncomfortable if it did.

The session basket will sit in the cookie if the user uses the cart without logging in, once logged in the user will have their cookie basket merged with a database version indexed on user_id.

There will always be a user cart indexed on user_id as well. This means you never rely on the session id of the user session, and so never use changing data that you must use some weird logic to anticipate.

thanks for the detailed explanation. we will go with the cookie based cart and user cart concept. And in which format are you saving the session data in YiiSession collection. i have got data something like.."SESSION|a:4:{s:3:\"sid\";s:26:\"oheriq7lldag6mvhlvr56tn8r0\";s:6:\"userid\";i:101109;s:3:\"uid\";C:7:\"MongoId\":24:{..". it is in serialized format? i am not able to unserialize it.

I store it in the cookie as a serialized array using unserialize to bring it back, however, I only store the var of the session, specifically I have a session var called basket and I serialize that var.

Sorry I cannot be more specific but I am not really allowed to be plus this is starting to get into a free lancing project now.

I configured the main with the blocks listed below but get:
include(Mongo.php): failed to open stream: No such file or directory

// We don't need to throw useless exceptions here, the MongoDB PHP Driver has its own checks and error reporting// Yii will easily and effortlessly display the errors from the PHP driver, we should only catch its exceptions if// we wanna add our own custom messages on top which we don't, the errors are quite self explanatoryif(version_compare(phpversion('mongo'), '1.3.0', '<')){
$this->_mongo = new mongo($this->server, $this->options);
$this->_mongo->connect();
if($this->setSlaveOkay)
$this->_mongo->setSlaveOkay($this->setSlaveOkay);
}else{