本文實例分析了Yii中Model(模型)的創建及使用方法。分享給大家供大家參考,具體如下:
YII 實作了兩種模型,表單模型(CFormModel類別)和Active Record模型(CAtiveRecord類別),它們都繼承自CModel類別。 CFormModel代表的資料模型是從HTML表單收集的輸入,封裝了所有邏輯(如表單的驗證和其它業務邏輯,應用到表單的域上)。它能將資料儲存在內 存中,或是在一個Active Record的幫助下,存入資料庫裡。
資料庫連接操作
在config/main.php中
'db'=>array( 'connectionString' => 'mysql:host=localhost;dbname=oss', 'emulatePrepare' => true, 'username' => 'root', 'password' => 'hahaha', 'charset' => 'utf8', //表前缀 'tablePrefix'=>"oss_" ),
開啟註釋,php要支援pdo
查看操作日誌
//显示日志信息,包括sql的查询信息 array( 'class'=>'CWebLogRoute', ),查看操作日誌
class Post extends CActiveRecord { public static function model($className=__CLASS__) { return parent::model($className); } public function tableName() { return '{{post}}'; } public function primaryKey() { return 'id'; // return array('pk1', 'pk2'); } }
lll. Record(AR) 是一種設計模式,用物件導向的方式抽象的存取數據,Yii中,每一個AR物件的實例都可以是CActiveRecord類別或它的子類別。它包裝了資料庫表 或視圖中的一行記錄,並封裝了所有的邏輯和風聞資料庫的細節,有大部分的業務邏輯,必須使用這種模型。資料庫表中一行每列欄位的值對應AR物件的一個屬 性。它將表映射到類,行映射到對象,列則映射到對象的資料。也就是說每一個Active Record類別的實例代表了資料庫中表格的一行。但一個 Active Record類別不單單是資料庫表中的欄位跟類別中屬性的映射關係。它還需要在這些資料上處理一些業務邏輯,定義了所有對資料庫的讀寫操作。
1) 宣告一個基於CActiveRecord 類別的Model
$post=new Post; $post->title='sample post'; $post->content='content for the sample post'; $post->create_time=time(); $post->save();
2) 使用父類別的方法完成資料庫操作
(1) Insert:
// find the first row satisfying the specified condition $post=Post::model()->find($condition,$params); // find the row with the specified primary key $post=Post::model()->findByPk($postID,$condition,$params); // find the row with the specified attribute values $post=Post::model()->findByAttributes($attributes,$condition,$params); // find the first row using the specified SQL statement $post=Post::model()->findBySql($sql,$params); $criteria=new CDbCriteria; $criteria->select='title'; // only select the 'title' column $criteria->condition='postID=:postID'; $criteria->params=array(':postID'=>10); $post=Post::model()->find($criteria); $post=Post::model()->find(array( 'select'=>'title', 'condition'=>'postID=:postID', 'params'=>array(':postID'=>10), )); // find all rows satisfying the specified condition $posts=Post::model()->findAll($condition,$params); // find all rows with the specified primary keys $posts=Post::model()->findAllByPk($postIDs,$condition,$params); // find all rows with the specified attribute values $posts=Post::model()->findAllByAttributes($attributes,$condition,$params); // find all rows using the specified SQL statement $posts=Post::model()->findAllBySql($sql,$params); // get the number of rows satisfying the specified condition $n=Post::model()->count($condition,$params); // get the number of rows using the specified SQL statement $n=Post::model()->countBySql($sql,$params); // check if there is at least a row satisfying the specified condition $exists=Post::model()->exists($condition,$params);
: 常用法
(1) Insert:
// update the rows matching the specified condition Post::model()->updateAll($attributes,$condition,$params); // update the rows matching the specified condition and primary key(s) Post::model()->updateByPk($pk,$attributes,$condition,$params); // update counter columns in the rows satisfying the specified conditions Post::model()->updateCounters($counters,$condition,$params);
: 常用法
(3) Update
$post=Post::model()->findByPk(10); // assuming there is a post whose ID is 10 $post->delete(); // delete the rows matching the specified condition Post::model()->deleteAll($condition,$params); // delete the rows matching the specified condition and primary key(s) Post::model()->deleteByPk($pk,$condition,$params);
(4) Delete
$model=Post::model(); $transaction=$model->dbConnection->beginTransaction(); try { // find and save are two steps which may be intervened by another request // we therefore use a transaction to ensure consistency and integrity $post=$model->findByPk(10); $post->title='new post title'; $post->save(); $transaction->commit(); } catch(Exception $e) { $transaction->rollBack(); }
(5) 使用事務
class LoginForm extends CFormModel { public $username; public $password; public $rememberMe=false; }使用者輸入哪些數據,以及應該符合什麼規則。一個模型類別可以用來記錄這些信息,模型是保持使用者輸入並進行驗證的核心根據我們如何使用使用者的輸入,我們可以建立兩種類型的模型。如果使用者輸入的資料被收集,使用,然後丟棄,我們將建立表單模型(form model); 如果使用者輸入的資料被儲存到資料庫中,我們則會使用 active record 。這兩種模型都繼承了他們相同的基底類別CModel中定義的表單的通用接 口。 1) 模型類別的定義下面的範例中,我們建立了一個LoginForm模型,用來收集使用者在登陸頁面的輸入。由於登陸資訊僅用於用戶驗證,並不需要保存,因此我們用form model創建
class LoginForm extends CFormModel { public $username; public $password; public $rememberMe=false; private $_identity; public function rules() { return array( array('username, password','required'), array('rememberMe', 'boolean'), array('password', 'authenticate'), ); } public function authenticate($attribute,$params) { if(!$this->hasErrors()) // we only want to authenticate when no input errors { $this->_identity=new UserIdentity($this->username,$this->password); if(!$this->_identity->authenticate()) $this->addError('password','Incorrect password.'); } } }LoginForm一共聲明了三個屬性(attributes),$username、$password、$rememberMe用來記錄用戶輸入的使用者名稱、密碼、以及是否記住登陸的選項。因為$rememberMe有了預設值false,所以顯示表單時對應的選框是沒有勾選的。 提示:我們使用名稱"attributes",而不是"properties",來把他們和正常的屬性(properties)進行區分。 2) 聲明驗證規則一旦把使用者提交的資料填入模型,在使用之前,我們要檢查他們是否合法。這是透過對輸入進行一組規則驗證來實現的。我們在rulers()方法中透過配置一個陣列來定義驗證規則
public function ValidatorName($attribute,$params) { ... }上面的程式碼指明了使用者名稱和密碼是必須得,密碼需要被驗證,rememberMe必須是布林型rules()中傳回的每條規則,必須按照以下格式array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...附加選項(additional options))AttributeList 是一個被逗號分隔的需要驗證的屬性名列表。 Validator 指出了需要做怎樣的驗證。可選的on 參數指出了該規則應用的場景列表,(additional options)是對應的name-value,用於初始對應驗證器的相關屬性在一個規則中指定Validator有三種方法,首先Validator可以使該類別的一個方法,例如上面例子中的authenticate。此Validator方法必須依照如下的格式宣告
// username is required array('username', 'required'), // username must be between 3 and 12 characters array('username', 'length', 'min'=>3, 'max'=>12), // when in register scenario, password must match password2 array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'), // when in login scenario, password must be authenticated array('password', 'authenticate', 'on'=>'login'),其次 Validator 可以使驗證器的類別名,當規則適用時,一個驗證器類別的實例會被建立並進行實際的驗證。規則裡的附加屬性,用於初始實例的相關屬性。驗證器類別必須繼承於CValidator
第三、Validator 可以使验证器类预先定义的别名。在上面的例子中,“required”便是CRequiredValidator的别名,用来验证属性不能为空。下面是预定义的验证器类别名的列表
? boolean:CBooleanValidator的别名,验证属性的值是否是CBooleanValidator::trueValue 或者 CBooleanValidator::falseValue
? captcha:CCaptchaValidator的别名,验证属性的值是否和CAPTCHA中显示的验证码的值相等
? compare:CCompareValidator的别名,验证属性的值是否等于另一个属性或者一个常量
? email:CEmailValidator的别名,验证属性的值是否是个合法的email地址
? default:CDefaultValueValidator的别名,为属性指派一个默认值
? exist:CExistValidator的别名,验证属性的值是否能在表的列里面找到
? file: CFileValidator 的别名, 验证属性是否包含上传文件的名字
? filter:CFilterValidator的别名,使用一个过滤器转换属性的形式
? in: CRangeValidator 的别名, 验证属性值是否在一个预订的值列表里面
? length: CStringValidator 的别名, 确保了属性值的长度在指定的范围内.
? match: CRegularExpressionValidator 的别名, 验证属性是否匹配一个正则表达式.
? numerical: CNumberValidator 的别名, 验证属性是否是一个有效的数字.
? required: CRequiredValidator 的别名, 验证属性的值是否为空.
? type: CTypeValidator 的别名, 验证属性是否是指定的数据类型.
? unique: CUniqueValidator 的别名, 验证属性在数据表字段中是否是唯一的.
? url: CUrlValidator 的别名, 验证属性是否是一个有效的URL路径.
下面我们给出一些使用预定义验证器的例子。
// username is required array('username', 'required'), // username must be between 3 and 12 characters array('username', 'length', 'min'=>3, 'max'=>12), // when in register scenario, password must match password2 array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'), // when in login scenario, password must be authenticated array('password', 'authenticate', 'on'=>'login'),
3) 安全属性的设置
当一个模型创建之后,我们往往需要根据用户的输入,为它填充属性。这可以方便的通过下面批量赋值的方式来实现
$model=new LoginForm; if(isset($_POST['LoginForm'])) $model->attributes=$_POST['LoginForm'];
最后那条语句便是批量赋值,把$_POST['LoginForm']中每个属性都赋值到对应的模型属性中,它等价于下面的语句
foreach($_POST['LoginForm'] as $name=>$value) { if($name is a safe attribute) $model->$name=$value; }
声明属性是否是安全属性是个至关重要的工作。例如,如果我把把数据表的主键暴露为安全属性,那么便可以通过修改主键的值,来管理本没有权限管理的数据,进行攻击。
4) 1.1版中的安全属性
在1.1版中,如果属性在适用的规则中指定了验证器,则认为是安全的。例如
array('username, password', 'required', 'on'=>'login, register'), array('email', 'required', 'on'=>'register'),
上面的代码中用户名和密码属性在login的场景下不允许为空。用户名、密码邮箱在register的场景下不允许为空。因此如果在login的场景下 进 行批量赋值,仅仅用户名和密码会被赋值,因为login场景下验证规则里仅出现了这两个属性,但是如果是在register场景下,那么这三个属性都 会被 赋值。
// in login scenario $model=new User('login'); if(isset($_POST['User'])) $model->attributes=$_POST['User']; // in register scenario $model=new User('register'); if(isset($_POST['User'])) $model->attributes=$_POST['User'];
那么为什么我们使用如此的策略来决定一个属性是否是安全属性呢?因为一个属性,已经有了一个或者多个对个进行校验的规则,那么我还需要担心吗?
需要记住的是,验证器是用来检测用户输入的数据,而不是我们用代码产生的数据(例如 时间戳,自增的主键等)。因此不要给那些不需要用户输入的属性添加验证器。
有时候我们想声明一些属性为安全属性,但是又不必给指定一个验证规则。例如文章的正文属性,我们可以允许用户的任何输入。为了实现这个目标,我们可以用safe规则。
array('content', 'safe')
对应的也有一个unsafe规则,来指定哪些属性是不安全的
array('permission', 'unsafe')
unsafe并不常用,对你以前定义的安全属性来说,这是个例外
5) 获取验证错误
当验证结束后,任何可能的错误都存储在模型的实例中。我们可以通过调用CModel::getErrors() 和 CModel::getError()重新获取到。这两个方法的区别在于,第一个可以返回指定模型属性的所有错误,而第二个方法只返回了第一条错误。
6) 属性标签
设计表单的时候,我们需要为用户的输入框显示一个标签,来提示用户输入。尽管我们可以再form中写死,但是如果我们在相应的模型中指定的话会更加方便和灵活
默认情况下,CModel 会简单的返回属性的名字作为标签。这可以通过重写attributeLabels() 方法来自定义。在接下来章节中我们将看到,在模型中指定标签可以让我们更快更强大的创建一个form表单
希望本文所述对大家基于yii框架的php程序设计有所帮助。
更多Yii中Model(模型)的创建及使用方法相关文章请关注PHP中文网!