Lithium: How Document->save() or Record->save() works - lithium

In lithium, document and record classes, or their superclasses/interfaces, have no save() method. Yet lithium's method for saving the record is as follows:
$record = Model::create()
$record->save()
I am not certain how this works, since record does not have save method (only Model has).

Document and Record extend from a base Entity class. The Entity class has a __call() magic method. See the api doc for Entity::__call over here: http://li3.me/docs/lithium/data/Entity::__call() That method obtains an instance of the Model class associated with the Entity and then calls the method passing the entity object in as the first argument. The Adding Functions To Models section of the Lithium manual also contains additional info related to this.

Related

Setting an entity's ID manually

I'm facing a little issue that I cannot understand here.
Using this chunk of code:
IEntity myEntity = controller.entityFactory.createEntityInstance(MyEntity.class)
myEntity.straightSetProperty(IEntity.ID, "anId")
myEntity.setReferenceProperty(someReference)
I get an "UOW bad usage" error
BAD SESSION USAGE You are modifying an entity ()[MyEntity] that has not been previously merged in the session.
You should 1st merge your entities in the session by using the backendController.merge(...) method.
The property being modified is [referenceProperty].
But when switching the lines it's okay
IEntity myEntity = controller.entityFactory.createEntityInstance(MyEntity.class)
myEntity.setReferenceProperty(someReference)
myEntity.straightSetProperty(IEntity.ID, "anId")
Any idea why i'm facing this issue ?
Jspresso computes the hashcode of an entity based on its id. this hashcode is indirectly used by Jspresso internally to perform some controls and other operations by using it in Hash[Map|Set].
That's why it's mandatory that :
The id is assigned as soon as the entity instance is created and before any setter or operation is performed on the entity.
The id does not change during the lifetime of the entity.
When you call :
IEntity myEntity = entityFactory.createEntityInstance(MyEntity.class)
a generated id is assigned to the entity.
In scenario 1, you first change the id (which breaks the hashcode), and call a setter. Jspresso thinks this entity has not been correctly registered because it cannot retrieve its id from the internal, hashcode based, storage.
In scenario 2, same violation but you call the setter before changing the id. But I suppose that if you call another setter afterwards, it will fail the same way.
The solution is to use the other signature of the entityFactory create method that allows to pass an id as parameter, e.g.
IEntity myEntity = entityFactory.createEntityInstance(MyEntity.class, "anId")
myEntity.setReferenceProperty(someReference)
which will immediately assign your id to the entity and perform all necessary operations afterwards.

Is there any good reason to use 'id' as return type or parameter type in public API?

I am learning from Stanford's CS193P course. In the class, Paul has a demo project, "Calculator", where he uses id as the type of a property. He intends to not use a specific class, because he does not want to create a new class and then he does not need to write documentation, and even when it is updated, he does not need to redesign the class. id can solve all these problems.
Is this a really a good way? id is the return type of the property, and used as the parameter type of another method. How does the caller know what id is, and how to provide the correct object? By reading code comments?
In general, is there any good reason to use id as a return type or parameter type in public API? (Except init and factory method, though even for those, instancetype is recommended.)
If your method returns a class that is a member of a class cluster, you should return id.
If you're returning an object whose class is opaque, isn't declared in a public header, you should return id. (Cocoa occasionally uses such objects as tokens or context data.)
Container classes should always accept and return their constituents as ids.

$model->validate() returns true without any attribute assignments?

I have a model with many attributes, I want to validate before saving it. So at some I would have only model initialization but no attribute assignments
$model=new patient(); $model->validate();
yet it returns true, I have many attributes set to required. I don't understand how does this happen?
Is there a way to validate a model before saving it even though no attributes are assigned to the model?
Your have validation rules but You may Miss the scenario's on validate .
Check the validators on your current object model by this
print_r($model->validatorList);
refer this link
You can validate a model at any time once it is created.
Let's look at the sequence of events :-
You have created a model class :
class User extends CActiveRecord
{
...
}
This creates a template for the patient class, which inherits from CActiveRecord, which means it has inherited functions available to it. So, while your class files does not the activate() function, it inherits it from the CActiveRecord class.
Now you create an instance of the class
$patient1 = new patient;
This means there is now some space in memory that exists for patient1. It has values. Some may be empty and some not (for example, they may have a default value).
So, at any time, you could
$model->validate();
This would change the model to include the error messages. To get the errors that have been raise, use
$allErrors = $model->getErrors()
print_r($all_errors); // This will show you the structure.
To print the errors in a neat way, use
echo CHtml::errorSummary($model);

Yii CActiveRecord with Column Named "attributes"

I used the CRUD generator from a legacy database. When searching for a column value I get the following error:
htmlspecialchars() expects parameter 1 to be string, array given (/usr/local/share/yii/framework/web/helpers/CHtml.php:103)
The problem is that the model has an existing column named "attributes" which is creating a conflict. I removed the entry from the _search.php and commented out all instances in the model hoping to at least get it working but no luck. Any suggestions would be appreciated.
Thanks.
Every CActiveRecord instance (or CModel instance for that matter) has a getter/setter named attributes with which all the attributes can be set. This leads to a conflict because the generated crud code uses the attributes attribute expecting it works as described before.
The controller does something like:
$model->attributes=$_POST['ModelClassName'];
// or
$model->attributes=$_GET['ModelClassName'];
This is meant to set al the (safe) attributes of the model at once. Instead this overwrites the database attribute attributes of your legacy DB model.
This in turn leads to the error you describe, because $_GET['ModelClassName'] and $_POST['ModelClassName'] typically contain arrays of data.
I guess the easiest fix would be to directly call the setter function for the "normal" attributes behavior which would lead to replacing the lines mentioned above with something like the following:
// in the controller
$model->setAttributes($_POST['ModelClassName']);
// and
$model->setAttributes($_GET['ModelClassName']);
I think rest of the generated CRUD code (the views) could and should be left untouched to make it work.
If you want to know how and why this works, it's best to do some research into the __get and __set magic functions and how they're used in the yii framework.

Automatically update Entity instance from class MVC 3

I've got a class that closely resembles one of my entities (I use the class for JSON de/serialization because the entity fails conversion to JSON, one of the known gotchyas of JSON + MVC).
Once I deserilize a JSON string into my object, is there a way to automatically update the associated Entity model instance. The property names are the same.
e.g.
'myDeserialized is the deserialized JSON object coming over the wire
Dim entityInstance As DLL.Person = db.getPersonById(myDeserialized.id)
myDeserialized.update(entityInstance)
Where this just goes through and takes all the properties in myDeserialized and updates the same named property in entityInstance?
Or is it possible to just iterate over a key-value pair of all the properties in an object/entity?
I'm looking for something like TryUpdateModel(), but that only works with forms, right? I don't want to tie my data to a form, that's all.
Thanks!
I don't know what type and version of EF you use, but there are very powerful functions for iterating on the entities properties. Which mean you can easily make your update function on the entity or its baseclass' partial (entityInstance.Update(myDesrialized)).
If you use EntityObject, then you can get an ObjectStateEntry for your entities and via this class you can very easily achieve this.
Please let us know what version and type of EF you use (POCO?)