亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Phalcon模型

chanjarster / 1644人閱讀

摘要:使用模型模型表示應(yīng)用程序信息數(shù)據(jù)以及這些數(shù)據(jù)的處理規(guī)則,主要用于管理與對(duì)應(yīng)數(shù)據(jù)表的交互規(guī)則。應(yīng)用中,是所有模型的基類。創(chuàng)建模型模型需繼承類,以大駝峰格式命名。方法在請(qǐng)求期間只調(diào)用一次,目的是為該模型的所有實(shí)例執(zhí)行初始化操作。

使用模型(Working with Models)

模型表示應(yīng)用程序信息(數(shù)據(jù))以及這些數(shù)據(jù)的處理規(guī)則,主要用于管理與對(duì)應(yīng)數(shù)據(jù)表的交互規(guī)則。大多數(shù)情況下,數(shù)據(jù)庫(kù)中的每一張表都有對(duì)應(yīng)的模型。應(yīng)用程序中的大部分業(yè)務(wù)邏輯集中在模型中。

Phalcon應(yīng)用中,PhalconMvcModel是所有模型的基類。它提供了數(shù)據(jù)庫(kù)獨(dú)立、基礎(chǔ)CRUD、高級(jí)查找、模型關(guān)聯(lián)以及其他服務(wù)。

PhalconMvcModel將調(diào)用的方法動(dòng)態(tài)轉(zhuǎn)換為相應(yīng)的數(shù)據(jù)庫(kù)操作,避免了直接使用SQL。

模型使用數(shù)據(jù)庫(kù)高級(jí)抽象層,如果想要使用更為底層的方式操作數(shù)據(jù)庫(kù),請(qǐng)參考PhalconDb組件文檔。

創(chuàng)建模型(Creating Models)

模型需繼承PhalconMvcModel類,以大駝峰格式命名。


如果使用PHP 5.4、5.5版本,建議在模型中聲明對(duì)應(yīng)數(shù)據(jù)表的所有字段,以節(jié)約內(nèi)存。

模型StoreToysRobotParts默認(rèn)映射robot_parts表,可以調(diào)用setSource()方法手動(dòng)指定映射表:

setSource("toys_robot_parts");
    }
}

模型RobotParts現(xiàn)在映射toys_robot_parts表。initialize()方法有助于在模型中創(chuàng)建自定義行為,如為模型指定映射表。

initialize()方法在請(qǐng)求期間只調(diào)用一次,目的是為該模型的所有實(shí)例執(zhí)行初始化操作。如果每次實(shí)例化模型的時(shí)候都需要進(jìn)行初始化,可以使用onConstruct()方法:


公共屬性和Setters、Getters方法(Public properties vs. Setters/Getters)

模型可以定義公共屬性,在任何獲取了模型實(shí)例的地方都可以讀寫模型的公共屬性:


另一種實(shí)現(xiàn)方式是getterssetters方法,控制哪些模型屬性可以公開(kāi)訪問(wèn)。這種方式的好處是,開(kāi)發(fā)者可以在對(duì)模型屬性進(jìn)行寫操作時(shí)執(zhí)行轉(zhuǎn)換和驗(yàn)證,這是使用公共屬性方式無(wú)法實(shí)現(xiàn)的。此外,getterssetters可以在不改動(dòng)模型和接口的前提下,應(yīng)對(duì)未來(lái)可能的改動(dòng)。如果字段名稱改變,唯一需要的改動(dòng)的地方是getterssetters中引用的模型私有屬性。

id;
    }

    public function setName($name)
    {
        // name不能太短
        if (strlen($name) < 10) {
            throw new InvalidArgumentException(
                "The name is too short"
            );
        }

        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setPrice($price)
    {
        // price不能為負(fù)
        if ($price < 0) {
            throw new InvalidArgumentException(
                "Price can"t be negative"
            );
        }

        $this->price = $price;
    }

    public function getPrice()
    {
        // 返回前,將該值轉(zhuǎn)換為double類型
        return (double) $this->price;
    }
}

雖然公共屬性在開(kāi)發(fā)中的復(fù)雜度更低,但是getterssetters可以大大提高程序的測(cè)試性、擴(kuò)展性和可維護(hù)性。開(kāi)發(fā)者可以根據(jù)需求決定哪種方式更適合他們的應(yīng)用。ORM兼容這兩種方式。

使用getterssetters時(shí),屬性名中的下劃線可能會(huì)導(dǎo)致問(wèn)題。

如果在屬性名中使用下劃線,在聲明getterssetters魔術(shù)方法時(shí),仍然要使用駝峰格式($model->getPropertyName()代替$model->getProperty_name(),$model->findByPropertyName()代替$model->findByProperty_name()等)。大多數(shù)系統(tǒng)推薦駝峰寫法,而不是下劃線寫法,所以建議按照文檔中的寫法為屬性命名??梢允褂米侄斡成?如上所述)以確保屬性正確映射到數(shù)據(jù)表中對(duì)應(yīng)字段。

理解記錄對(duì)象(Understanding Records To Objects)

模型的每一個(gè)實(shí)例代表數(shù)據(jù)表中的一條記錄,可以通過(guò)讀取模型對(duì)象屬性來(lái)訪問(wèn)記錄數(shù)據(jù)。例如,表robots有如下記錄:

mysql> select * from robots;
+----+------------+------------+------+
| id | name       | type       | year |
+----+------------+------------+------+
|  1 | Robotina   | mechanical | 1972 |
|  2 | Astro Boy  | mechanical | 1952 |
|  3 | Terminator | cyborg     | 2029 |
+----+------------+------------+------+
3 rows in set (0.00 sec)

通過(guò)主鍵查找某條記錄:

name;

一旦記錄存儲(chǔ)在內(nèi)存中,就可以修改其中的數(shù)據(jù)并保存:

name = "RoboCop";

$robot->save();

PhalconMvcModel為web應(yīng)用提供了數(shù)據(jù)庫(kù)高級(jí)抽象層,不需要使用原生SQL語(yǔ)句。

查找記錄(Finding Records)

PhalconMvcModel提供了多種查詢記錄的方法,下面例子演示如何用模型查找一條或多條記錄:

 "name",
    ]
);
foreach ($robots as $robot) {
    echo $robot->name, "
";
}

// 獲取type = "virtual"的前100條記錄,根據(jù)name排序
$robots = Robots::find(
    [
        "type = "virtual"",
        "order" => "name",
        "limit" => 100,
    ]
);
foreach ($robots as $robot) {
    echo $robot->name, "
";
}

如果要使用外部數(shù)據(jù)(如用戶輸入)或變量查找記錄,必須進(jìn)行參數(shù)綁定。

使用findFirst()方法,獲取滿足給定條件的第一條記錄:

name, "
";

// 獲取robots表中type = "mechanical"的第一條記錄
$robot = Robots::findFirst("type = "mechanical"");
echo "The first mechanical robot name is ", $robot->name, "
";

// 獲取robots表中type = "virtual"的第一條記錄,根據(jù)name排序
$robot = Robots::findFirst(
    [
        "type = "virtual"",
        "order" => "name",
    ]
);

echo "The first virtual robot name is ", $robot->name, "
";

find()方法和findFirst()方法都接受一個(gè)包含指定搜索條件的關(guān)聯(lián)數(shù)組:

 "name DESC",
        "limit" => 30,
    ]
);

$robots = Robots::find(
    [
        "conditions" => "type = ?1",
        "bind"       => [
            1 => "virtual",
        ],
    ]
);

有下列查詢選項(xiàng):

參數(shù) 說(shuō)明 示例
conditions 查詢操作的搜索條件,用于篩選符合指定條件的記錄。默認(rèn)情況下,PhalconMvcModel假定第一個(gè)參數(shù)就是搜索條件 "conditions" => "name LIKE "steve%""
columns 獲取模型中的指定字段,而不是所有字段。使用此選項(xiàng)時(shí),返回不完整對(duì)象。 "columns" => "id, name"
bind 參數(shù)綁定與conditions一起使用,通過(guò)替換占位符、轉(zhuǎn)義特殊字符從而提高安全性 "bind" => ["status" => "A", "type" => "some-time"]
bindTypes 使用參數(shù)綁定時(shí),可以使用這個(gè)參數(shù)為綁定參數(shù)定義額外的類型限制,從而提高安全性 "bindTypes" => [Column::BIND_PARAM_STR, Column::BIND_PARAM_INT]
order 用于對(duì)結(jié)果集進(jìn)行排序,使用逗號(hào)分隔多個(gè)字段 "order" => "name DESC, status"
limit 將查詢結(jié)果的數(shù)量限制在一定范圍內(nèi) "limit" => 10
offset 設(shè)定查詢結(jié)果偏移量 "offset" => 5
group 允許跨記錄收集數(shù)據(jù),并將結(jié)果集按一個(gè)或多個(gè)字段分組 "group" => "name, status"
for_update 使用此選項(xiàng),PhalconMvcModel將讀取最新的可用數(shù)據(jù),并為讀取到的每一條記錄設(shè)置獨(dú)占鎖 "for_update" => true
shared_lock 使用此選項(xiàng),PhalconMvcModel將讀取最新的可用數(shù)據(jù),并為讀取到的每一條記錄設(shè)置共享鎖 "shared_lock" => true
cache 緩存結(jié)果集,減少對(duì)數(shù)據(jù)庫(kù)的持續(xù)訪問(wèn) "cache" => ["lifetime" => 3600, "key" => "my-find-key"]
hydration 設(shè)置結(jié)果集返回模式 "hydration" => Resultset::HYDRATE_OBJECTS

除了使用參數(shù)數(shù)組,還可以使用面向?qū)ο蟮姆绞絼?chuàng)建查詢:

where("type = :type:")
    ->addWhere("year < 2000")
    ->bind(["type" => "machanical"])
    ->order("name")
    ->execute();

靜態(tài)方法query()返回一個(gè)IDE自動(dòng)完成友好的PhalconMvcModelCriteria對(duì)象。

所有查詢?cè)趦?nèi)部都以PHQL查詢的方式處理。PHQL是一種高級(jí)的、面向?qū)ο蟮念怱QL語(yǔ)言,這種語(yǔ)言提供了多種功能來(lái)執(zhí)行查詢,如join其他模型,定義分組,添加聚合等。

最后,還有一個(gè)findFirstBy()方法,該方法擴(kuò)展了findFirst()方法,它允許通過(guò)使用方法中的屬性名稱并向它傳遞一個(gè)包含要在該字段中搜索數(shù)據(jù)的參數(shù),從表中快速執(zhí)行檢索。以上面的Robots模型為例:


這里有三個(gè)屬性:$id,$name$price,假設(shè)要檢索name為"Terminator"的第一條記錄,代碼如下:

price, ".";
} else {
    echo "There were no robots found in our table with the name " . $name . ".";
}

請(qǐng)注意,我們?cè)谡{(diào)用的方法中使用了Name并傳遞了變量$name,表中name字段值為$name的記錄就是我們要查找的。

模型結(jié)果集(Model Resultsets)

findFirst()方法返回被調(diào)用類的實(shí)例(如果有結(jié)果返回),而find()方法返回PhalconMvcModelResultsetsSimple對(duì)象,該對(duì)象封裝了結(jié)果集應(yīng)有的所有功能,如遍歷,查找特定記錄,統(tǒng)計(jì)等。

這些對(duì)象比一般數(shù)組功能強(qiáng)大,PhalconMvcModelResultset一個(gè)最大的特點(diǎn)是,任何時(shí)刻,只有一條記錄保存在內(nèi)存中。這對(duì)內(nèi)存管理有極大幫助,特別是在處理大批量數(shù)據(jù)時(shí)。

name, "
";
}

// while遍歷
while ($robots->valid()) {
    $robot = $robots->current();

    echo $robot->name, "
";

    $robots->next();
}

// 結(jié)果集計(jì)數(shù)
echo count($robots);

// 另一種結(jié)果集計(jì)數(shù)方法
echo $robots->count();

// 移動(dòng)游標(biāo)到第三條記錄
$robots->seek(2);

$robot = $robots->current();

// 通過(guò)位置訪問(wèn)結(jié)果集中的記錄
$robot = $robots[5];

// 檢查指定位置是否有記錄
if (isset($robots[3])) {
    $robot = $robots[3];
}

// 獲取結(jié)果集中第一條記錄
$robot = $robots->getFirst();

// 獲取結(jié)果集中最后一條記錄
$robot = $robots->getLast();

Phalcon結(jié)果集模擬游標(biāo),可以通過(guò)訪問(wèn)其位置或內(nèi)部指針獲取任一條記錄。注意,某些數(shù)據(jù)庫(kù)系統(tǒng)不支持游標(biāo),這會(huì)導(dǎo)致查詢被反復(fù)執(zhí)行,以重置游標(biāo)到初始位置并獲取被請(qǐng)求位置的記錄。同樣的,遍歷多少次結(jié)果集,查詢便要執(zhí)行多少次。

將大量查詢結(jié)果保存在內(nèi)存中會(huì)消耗太多資源,因此,在某些情況下,以32條記錄為一塊從數(shù)據(jù)庫(kù)中獲取記錄,可以降低重復(fù)執(zhí)行請(qǐng)求的內(nèi)存消耗。

注意,結(jié)果集可以序列化后存儲(chǔ)在緩存中,PhalconCache可以實(shí)現(xiàn)該需求。但是序列化數(shù)據(jù)會(huì)導(dǎo)致PhalconMvcModel以數(shù)組形式保存從數(shù)據(jù)庫(kù)中檢索到的數(shù)據(jù),這會(huì)導(dǎo)致更多的內(nèi)存消耗。

id;
}
自定義結(jié)果集(Custom Resultsets)

有時(shí)候應(yīng)用程序需要對(duì)數(shù)據(jù)庫(kù)中檢索到的數(shù)據(jù)進(jìn)行額外處理。以前,我們只需要擴(kuò)展模型或?qū)⒐δ芊庋b在模型或trait當(dāng)中,然后返回一組經(jīng)過(guò)轉(zhuǎn)換的數(shù)據(jù)。

通過(guò)自定義結(jié)果集,不需要再如此處理。自定義結(jié)果集將封裝原本封裝在模型中并能被其他模型重用的功能,這樣可以簡(jiǎn)化代碼。如此,find()方法返回自定義對(duì)象,而不再返回PhalconMvcModelResultset對(duì)象。Phalcon允許在模型中定義getResultsetClass()方法來(lái)實(shí)現(xiàn)此操作。

首先,聲明resultset類:


模型中,在getResultsetClass()方法里設(shè)置resultset類,如下:


最后,代碼里應(yīng)包含如下內(nèi)容:

 "date between "2017-01-01" AND "2017-12-31"",
        "order"      => "date",
    ]
);

/**
 * 傳遞數(shù)據(jù)到視圖
 */
$this->view->mydata = $robots->getSomeData();
過(guò)濾結(jié)果集(Filtering Resultsets)

過(guò)濾數(shù)據(jù)最有效的方法之一是設(shè)置搜索條件,數(shù)據(jù)庫(kù)將使用表索引以更快的返回?cái)?shù)據(jù)。Phalcon允許使用PHP函數(shù)或是數(shù)據(jù)庫(kù)不支持的方式過(guò)濾數(shù)據(jù):

filter(
    function ($customer) {
        // 只返回e-mail合法的記錄
        if (filter_var($customer->email, FILTER_VALIDATE_EMAIL)) {
            return $customer;
        }
    }
);
參數(shù)綁定(Binding Parameters)

PhalconMvcModel支持參數(shù)綁定,建議使用這種方法以避免SQL注入,字符串占位符和數(shù)字占位符均被支持。參數(shù)綁定簡(jiǎn)單實(shí)現(xiàn)如下:

 [
            "name" => "Robotina",
            "type" => "maid",
        ],
    ]
);

// 數(shù)字占位符
$robots = Robots::find(
    [
        "name = ?1 AND type = ?2",
        "bind" => [
            1 => "Robotina",
            2 => "maid",
        ],
    ]
);

// 同時(shí)使用字符串占位符和數(shù)字占位符
$robots = Robots::find(
    [
        "name = :name: AND type = ?1",
        "bind" => [
            "name" => "Robotina",
            1      => "maid",
        ],
    ]
);

使用數(shù)字占位符時(shí),需要將它們定義成整數(shù)形式,即1或2。而"1"或"2"會(huì)被當(dāng)成字符串,所以占位符不能被成功替換。

字符串會(huì)自動(dòng)使用PDO轉(zhuǎn)義,該功能會(huì)考慮連接字符集,因此建議在連接參數(shù)或數(shù)據(jù)庫(kù)配置中定義正確字符集,因?yàn)殄e(cuò)誤字符集會(huì)在存儲(chǔ)和檢索數(shù)據(jù)時(shí)產(chǎn)生不良影響。

還可以設(shè)置bindTypes參數(shù),定義參數(shù)如何根據(jù)其類型綁定:

 "Robotina",
    "year" => 2008,
];

// 參數(shù)類型轉(zhuǎn)換
$types = [
    "name" => Column::BIND_PARAM_STR,
    "year" => Column::BIND_PARAM_INT,
];

// 字符串占位符
$robots = Robots::find(
    [
        "name = :name: AND year = :year:",
        "bind"      => $parameters,
        "bindTypes" => $types,
    ]
);

由于默認(rèn)的綁定類型是PhalconDbColumn::BIND_PARAM_STR,如果所有字段都是字符串類型,則沒(méi)有必要指定bindTypes參數(shù)。

如果使用數(shù)組作為綁定參數(shù),則數(shù)組必須是鍵名從0開(kāi)始的索引數(shù)組:

 "a", [1] => "b", [2] => "c"]

unset($array[1]); // $array: [[0] => "a", [2] => "c"]

// 現(xiàn)在必須重建數(shù)組索引
$array = array_values($array); // $array: [[0] => "a", [1] => "c"]

$robots = Robots::find(
    [
        "letter IN ({letter:array})",
        "bind" => [
            "letter" => $array,
        ],
    ]
);

參數(shù)綁定除了可用于所有查詢方法,如find()findFirst()外,還可用于count()sum(),average()等統(tǒng)計(jì)方法。

使用finders時(shí),會(huì)自動(dòng)使用參數(shù)綁定:

 [
            "Ultron",
        ],
    ]
);

// 隱式使用參數(shù)綁定
$robots = Robots::findByName("Ultron");
初始化已獲取記錄(Initializing / Preparing fetched records)

有時(shí)從數(shù)據(jù)庫(kù)獲取記錄之后,在數(shù)據(jù)被應(yīng)用程序使用之前,需要對(duì)數(shù)據(jù)進(jìn)行初始化??梢栽谀P椭袑?shí)現(xiàn)afterFetch()方法,實(shí)例化模型時(shí)會(huì)執(zhí)行該方法,并將數(shù)據(jù)傳遞給它:

status = join(",", $this->status);
    }

    public function afterFetch()
    {
        // 將字符串轉(zhuǎn)換成數(shù)組
        $this->status = explode(",", $this->status);
    }

    public function afterSave()
    {
        // 將字符串轉(zhuǎn)換成數(shù)組
        $this->status = explode(",", $this->status);
    }
}

如果使用getters/setters代替公共屬性,或同時(shí)使用它們,可以在字段被訪問(wèn)時(shí)初始化字段:

status);
    }
}
生成運(yùn)算(Generating Calculations)

運(yùn)算(或聚合)是數(shù)據(jù)庫(kù)中常用的輔助方法,如COUNT,SUM,MAX,MINAVG。PhalconMvcModel可以直接使用這些方法。
Count示例:

 "area",
    ]
);

// 表employees共有多少area為"Testing"的記錄
$rowcount = Employees::count(
    "area = "Testing""
);

// 按area分組統(tǒng)計(jì)表employees記錄
$group = Employees::count(
    [
        "group" => "area",
    ]
);
foreach ($group as $row) {
    echo "There are ", $row->rowcount, " in ", $row->area;
}

// 按area分組統(tǒng)計(jì)表employees記錄,并根據(jù)數(shù)目排序
$group = Employees::count(
    [
        "group" => "area",
        "order" => "rowcount",
    ]
);

// 使用參數(shù)綁定避免SQL注入
$group = Employees::count(
    [
        "type > ?0",
        "bind" => [
            $type,
        ],
    ]
);

Sum示例:

 "salary",
    ]
);

// area = "Sales"的所有employees的salaries總和
$total = Employees::sum(
    [
        "column"     => "salary",
        "conditions" => "area = "Sales"",
    ]
);

// 根據(jù)area分組統(tǒng)計(jì)salaries
$group = Employees::sum(
    [
        "column" => "salary",
        "group"  => "area",
    ]
);
foreach ($group as $row) {
    echo "The sum of salaries of the ", $row->area, " is ", $row->sumatory;
}

// 根據(jù)area分組統(tǒng)計(jì)salaries,salaries由高到低排序
$group = Employees::sum(
    [
        "column" => "salary",
        "group"  => "area",
        "order"  => "sumatory DESC",
    ]
);

// 使用參數(shù)綁定避免參數(shù)綁定
$group = Employees::sum(
    [
        "conditions" => "area > ?0",
        "bind"       => [
            $area,
        ],
    ]
);

Average示例:

 "salary",
    ]
);

// area = "Sales"的employees的平均salary
$average = Employees::average(
    [
        "column"     => "salary",
        "conditions" => "area = "Sales"",
    ]
);

// 使用參數(shù)綁定避免SQL注
$average = Employees::average(
    [
        "column"     => "age",
        "conditions" => "area > ?0",
        "bind"       => [
            $area,
        ],
    ]
);

Max / Min示例:

 "age",
    ]
);

// area = "Sales"的employees中age最大的
$age = Employees::maximum(
    [
        "column"     => "age",
        "conditions" => "area = "Sales"",
    ]
);

// 所有employees中salary最低的
$salary = Employees::minimum(
    [
        "column" => "salary",
    ]
);
創(chuàng)建 / 更新記錄(Creating / Updating Records)

PhalconMvcModel::save()方法會(huì)根據(jù)記錄是否存在于模型映射表中而創(chuàng)建 / 更新記錄,PhalconMvcModel的創(chuàng)建和更新方法會(huì)在內(nèi)部調(diào)用該方法。為此,必須在實(shí)體中正確定義主鍵,以確定是創(chuàng)建記錄還是更新記錄。

該方法會(huì)執(zhí)行相關(guān)驗(yàn)證器,虛擬外鍵和模型中定義的事件:

type = "mechanical";
$robot->name = "Astro Boy";
$robot->year = 1952;

if ($robot->save() === false) {
    echo "Umh, We can"t store robots right now: 
";

    $messages = $robot->getMessages();

    foreach ($messages as $message) {
        echo $message, "
";
    }
} else {
    echo "Great, a new robot was saved successfully!";
}

直接傳遞或者通過(guò)屬性數(shù)組傳遞的值會(huì)根據(jù)其數(shù)據(jù)類型自動(dòng)被轉(zhuǎn)義 / 過(guò)濾,所以可以傳遞一個(gè)不安全的數(shù)組而不用擔(dān)心SQL注入:

save($_POST);

毫無(wú)防護(hù)的批量傳值可能會(huì)允許攻擊者設(shè)置任意字段的值,僅在允許用戶插入 / 更新模型中所有字段的情況下使用上述功能,即使這些字段不是使用表單提交的。

可以在save()方法中設(shè)置額外參數(shù),以設(shè)置批量傳值時(shí),執(zhí)行插入 / 更新操作的白名單字段。

save(
    $_POST,
    [
        "name",
        "type",
    ]
);
創(chuàng)建 / 更新執(zhí)行結(jié)果(Create / Update with Confidence)

應(yīng)用程序高并發(fā)時(shí),創(chuàng)建記錄操作可能會(huì)變成更新操作。使用PhalconMvcModel::save()方法保存記錄時(shí),可能發(fā)生這種情況。如果想確保執(zhí)行創(chuàng)建或更新,可以使用create()update()方法替換save()

type = "mechanical";
$robot->name = "Astro Boy";
$robot->year = 1952;

// 僅創(chuàng)建記錄
if ($robot->create() === false) {
    echo "Umh, We can"t store robots right now: 
";

    $messages = $robot->getMessages();

    foreach ($messages as $message) {
        echo $message, "
";
    }
} else {
    echo "Great, a new robot was created successfully!";
}

create()方法和update()方法同樣接受一個(gè)數(shù)組作為參數(shù)。

刪除記錄(Deleting Records)

PhalconMvcModel::delete()方法允許刪除記錄,使用示例:

delete() === false) {
        echo "Sorry, we can"t delete the robot right now: 
";

        $messages = $robot->getMessages();

        foreach ($messages as $message) {
            echo $message, "
";
        }
    } else {
        echo "The robots was deleted successfully!";
    }
}

也可以通過(guò)使用foreach遍歷結(jié)果集來(lái)刪除多條記錄:

delete() === false) {
        echo "Sorry, we can"t delete the robot right now: 
";

        $messages = $robot->getMessages();

        foreach ($messages as $message) {
            echo $message, "
";
        }
    } else {
        echo "The robot was deleted successfully!";
    }
}

以下事件可以用于定義在執(zhí)行刪除操作時(shí),要執(zhí)行的自定義業(yè)務(wù)規(guī)則:

操作 事件名稱 能否終止操作 說(shuō)明
刪除 afterDelete 刪除操作后執(zhí)行
刪除 beforeDelete 刪除操作前執(zhí)行

通過(guò)上述事件,可以在模型中定義業(yè)務(wù)規(guī)則:

status === "A") {
            echo "The robot is active, it can"t be deleted";

            return false;
        }

        return true;
    }
}
Hydrations模式(Hydration Modes)

如前所述,結(jié)果集是完整對(duì)象的集合,這意味著每條返回結(jié)果都是一個(gè)對(duì)象,代表數(shù)據(jù)表中的一行。這些對(duì)象可以修改并永久保存:

year = 2000;

    $robot->save();
}

有時(shí)記錄只能以只讀模式呈現(xiàn)給用戶,這種情況下,改變記錄的展現(xiàn)方式有助于用戶處理數(shù)據(jù)。用于表示結(jié)果集中返回的對(duì)象的策略稱為"hydration mode":

setHydrateMode(
    Resultset::HYDRATE_ARRAYS
);

foreach ($robots as $robot) {
    echo $robot["year"], PHP_EOL;
}

// 返回stdClass對(duì)象
$robots->setHydrateMode(
    Resultset::HYDRATE_OBJECTS
);

foreach ($robots as $robot) {
    echo $robot->year, PHP_EOL;
}

// 返回模型實(shí)例
$robots->setHydrateMode(
    Resultset::HYDRATE_RECORDS
);

foreach ($robots as $robot) {
    echo $robot->year, PHP_EOL;
}

Hydration mode也可以作為find()方法的參數(shù)傳遞:

 Resultset::HYDRATE_ARRAYS,
    ]
);

foreach ($robots as $robot) {
    echo $robot["year"], PHP_EOL;
}
表前綴(Table prefixes)

如果希望所有表名稱都有特定前綴,并且不想在每個(gè)模型中都調(diào)用setSource()方法,則可以調(diào)用PhalconMvcModelManagersetModelprefix()方法:

setModelPrefix("wp_");
$robots = new Robots(null, null, $manager);
echo $robots->getSource(); // 返回wp_robots
自動(dòng)生成的標(biāo)識(shí)字段(Auto-generated identity columns)

某些模型有標(biāo)識(shí)字段,這些字段通常是映射表的主鍵。PhalconMvcModel能夠識(shí)別標(biāo)識(shí)字段,并在生成INSERT語(yǔ)句時(shí)忽略它,所以數(shù)據(jù)庫(kù)能夠自動(dòng)為它生成一個(gè)值。創(chuàng)建記錄之后,標(biāo)識(shí)字段的值會(huì)被注冊(cè)為數(shù)據(jù)庫(kù)為其生成的值:

save();

echo "The generated id is: ", $robot->id;

PhalconMvcModel能夠識(shí)別標(biāo)識(shí)字段,根據(jù)數(shù)據(jù)庫(kù)系統(tǒng),這些字段可能是PostgreSQL的串行列,或者是MySQL的自增列。

PostgreSQL使用序列生成自增值,默認(rèn)情況下,Phalcon試圖從序列table_field_seq中獲取生成的值,例如:robots_id_seq,如果序列具有其他名稱,則需要實(shí)現(xiàn)getSequenceName()方法:


忽略字段(Skipping Columns)

PhalconMvcModel指定創(chuàng)建 / 更新記錄時(shí)需要被忽略的字段,以便數(shù)據(jù)庫(kù)為其賦默認(rèn)值:

skipAttributes(
            [
                "year",
                "price",
            ]
        );

        // INSERT操作忽略字段
        $this->skipAttributes(
            [
                "created_at",
            ]
        );

        // UPDATE操作忽略字段
        $this->skipAttributes(
            [
                "modified_in",
            ]
        );
    }
}

這將全局忽略應(yīng)用程序中每個(gè)INSERT / UPDATE操作的這些字段。如果想在不同的INSERT / UPDATE操作時(shí)忽略不同字段,可以傳遞第二個(gè)參數(shù)(布爾值) - true。強(qiáng)制使用默認(rèn)值,實(shí)現(xiàn)方式如下:

name       = "Bender";
$robot->year       = 1999;
$robot->created_at = new RawValue("default");

$robot->create();

回調(diào)函數(shù)也可以用于為默認(rèn)值創(chuàng)建分配條件:

price > 10000) {
            $this->type = new RawValue("default");
        }
    }
}

切勿使用PhalconDbRawValue傳遞外部數(shù)據(jù)(如用戶輸入)或可變數(shù)據(jù),因?yàn)閰?shù)綁定時(shí),這些字段的值也會(huì)被忽略,所以有可能會(huì)被用來(lái)實(shí)施注入攻擊。

動(dòng)態(tài)更新(Dynamic Updates)

UPDATE語(yǔ)句默認(rèn)使用模型中定義的所有字段創(chuàng)建(全字段更新SQL),可以更改特定模型以進(jìn)行動(dòng)態(tài)更新,用需要更新的字段創(chuàng)建SQL語(yǔ)句。

useDynamicUpdate(true);
    }
}
獨(dú)立列映射(Independent Column Mapping)

ORM支持獨(dú)立的列映射,它允許開(kāi)發(fā)者在模型中定義與映射表列名稱不相同的字段名,Phalcon會(huì)識(shí)別新的字段名稱,并重命名字段以匹配數(shù)據(jù)庫(kù)中相應(yīng)的列。這是一項(xiàng)很棒的功能,當(dāng)需要重命名數(shù)據(jù)庫(kù)中的列名稱時(shí),不需要更改查詢代碼,模型中的映射列會(huì)處理好這一切。例如:

 "code",
            "the_name" => "theName",
            "the_type" => "theType",
            "the_year" => "theYear",
        ];
    }
}

然后,可以使用新的字段名:

theName, "
";

// 根據(jù)type排序
$robot = Robots::find(
    [
        "order" => "theType DESC",
    ]
);

foreach ($robots as $robot) {
    echo "Code: ", $robot->code, "
";
}

// 添加記錄
$robot = new Robots();

$robot->code    = "10101";
$robot->theName = "Bender";
$robot->theType = "Industrial";
$robot->theYear = 2999;

$robot->save();

重命名字段時(shí)需要注意以下事項(xiàng):

關(guān)系 / 驗(yàn)證器中對(duì)屬性的引用必須使用新名稱

引用實(shí)際列名稱將導(dǎo)致ORM異常

獨(dú)立列映射允許:

使用自定義約定編寫應(yīng)用程序

清除代碼中列的前后綴

改變列名稱時(shí),無(wú)需更改應(yīng)用代碼

記錄快照(Record Snapshots)

查詢時(shí)可以設(shè)置特定的模型以保持記錄快照。可以使用此功能來(lái)實(shí)現(xiàn)審計(jì),或是根據(jù)持久性查詢的數(shù)據(jù)了解哪些字段發(fā)生了改變:

keepSnapshots(true);
    }
}

當(dāng)激活此功能時(shí),應(yīng)用程序會(huì)消耗更多的內(nèi)存來(lái)與持久性查詢的原始數(shù)據(jù)保持同步。在激活此功能的模型中,可以按如下方式檢查發(fā)生改變的字段:

name = "Other name";

var_dump($robot->getChangedFields()); // ["name"]

var_dump($robot->hasChanged("name")); // true

var_dump($robot->hasChanged("type")); // false

快照會(huì)在模型創(chuàng)建 / 更新時(shí)自動(dòng)更新,使用hasUpdated()方法和getUploadedFields()方法檢查create / save / update操作后,字段是否更新。但是在afterUpdate(),afterSave()afterCreate()方法中調(diào)用getChangedFields()方法,會(huì)導(dǎo)致應(yīng)用程序出問(wèn)題。

可以禁用此功能:

 false,
    ]
);

也可以在php.ini中設(shè)置:

phalcon.orm.update_snapshot_on_save = 0

使用此功能會(huì)產(chǎn)生以下效果:

keepSnapshots(true);
    }
}

$user       = new User();
$user->name = "Test User";
$user->create();
var_dump($user->getChangedFields());
$user->login = "testuser";
var_dump($user->getChangedFields());
$user->update();
var_dump($user->getChangedFields());

在Phalcon 3.1.0及之后的版本中:

array(0) {
}
array(1) {
[0] => string(5) "login"
}
array(0) {
}

getUpdatedFields()方法將正確返回更新的字段,或如上所述,可以通過(guò)設(shè)置相關(guān)的ini值回到先前的行為。

指向不同模式(Pointing to a different schema)

如果模型映射到非默認(rèn)的模式 / 數(shù)據(jù)庫(kù),可以使用setSchema()方法重新定義它:

setSchema("toys");
    }
}
多數(shù)據(jù)庫(kù)配置(Setting multiple databases)

Phalcon應(yīng)用中,所有模型可以屬于相同的數(shù)據(jù)庫(kù)連接,或具有獨(dú)立的數(shù)據(jù)庫(kù)連接。實(shí)際上,當(dāng)PhalconMvcModel需要連接數(shù)據(jù)庫(kù)時(shí),它會(huì)在應(yīng)用程序的服務(wù)容器中請(qǐng)求數(shù)據(jù)庫(kù)服務(wù)??梢栽?b>initialize()方法中設(shè)置,覆蓋該服務(wù):

set(
    "dbMysql",
    function () {
        return new MysqlPdo(
            [
                "host"     => "localhost",
                "username" => "root",
                "password" => "secret",
                "dbname"   => "invo",
            ]
        );
    }
);

// 注冊(cè)PostgreSQL數(shù)據(jù)庫(kù)服務(wù)
$di->set(
    "dbPostgres",
    function () {
        return new PostgreSQLPdo(
            [
                "host"     => "localhost",
                "username" => "postgres",
                "password" => "",
                "dbname"   => "invo",
            ]
        );
    }
);

然后,在initialize()方法中為模型定義連接服務(wù):

setConnectionService("dbPostgres");
    }
}

Phalcon提供了更靈活的操作,可以定義只讀連接或?qū)戇B接,這對(duì)于負(fù)載均衡和主從架構(gòu)的的數(shù)據(jù)庫(kù)非常有用:

setReadConnectionService("dbSlave");

        $this->setWriteConnectionService("dbMaster");
    }
}

ORM還支持分片功能,允許根據(jù)當(dāng)前查詢條件實(shí)施分片選擇:

 0 && $id < 10000) {
                    return $this->getDI()->get("dbShard1");
                }

                if ($id > 10000) {
                    return $this->getDI()->get("dbShard2");
                }
            }
        }

        // 使用默認(rèn)分片
        return $this->getDI()->get("dbShard0");
    }
}

selectReadConnection()方法選擇合適的連接,會(huì)影響任何新執(zhí)行的查詢:


注入服務(wù)到模型(Injecting services into Models)

有時(shí)可能需要在模型中訪問(wèn)應(yīng)用程序服務(wù),以下示例介紹了如何執(zhí)行此操作:

getDI()->getFlash();

        $messages = $this->getMessages();

        // 顯示驗(yàn)證消息
        foreach ($messages as $message) {
            $flash->error($message);
        }
    }
}

創(chuàng)建或更新操作執(zhí)行失敗時(shí)會(huì)觸發(fā)notSaved事件,因此我們從DI容器中獲取flash服務(wù),然后閃存驗(yàn)證消息。這樣,我們不必在每次保存后打印消息。

禁用 / 啟用功能(Disabling / Enabling Features)

在ORM中,我們實(shí)現(xiàn)了一種機(jī)制,允許在全局范圍內(nèi)啟用 / 禁用特定功能或選項(xiàng),根據(jù)ORM的使用情況,可以禁用那些你沒(méi)有使用到的功能。如有需要,下面這些選項(xiàng)可以暫時(shí)禁用:

 false,
        "columnRenaming" => false,
    ]
);

可用選項(xiàng):

選項(xiàng) 說(shuō)明 默認(rèn)值
astCache 啟用 / 禁用模型中的回調(diào)、鉤子和事件通知 null
cacheLevel 設(shè)置ORM的緩存級(jí)別 3
castOnHydrate false
columnRenaming 啟用 / 禁用字段重命名 true
disableAssignSetters 模型中禁用setter false
enableImplicitJoins true
enableLiterals true
escapeIdentifiers true
events 啟用 / 禁用模型中的回調(diào)、鉤子和事件通知 true
exceptionOnFailedSave 啟用 / 禁用save()操作失敗時(shí)拋出異常 false
forceCasting false
ignoreUnknownColumns 啟用 / 禁用忽略模型上的未知字段 false
lateStateBinding 啟用 / 禁用PhalconMvcModel::cloneResultMap()方法的延遲綁定 false
notNullValidations ORM自動(dòng)驗(yàn)證映射表中的非空列 true
parserCache null
phqlLiterals 啟用 / 禁用PHQL解析器中的字面量 true
uniqueCacheId 3
updateSnapshotOnSave 啟用 / 禁用save()方法的更新快照 true
virtualForeignKeys 啟用 / 禁用虛擬外鍵 true

注意,給PhalconMvcModel::assign()方法(創(chuàng)建 / 更新 / 保存模型中常用到它)傳遞參數(shù)時(shí),setters始終會(huì)被調(diào)用,這會(huì)給應(yīng)用程序增加額外開(kāi)銷??梢栽趐hp.ini文件中添加配置phalcon.orm.disable_assign_setters = 1,這樣就只會(huì)簡(jiǎn)單的使用$this->property = value。

獨(dú)立組件(Stand-Along component)

下面演示以獨(dú)立組件模式使用PhalconMvcModel

set(
    "db",
    new Connection(
        [
            "dbname" => "sample.db",
        ]
    )
);

// 創(chuàng)建模型管理器
$di->set(
    "modelsManager",
    new ModelsManager()
);

// 使用內(nèi)存元數(shù)據(jù)適配器或其他
$di->set(
    "modelsMetadata",
    new MetaData()
);

// 創(chuàng)建模型
class Robots extends Model
{

}

// 使用模型
echo Robots::count();

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/28682.html

相關(guān)文章

  • Phalcon入門教程之模型

    摘要:原文發(fā)表于入門教程之模型提供了四種方式操作數(shù)據(jù)庫(kù)模型數(shù)據(jù)庫(kù)抽象層以及原生。創(chuàng)建模型模型類的命名必須符合駝峰命名法,而且須繼承自類文件路徑繼承自類。 原文發(fā)表于:Phalcon入門教程之模型 Phalcon 提供了四種方式操作Mysql數(shù)據(jù)庫(kù):模型、PHQL、數(shù)據(jù)庫(kù)抽象層以及原生SQL。不論何種方式,首先都需要在DI中注冊(cè) db 服務(wù)才能正常使用: DI注冊(cè)db服務(wù) // 文件路徑:...

    FreeZinG 評(píng)論0 收藏0
  • PHP-Phalcon框架中的數(shù)據(jù)庫(kù)操作

    摘要:本文描述了框架中數(shù)據(jù)庫(kù)操作方法,主要討論框架的組件中的操作方法。屬性方法在框架中支持屬性的擴(kuò)展查詢,在上例中,可以把條件語(yǔ)句改為同時(shí)省略查詢條件結(jié)果不變。 本文描述了PHP-Phalcon框架中數(shù)據(jù)庫(kù)操作方法,主要討論P(yáng)halcon框架的Model組件中的操作方法。更詳細(xì)的Model介紹請(qǐng)參考:官方文檔 1. 連接數(shù)據(jù)庫(kù) 在Phalcon框架中,通過(guò)在DI中注入db參數(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)庫(kù)的...

    xiaotianyi 評(píng)論0 收藏0
  • Phalcon查詢語(yǔ)言

    摘要:查詢語(yǔ)言查詢語(yǔ)言,簡(jiǎn)稱或,是一種面向?qū)ο蟮母呒?jí)語(yǔ)言,允許用標(biāo)準(zhǔn)化的編寫。該對(duì)象的每個(gè)成員都是一個(gè)包含所查詢字段的標(biāo)準(zhǔn)對(duì)象。 Phalcon查詢語(yǔ)言(Phalcon Query Language) Phalcon查詢語(yǔ)言,簡(jiǎn)稱PhalconQL或PHQL,是一種面向?qū)ο蟮母呒?jí)SQL語(yǔ)言,允許用標(biāo)準(zhǔn)化的SQL編寫。PHQL實(shí)現(xiàn)了把操作語(yǔ)句解析為RDBMS目標(biāo)語(yǔ)言的解析器(C語(yǔ)言編寫)。 為...

    Moxmi 評(píng)論0 收藏0
  • Phalcon入門教程之目錄結(jié)構(gòu)

    摘要:原文發(fā)表于入門教程之目錄結(jié)構(gòu)很多初學(xué)的朋友,對(duì)于以框架為基礎(chǔ)構(gòu)建的項(xiàng)目,應(yīng)該如何組織目錄結(jié)構(gòu)有點(diǎn)摸不著頭腦。只需要通過(guò)注冊(cè)這些目錄結(jié)構(gòu),即可正常使用。 原文發(fā)表于:Phalcon入門教程之目錄結(jié)構(gòu) 很多初學(xué)Phalcon的朋友,對(duì)于以Phalcon框架為基礎(chǔ)構(gòu)建的項(xiàng)目,應(yīng)該如何組織目錄結(jié)構(gòu)有點(diǎn)摸不著頭腦。比如多模塊的項(xiàng)目中,如何共用libs類庫(kù)和models目錄中模型類的情況,就有很...

    reclay 評(píng)論0 收藏0
  • Phalcon數(shù)據(jù)庫(kù)抽象層

    摘要:數(shù)據(jù)庫(kù)抽象層是底層組件,由它驅(qū)動(dòng)框架中的模型層。它完全由語(yǔ)言編寫,是一個(gè)獨(dú)立的數(shù)據(jù)庫(kù)高級(jí)抽象層。使用任何數(shù)據(jù)庫(kù)適配器,數(shù)據(jù)都會(huì)被自動(dòng)轉(zhuǎn)義。配合使用,可以在數(shù)據(jù)庫(kù)抽象層上提供日志記錄功能。語(yǔ)法因數(shù)據(jù)庫(kù)而異。并非所有數(shù)據(jù)庫(kù)系統(tǒng)都允許修改列或 數(shù)據(jù)庫(kù)抽象層(Database Abstraction Layer) PhalconDb是PhalconMvcModel底層組件,由它驅(qū)動(dòng)框架中的模型...

    klinson 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

chanjarster

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<