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

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);

Related

OOP - When to Use Properties vs When to Use Return Values

I am designing a process that should be run daily at work, and I've written a class to do the work. It looks something like this:
class LeadReport {
public $posts = array();
public $fields = array();
protected _getPost() {
// get posts of a certain type
// set them to the property $this->posts
}
protected _getFields() {
// use $this->posts to get fields
// set $this->fields
}
protected _writeCsv() {
// use the properties to write a csv
}
protected _sendMail() {
// attach a csv and send it
}
public function main() {
$this->out('Lead Report');
$this->out("Getting Yesterday's Posts...");
$this->_getPosts();
$this->out("Done.");
$this->out("Next, Parsing the Fields...");
$this->_getFields();
$this->out("Done.");
$this->out("Next, Writing the CSVs...");
$this->_writeCsv();
$this->out("Done.");
$this->out("Finally, Sending Mail");
$this->_sendMail();
$this->out('Bye!');
}
}
After showing this code to one of my colleagues, he commented that the _get() methods should have return values, and that the _write() and _sendMail() methods should use those values as parameters.
So, two questions:
1) Which is "correct" in this case (properties or return values)?
2) Is there a general rule or principle that governs when to use properties over when to use return values in object oriented programming?
I think maybe the source of your question comes from the fact that you are not entirely convinced that using properties is better than having public fields. For example here, common practice says that should not have posts and fields as public. You should use the getField method or a Field protected property to regulate access to those fields. Having a protected getField and a public fields doesn't really make sense.
In this case your colleague may be pointing at two things. The fact that you need to use Properties and not public fields and also the fact that it is probably better to pass the post into the method and not have the method access a property if you can. That way you don't have to set a property before calling the method. Think of it as a way of documenting what the method needs for it to operate. In this way another developer doesn't need to know which properties need to be set for the method to work. Everything the method needs should be passed in.
Regarding why we need properties in the first place? why shouldn't you use public fields. Isn't it more convenient? It sure is. The reason we use properties and not public fields is that just like most other concepts in OOP, you want your object to hide its details from the outside world and just project well defined interfaces of its state. Why? Ultimately to hide implementation details and keep internal change to ripple out(Encapsulation). Also, accessing properties has the added benefit of debugging. You can simply set a breakpoint in a property to see when a variable is changed or simply do a check if the variable is of certain value. Instead of littering your code with said check all over the place. There are many more goodies that come with this, returning readonly values, access control, etc.
To sum up, fields are though of as internal state. Properties(actual get/set methods) are though of as methods that interact with internal state. Having an outside object interact with interfaces is smiley face. Having outside class interact with internal state directly is frowny face.

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.

Why is 'New' being called for each record retrieved when using the entity Framework

I have been seeing some odd behaviour in an entity that I have for which I created a partial class to override the ToSting Method and provide some basic property setting when a new instance of that entity is created (for example I might set an order date to 'Now') in a constructor.
This odd behaviour led me to look closely at the partial class and I was surprised to see that even when a set of pre existing records was being retrieved the constructor was being called for each retrieved record.
below is a very simple example of what I might have:
Partial Public Class Product
Public Sub New()
CostPrice = 0.0
ListPrice = 0.0
End Sub
Public Overrides Function ToString() As String
Return ProductDescription
End Function
End Class
I have two questions that arise from this:
1) is this normal behaviour in the Entity Framework if you add a partial class to which you add a constructor?
2) if not then I must assume that I have done something wrong, so what would be the correct way to
override the constructor to do things similar to the example I mentioned above?
Thanks for any insights that you can give me.
This is using EF 5.0 in a vb project
think to the sequence of events leading to the retrieval of an entity from the database. Basically it should be something like:
query the database
for each row of the query result give an entity
The giving is then as follow for each retrieved row:
create a new instance of the retrieved entity
populate this new instance with the value of the row
Well with each instance creation, the constructor is called.
I think you are mixing:
instance initialization where you "allocate" the object, and
business initialization where you enforce business logic
both may be done, at least partially, in the constructor.
new is always called when a class is first instantiated and if you do not explicitly declare a constructor then a default constructor will be created by the compiler.
Unless the class is static, classes without constructors are given a public default constructor by the C# compiler in order to enable class instantiation.
When defining POCO classes for Entity Framework the class must have a default constructor and EF will always call this default constructor whether you have explicitly defined it or the compiler did it for you.
If for any reason you have need to pass anything into the class when it is instantiated you can use the ObjectContext.ObjectMaterialized event.

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

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.

difference between ActiveRecord and model() in yii?

What is the relation or difference between ActiveRecord and model in YII ?
i was trying to log is_object(CActiveRecord::model('Project')); and was expecting false but it returned true;
Since the logging indicated that it's an object, i thought it is representing a row in the table, but i couldn't find any attributes that represent the coloumns.
Also http://www.yiiframework.com/doc/api/1.1/CActiveRecord#model-detail states that it's returning an instance of CActiveRecord class , but i could not find any values of the table row in that object.
The answer is in your documentation link, model() is a class level method, and it:
Returns the static model of the specified AR class. The model returned is a static instance of the AR class. It is provided for invoking class-level methods (something similar to static class methods.)
Let's say you do: $model=CActiveRecord::model('Project'); , then using that $model you can call all the class level methods of CActiveRecord, like:
$allModels = $model->findAll(); // will give you all the models of Project
$someModel = $model->findByPk('pkValue'); // will give you the row with primary key value = pkValue
$model->deleteAll(); // will delete all the records of Project
// and so on
Edit:
Also this post in the forum says: (Difference between class level and static methods)
Class Level Methods are effectively Static Methods BUT with the benefit of being able to use inheritance. That is, you can override the operation of a Class Level Method in a subclass, whereas if you used a static method you would not be able to override it.
....
So, in general, you should use class level methods, not static methods, as it gives you the benefit of inheritance although it might feel a little weird. Then you call them using $class::model()->method().
ActiveRecord is a pattern. A pattern to store data in relational database. Model, in MVC pattern, is the part of data. So, Yii is an MVC framework that implement ActiveRecord for model.
model method is this
public static function model($className=__CLASS__)
{
if(isset(self::$_models[$className]))
return self::$_models[$className];
else
{
$model=self::$_models[$className]=new $className(null);
$model->_md=new CActiveRecordMetaData($model);
$model->attachBehaviors($model->behaviors());
return $model;
}
}
As you can see return an object