Changes and new features for CModel
#1
Posted 21 July 2011 - 10:12 AM
#2
Posted 22 July 2011 - 06:19 PM
- toArray();
- toJSON();
www.ramirezcobos.com
#3
Posted 22 July 2011 - 07:29 PM
How are you going to use .toJSON()? What is the difference between .attributes and .toArray()?
#4
Posted 23 July 2011 - 01:28 AM
How I am going to use .toJSON? To have a client representation of the model and its relations to power my client JavaScript UI Elements.
For example, instead of loading a table with my AJAX call -CGridView paging, delete or update call, I just get a JSON or array representation and then update my UI elements, so to speed up the server execution time and allow the creation of more powerful and richer elements on the client.
If you look for example a ExtJS javascript library, you find out how client elements do automatically update themselves by JSON/Array responses from the server.
Edit: I imagine a future where a proper JQuery UI client library 'plugs' seamlessly into Yii allowing programmers to decide where to place the creation of its elements, Zii for server, Jii on the client? With dialogs, sliders, grids, tabs, etc, that communicate with Yii as easy as Yii does its things on the server side.
www.ramirezcobos.com
#5
Posted 23 July 2011 - 02:00 PM
// call to external URL that returns JSON object with attributes and relation objects
$json = EHttp::getUrl('http://www.external.com/getCountry?id=2');
$model = new Country();
$model->fromJSON($json);
// now model has been initialized from JSON object
// we can now display it on the view
www.ramirezcobos.com
#6
Posted 23 July 2011 - 02:35 PM
1. Why moving JSON encoding into model?
2. How not to encode some properties?
3. How to specify if we need to encode related models or not?
#7
Posted 23 July 2011 - 03:23 PM
To have a client representation of the model and its relations to power my JavaScript UI Elements, and possibly model information server exchange
2. How not to encode some properties?
3. How to specify if we need to encode related models or not?
This one is harder to answer, maybe through a flag on the methods
return $model->toJSON(array('attributes'=>array('id'=>false),'relations'=>array('country'=>false)));
www.ramirezcobos.com
#8
Posted 23 July 2011 - 06:28 PM
#9
Posted 24 July 2011 - 03:49 AM
samdark, on 23 July 2011 - 06:28 PM, said:
Both ways are acceptable... didn't think about improving CJSON
www.ramirezcobos.com
#10
Posted 24 July 2011 - 06:26 AM
Again, about the topic. It's about CModel and CFormModel. So:
— attributes.
— errors.
— scenario.
— validators.
— events.
#11
Posted 24 July 2011 - 09:54 AM
public static function model(){
$modelClass=get_called_class();
//same old logic
}
calling myModel::someMethod will now be possible with get_called_class and __callStatic, the implementation can be something like
public static function __callStatic($method,$args){
return call_user_func_array(array(self::model(),$method),$args);
}
//usage
MyModel::setAttributes($_POST['MyModel'])->validate();
MyModel::findAll();
what do you think ?
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#12
Posted 24 July 2011 - 10:00 AM
The declaration of the model() method is no longer needed, using PHP 5.3.
However, we probably will still use something like this to do query:
Post::model()->findAll().
The main reason is that we need a place to store the query criteria so that you can modify it using scopes, etc.
We may seek for a pattern to separate the finder class and the object storage class, though. Not decided yet.
#13
Posted 24 July 2011 - 10:22 AM
Quote
I am actually refering to CModel, findAll is just an example of a very common usage of CModel + AR, my other example is still valid
CModel::setAttributes($attributes)->validate()
that refers to CModel in general, including CFormModel and AR
Quote
actually, by declaring __callStatic like I just posted, will do that, as it calls self::model() in __callStatic, returning an instance of the model
What you can do is
$model=MyFormModel::setScenario('create')->setAttributes($_POST);
if($model->validate()){
echo 'works!!';
}
1 change needed to perform the code above is that setter methods needs to return $this;
this change may cause confusion at first, but will simplify things ,9 less chars to write, 'model()->' , a lot of times
as for the others functions of CModel, like samdark wrote
Quote
— errors.
— scenario.
— validators.
— events.
I'm very happy with the way it works now
Extensions:
translate modue - module to handle translations
multiActiveRecord - db selection in models
redisCache - redis cache component
mpCpanel - interact with cpanel api
mUploadify - use uploadify uploader in your application
Gustavo Salomé Silva
#14
Posted 24 July 2011 - 01:36 PM
btw., the fact that scopes are currently applied to all model objects instead of specific one confuses developers a lot.
#15
Posted 25 July 2011 - 01:59 AM
I want automatic handling of localized formats for dates and numbers (both for displaying and parsing formatted values).
I would suggest, that for any attribute of <name> there should be an implicit attribute formatted<name>. This virtual attribute would be used as attribute name in forms:
<?php // Input for 'amount': $form->textField($model,'formattedAmount');
It would handle formatting and parsing of localized numbers and dates. The model should parse formattedAmount into amount onBeforeValidate and, in case of an error, add errors to both, amount and formattedAmount. The formats should be configurable per attribute, scenario and target language in the model. We could have a method formats() that works similar to rules() but returns a number/date format for an attribute.
For AR some of this could be automated, as we know if something is a number or a date. We could have a global default format for numbers and dates.
I was thinking about implementing a behavior for this. But for full I18N support, something like this should be supported by the core.
#16
Posted 25 July 2011 - 03:25 AM
// in some controller
$model = new LoginForm();
if (isset($_POST['LoginForm']))
{
$model->attributes = $_POST['LoginForm'];
//
// now, here all the attributes should have been converted into the correct datatype
//
}
// variant 1 - using prefixes
class LoginForm extends FormModel
{
public $strUser = '';
public $strPswd = '';
public $bAutoLogin = false;
public $iSessionTimeout = 60*60;
}
// variant 2 - using doc comments
class LoginForm extends FormModel
{
/**
* @var string
*/
public $user = '';
/**
* @var string
*/
public $pswd = '';
/**
* @var bool
*/
public $autoLogin = false;
/**
* @var integer
*/
public $sessionTimeout = 60*60;
}
#17
Posted 25 July 2011 - 05:54 AM
Formatting is a part of the view layer. Any practical example where your way is better than just calling appropriate formatter in the view?
Ben
Aren't they converted if proper rules such as boolean are used?
#18
Posted 25 July 2011 - 05:59 AM
samdark, on 25 July 2011 - 05:54 AM, said:
Formatting is a part of the view layer. Any practical example where your way is better than just calling appropriate formatter in the view?
It's also about parsing these values back into DB format. So it's a simple automatism for back and forth conversion. We also have other view related properties in the model, e.g. labels or error messages.
The only workaround for now is to write custom getters/setters for each number/date column. This is very repetitive as it's most often using the same formatting schema. Having support for this would make localization much less cumbersome when it comes to dates and numbers.
#19
Posted 25 July 2011 - 04:34 PM
samdark, on 25 July 2011 - 05:54 AM, said:
Aren't they converted if proper rules such as boolean are used?
Is this a trick question? Is there a way to make it work?
Hm... Here's what I'm trying to do and the results:
// --- Model -----------------------------
class LoginForm extends CFormModel
{
public $username='';
public $password='';
public $rememberMe=true;
public $sessionTimeout=3600;
public function rules()
{
return array(
array('username, password', 'required'),
array('rememberMe', 'boolean'),
array('sessionTimeout', 'numerical', 'integerOnly' => true),
array('password', 'authenticate'),
);
}
}
// --- in Controller -----------------------------
public function actionLogin()
{
$model=new LoginForm;
if(isset($_POST['LoginForm']))
{
CVarDumper::dump( $_POST['LoginForm'], 3, true );
// array
// (
// 'username' => 'demo'
// 'password' => 'demo'
// 'rememberMe' => '1'
// 'sessionTimeout' => '3600'
// )
// I like type safety. So ideally, conversion should happen on assignment
$model->attributes = $_POST['LoginForm'];
CVarDumper::dump( $model, 3, true );
// LoginForm#1
// (
// [username] => 'demo'
// [password] => 'demo'
// [rememberMe] => '1'
// [sessionTimeout] => '3600'
// ...
// )
// Up to now, the model still holds string data. Maybe after validation...
$model->validate();
CVarDumper::dump( $model, 3, true );
// LoginForm#1
// (
// [username] => 'demo'
// [password] => 'demo'
// [rememberMe] => '1'
// [sessionTimeout] => '3600'
// ...
// )
[...]
}
}
What I liked the data to be is (at least after validation):
// LoginForm#1 // ( // [username] => 'demo' // [password] => 'demo' // [rememberMe] => true // [sessionTimeout] => 3600 // ... // )
///////////////////
// EDIT:
Using validation rules for type conversion instead of prefixes or doc comments looks like a good idea to me.
#20
Posted 25 July 2011 - 05:57 PM
It doesn't produce true because http://www.yiiframew...rueValue-detail is 1 by default. That's to be able to write value into DB but you can change it if needed. You're right about numerical validator. It doesn't convert value into integer. Conversion via validators looks like a good idea.

Help
This topic is locked












