<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ## 新增單條數據:save( )方法 #### 1. 功能:向指定數據表中添加一條記錄 >[info] 該方法每次僅能向表中添加一條新記錄,添加多條可重復執行,不過后面要學習的saveAll()可一次性添加多條 **** #### 2. 源碼:/thinkphp/library/think/Model.php >[info] save方法是Model類中較復雜的方法之一,因為save方法身兼多職,不僅用于新增,還可以用于更新數據,這里我將用于新增部分作了簡單注釋 ~~~ /** * 保存當前數據對象,并寫入表中 * @access public * @param array $data 數據 * @param array $where 更新條件 * @param string $sequence 自增序列名 * @return integer|false */ public function save($data = [], $where = [], $sequence = null) { if (!empty($data)) { // 數據自動驗證 if (!$this->validateData($data)) { return false; } // 數據對象賦值,其實就是給$data[]初始化 foreach ($data as $key => $value) { $this->setAttr($key, $value, $data); } if (!empty($where)) { //第二個參數$where條件數組不為空 $this->isUpdate = true; //才允許更新,防止全部更新產生誤操作 } //即沒有設置條件就拒絕更新 } // 檢測字段 if (!empty($this->field)) { //如果字段數組不為空 foreach ($this->data as $key => $val) {//遍歷數據對象 if (!in_array($key, $this->field)) { //數據對象中與表字段不對應的元素 unset($this->data[$key]); //應該銷毀 } } } // 數據自動完成 $this->autoCompleteData($this->auto); // 自動寫入更新時間 if ($this->autoWriteTimestamp && $this->updateTime) { $this->setAttr($this->updateTime, null); } // 事件回調 if (false === $this->trigger('before_write', $this)) { return false; } $pk = $this->getPk(); if ($this->isUpdate) { // 自動更新 $this->autoCompleteData($this->update); // 事件回調 if (false === $this->trigger('before_update', $this)) { return false; } // 去除沒有更新的字段 $data = []; foreach ($this->data as $key => $val) { if (in_array($key, $this->change) || $this->isPk($key)) { $data[$key] = $val; } } if (!empty($this->readonly)) { // 只讀字段不允許更新 foreach ($this->readonly as $key => $field) { if (isset($data[$field])) { unset($data[$field]); } } } if (empty($where) && !empty($this->updateWhere)) { $where = $this->updateWhere; } if (is_string($pk) && isset($data[$pk])) { if (!isset($where[$pk])) { unset($where); $where[$pk] = $data[$pk]; } unset($data[$pk]); } $result = $this->db()->where($where)->update($data); // 清空change $this->change = []; // 更新回調 $this->trigger('after_update', $this); } else { // 自動寫入 $this->autoCompleteData($this->insert); // 自動寫入創建時間 if ($this->autoWriteTimestamp && $this->createTime) { $this->setAttr($this->createTime, null); } if (false === $this->trigger('before_insert', $this)) { return false; } //數據庫更新底層仍是調用Db::insert()完成 //db()獲取數據庫Query對象,這樣才能調用數據庫Query方法:insert(數據對象$data) $result = $this->db()->insert($this->data); // 獲取自動增長主鍵 if ($result && is_string($pk) && !isset($this->data[$pk])) { $insertId = $this->db()->getLastInsID($sequence); if ($insertId) { $this->data[$pk] = $insertId; } } // 標記為更新 $this->isUpdate = true; // 清空change $this->change = []; // 新增回調 $this->trigger('after_insert', $this); } // 寫入回調 $this->trigger('after_write', $this); return $result; } ~~~ >[info] 源碼簡要解析:新增忽略條件[ isUpsata(false) ],只需要用參數$data初始化模型的$data屬性,創建數據對象,就可以自動將數據添加到數據表中。 源碼中有二條關鍵語句,負責寫表操作: 1. `$result = $this->db()->insert($this->data);`:將數據插入到表中; 2. `$result = $this->db()->where($where)->update($data);`:根據條件更新表中數據; >[warning] 新增與更新操作都是:save方法,那么如何區分新增與更新呢? #### 答案就是:看有沒有設置where條件,如果無就是新增,有就是更新。 **由此可見:**最終仍是由數據庫查詢方法完成相關操作。 * * * * * #### 3. 參數與返回值 * 參數:這里有三個參數,但與新增有用的只有一個 | 序號 | 參數 | 說明 | | --- | --- | --- | | 1 | $data / Array數組 | 用來初始化模型對象的$data屬性 | * 返回值:返回受影響記錄數量,成功返回1。 * * * * * #### 4. 基本語法: * 格式1:將數據直接寫在save方法參數中 ~~~ 模型對象 -> save(數組); ~~~ * 格式2:先生成數據對象,然后用save方法直接寫入表中 ~~~ 模型對象 -> data(數組) -> save(); ~~~ >[info] 這二種語法都可以完成新增操作。但是第二種語法結構更加清晰,可讀性好,修改更加方便。第一種更加的簡潔緊湊,但可讀性不如第二個,想用哪個由你決定吧~~ * * * * * #### 5. 實例演示 * 先創建一個模型類與表綁定:Staff.php ~~~ <?php namespace app\index\model; //導入模型類 use think\model; class Staff extends model { //自定義模型類代碼 } ~~~ #### **任務:** 新增一條記錄到tp5_staff表中 >[info] 根據數據對象創建方式和save參數有無,我們用三種方法來完成這個任務 一、用data方法創建數據對象,來完成新增 * 控制器:Index.php ~~~ <?php namespace app\index\controller; //導入自定義模型類 use app\index\model\Staff; class Index { public function index(){ //1.創建數據:與表中字段對應 $data = []; $data['name'] = '周星星'; $data['sex'] = 1; $data['age'] = 39; $data['salary'] = 3500; $data['dept'] = 3; $data['hiredate'] = date('Y-m-d',time()); //2.創建數據對象 $model = (new Staff) -> data($data); //3.獲取新增操作執行前:數據對象原始數據 $data_before = $model -> getData(); //4.查看新增操作執行前的數據對象:$model echo '查看新增操作執行前的數據對象:<br />'; dump($data_before); //5.將數據對象原始數據寫入數據表中,返回影響記錄數 $affected = $model -> allowField(true) -> save(); //6.獲取新增操作執行后:數據對象原始數據 $data_after = $model -> getData(); //7.查看新增操作執行后的數據對象:$model echo '查看新增操作執行后的數據對象:<br />'; dump($data_after); //8. 獲取新增記錄的主鍵id,等價于: $model -> id $insert_ID = $data_after['id']; //6.驗證是否新增成功 echo $affected ? '新增成功!新記錄主鍵id是:'.$insert_ID : '新增失敗!'; } } ~~~ >[info] 代碼分析: 1. 其實上面源碼,部分語句是可以合并的,分開寫是為了可讀性更好; 2. `$model = (new Staff) -> data($data);` 中,` (new Staff)` 生成模型對象,`data($data);`給模型對象$data屬性初始化,完成數據對象`$model`的創建。 3. `$data_before = $model -> getData();`,此時$model已經是經過初始化了的數據對象,它的$data屬性是有值的,該語句可直接獲取到這個值($data數組); 4. `$data_after = $model -> getData();`,這時獲取的原始數據與操作執行前是不一樣的,系統自動添加了自增主鍵id字段,注意區別。 4. `$affected = $model -> allowField(true) -> save();`:將數據寫入表中,并返回影響條數,成功返回 1, 5. `allowField(true)`:過濾非數據表字段數據,僅允許與表字段對應的數組值寫入。 6. `echo $affected ? '新增成功!新記錄主鍵id是:'.$insert_ID : '新增失敗!'; `: `$affected` 作為判斷條件,如果新增成功,`$affected`為 1,失敗為 0 ,根據該值返回相應的提示信息,反饋給客戶。 * 讓我們看一下執行結果: ~~~ 查看新增操作執行前的數據對象: array(6) { ["name"] => string(9) "周星星" ["sex"] => int(1) ["age"] => int(39) ["salary"] => int(3500) ["dept"] => int(3) ["hiredate"] => string(10) "2016-11-25" } 查看新增操作執行后的數據對象: array(7) { ["name"] => string(9) "周星星" ["sex"] => int(1) ["age"] => int(39) ["salary"] => int(3500) ["dept"] => int(3) ["hiredate"] => string(10) "2016-11-25" ["id"] => string(4) "1033" } 新增成功!新記錄主鍵id是:1033 ~~~ * 對應的SQL語句: ~~~ INSERT INTO `tp5_staff` (`name` , `sex` , `age` , `salary` , `dept` , `hiredate`) VALUES ('周星星' , 1 , 39 , 3500 , 3 , '2016-11-25') ~~~ * 再返回到SQLPRO for MySQL,查看一下現在表中數據: ![](https://box.kancloud.cn/17e7a6382112653cfafbd9d91787a576_822x775.png) >[warning] 是不是覺得上面的代碼太冗長啦,做為程序員的我們,怎么能夠容忍?說實話,能學習到ThinkPHP框架開發,都不算是PHP小白了。下面跟我一道,把上面的代碼進行精簡~~ * * * * * 二、給sava方法傳參方式,完成新增操作 * 控制器:Index.php >[info] 有了上例的基礎,看懂下面的代碼,是沒有難度的 ~~~ <?php namespace app\index\controller; //導入自定義模型類 use app\index\model\Staff; class Index { public function index(){ //1.創建數據:與表中字段對應 $data = []; $data['name'] = '紫霞仙子'; $data['sex'] = 0; $data['age'] = 19; $data['salary'] = 7800; $data['dept'] = 2; $data['hiredate'] = date('Y-m-d',time()); //2.創建模型對象 $model = new Staff(); //3.將數據參數傳入save方法,將原始數據寫入表中,并返回影響記錄數 $affected = $model -> allowField(true) -> save($data); //3.驗證是否新增成功 echo $affected ? '新增成功!新記錄主鍵id是:'.$model->getData('id') : '新增失敗!'; } } ~~~ * 源碼分析:這里我們是把數據直接傳給了save方法,其實把數據參數傳給Staff類構造器也可以完成操作。為什么呢? 1. Staff類構造方法,就是給對象的$data屬性初始化,來創建數據對象的; 2. save方法,其實底層實現就是把數據對象中的$data原始數據寫入到數據表中。 >[warning] 所以說,把數組賦給類,還是save方法,本質上是完全相同 。 #### 不好意思,這里面有點點繞,把前面課程多看幾遍吧! * 現在我們再簡單修改一下控制器:Index.php >[info] 用Staff類的對象構造器創建數據對象,只需實例化傳入數據參數即可 ~~~ <?php namespace app\index\controller; //導入自定義模型類 use app\index\model\Staff; class Index { public function index(){ //1.創建數據:與表中字段對應 $data = []; $data['name'] = '紫霞仙子'; $data['sex'] = 0; $data['age'] = 19; $data['salary'] = 7800; $data['dept'] = 2; $data['hiredate'] = date('Y-m-d',time()); //2.創建模型對象 $model = new Staff($data); //3.將數據對象原始數據寫入數據表中,返回影響記錄數 $affected = $model -> allowField(true) -> save(); //3.驗證是否新增成功 echo $affected ? '新增成功!新記錄主鍵id是:'.$model->getData('id') : '新增失敗!'; } } ~~~ >[info] 其實這段代碼與上面的代碼就一點點區別: 1. 第一段代碼中,是這樣的:$data是傳入save方法的 ~~~ /2.創建模型對象 $model = new Staff(); //3.將數據參數傳入save方法,將原始數據寫入表中,并返回影響記錄數 $affected = $model -> allowField(true) -> save($data); ~~~ 2. 第二段代碼中,僅是將參數從傳給save,改為傳給Staff類 ~~~ //2.創建模型對象 $model = new Staff($data); //3.將數據對象原始數據寫入數據表中,返回影響記錄數 $affected = $model -> allowField(true) -> save(); ~~~ * 當然,運行結果是完全一致的,這里就不再貼出運行結果啦! * * * * * 三、用魔術方法創建數據對象,完成新增數據操作 >[info] 先復習一下Model類的魔術方法:__set( ) ~~~ /** * 修改器 設置數據對象的值 * @access public * @param string $name 名稱 * @param mixed $value 值 * @return void */ public function __set($name, $value) //魔術方法來動態設置數據對象$data[] { $this->setAttr($name, $value); //鍵值對方式寫入 } ~~~ **分析**:__set( )可完成模型對象的原始數據$data屬性賦值 * 控制器:Index.php ~~~ <?php namespace app\index\controller; //導入自定義模型類 use app\index\model\Staff; class Index { public function index(){ //1.創建模型對象 $model = new Staff(); //2.創建數據:與表中字段對應 $model -> name = '朱老師'; $model -> sex = 1; $model -> age = 31; $model -> salary = 4600; $model -> dept = 1; $model -> hiredate = date('Y-m-d',time()); //3.將數據對象原始數據寫入數據表中,返回影響記錄數 $affected = $model -> allowField(true) -> save(); //3.驗證是否新增成功 echo $affected ? '新增成功!新記錄主鍵id是:'.($model -> id) : '新增失敗!'; } } ~~~ >[warning] $model -> id:是調用Model類中的魔術方法__get( )方法實現的 * 返回結果: ~~~ 新增成功!新記錄主鍵id是:1038 ~~~ * 生成的SQL語句: ~~~ INSERT INTO `tp5_staff` (`name` , `sex` , `age` , `salary` , `dept` , `hiredate`) VALUES ('朱老師' , 1 , 31 , 4600 , 1 , '2016-11-25') ~~~ * SQLPRO for MySQL 控制臺查看: ![](https://box.kancloud.cn/97838a4af6474dc68281302f31bb0d04_585x406.png) * * * * * 四、save方法多次調用的問題: >[danger] 特別提示: 1. 用save方法連續新增數據時,第二次調用時,數據對象中存在有第一次調用時創建的自增主鍵的(如:id),該id值會被認為是更新條件,而將新增誤判為更新操作。 2. 所以,同一腳本中,第2次調用save方法新增時,一定要在save方法前添加isUpdata(false)方法,來規避這個問題。 * 我們還是用實例來演示: * 控制器:Index.php ~~~ <?php namespace app\index\controller; //導入自定義模型類 use app\index\model\Staff; class Index { public function index(){ //1.創建模型對象 $model = new Staff(); //2.創建數據:與表中字段對應 $model -> name = '王老師'; $model -> sex = 1; $model -> age = 20; $model -> salary = 5000; $model -> dept = 3; $model -> hiredate = date('Y-m-d',time()); //3.將數據對象原始數據寫入數據表中,返回影響記錄數 $affected = $model -> allowField(true) -> save(); //4.再創建一個要添加到表中的數據 $model -> name = '張老師'; $model -> sex = 1; $model -> age = 50; $model -> salary = 4600; $model -> dept = 2; $model -> hiredate = date('Y-m-d',time()); //5.將該數據添加到表中 $affected = $model -> allowField(true) -> save(); //3.驗證是否新增成功 echo $affected ? '新增成功!新記錄主鍵id是:'.($model -> id) : '新增失敗!'; } } ~~~ >[info] 上面的代碼看上去很簡單:添加二條數據到表中,可實際上只會添加name='張老師'的記錄,而第一條數據并未沒有添加到表中,這是為什么呢? 原因是:第一次添加完name=’王老師‘的記錄后,數據對象中自增主鍵id有了值,而這個值將會被視為更新操作的條件使用,所以第二次執行save方法時,就變成了更新操作,直接根據上一次執行返回的新增id,將name=’王老師‘的記錄,更新成了name='王老師'的信息。 * 我們再次修改一下控制器代碼:Index.php 將代碼中第2次調用save方法部分修改一下: ~~~ ······ //4.再創建一個要添加到表中的數據 $model -> name = '張老師'; $model -> sex = 1; $model -> age = 50; $model -> salary = 4600; $model -> dept = 2; $model -> hiredate = date('Y-m-d',time()); //5.將該數據添加到表中 $affected = $model -> allowField(true) //過濾非表中字段 -> setAttr('id',null) //將數據對像主鍵置空 -> isUpdate(false) //忽略主鍵 -> save(); //執行新增操作 ······ ~~~ >[info] -> setAttr('id',null) //將數據對像主鍵置空 -> isUpdate(false) //忽略主鍵 這是一步雙保險操作,有時:isUpdate(false)無效, 這是是ThinkPHP5的小bug * * * * * #### 6. 總結 >[danger] 我們通過save方法的學習,又全面復習了之前的知識,下節課要學習的saveAll方法就方便多了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看