国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

干貨:構(gòu)建復(fù)雜的 Eloquent 搜索過濾

Shisui / 1299人閱讀

摘要:最近,我需要在開發(fā)的事件管理系統(tǒng)中實(shí)現(xiàn)搜索功能。今天,我會(huì)介紹整個(gè)過程以及如何構(gòu)建靈活且可擴(kuò)展的搜索系統(tǒng)。這將是個(gè)挑戰(zhàn)前端的條件過濾的截圖。像剛剛的情況下搜索用戶時(shí)加上一個(gè)過濾器再返回搜索結(jié)果。

最近,我需要在開發(fā)的事件管理系統(tǒng)中實(shí)現(xiàn)搜索功能。 一開始只是簡(jiǎn)單的幾個(gè)選項(xiàng) (通過名稱,郵箱等搜索),到后面參數(shù)變得越來越多。

今天,我會(huì)介紹整個(gè)過程以及如何構(gòu)建靈活且可擴(kuò)展的搜索系統(tǒng)。如果你想查看代碼,請(qǐng)?jiān)L問?Git 倉(cāng)庫(kù)?。

我們將創(chuàng)造什么

我們公司需要一種跟蹤我們與世界各地客戶舉辦的各種活動(dòng)和會(huì)議的方式。我們目前的唯一方法是讓每位員工在 Outlook 日程表上存儲(chǔ)會(huì)議的詳細(xì)信息。可拓展性較差!

我們需要公司的每個(gè)人都可以訪問,來查看我們客戶的被邀請(qǐng)的詳細(xì)信息以及他們的RSVP(國(guó)際縮用語(yǔ):請(qǐng)回復(fù))狀態(tài)。

這樣,我們可以通過上次與他們互動(dòng)的數(shù)據(jù)來確定哪些用戶可以邀請(qǐng)來參加未來的活動(dòng)。

使用高級(jí)搜索過濾器查找的截圖

查找用戶

常用過濾用戶的方法:

通過姓名,電子郵件,位置

通過用戶工作的公司

被邀請(qǐng)參加特定活動(dòng)的用戶

參加過特定活動(dòng)的用戶

邀請(qǐng)及已參加活動(dòng)的用戶

邀請(qǐng)但尚未回復(fù)的用戶

答應(yīng)參加但未出席的用戶

分配給銷售經(jīng)理的用戶

雖然這個(gè)列表不算完整,但可以讓我們知道需要多少個(gè)過濾器。這將是個(gè)挑戰(zhàn)!

前端的條件過濾的截圖。

模型及模型關(guān)聯(lián)

在這個(gè)例子中我們回用到很多模型:

User?---? 代表被邀請(qǐng)參加活動(dòng)的用戶。一個(gè)用戶可以參加很多活動(dòng)。

Event?--- 代表我公司舉辦的活動(dòng)。活動(dòng)可以有多個(gè)。

Rsvp?---? 代表用戶對(duì)活動(dòng)邀請(qǐng)的回復(fù)。一個(gè)用戶對(duì)一個(gè)活動(dòng)的回復(fù)是一對(duì)一的。

Manager?---? 一個(gè)用戶可以對(duì)應(yīng)多個(gè)我公司的銷售經(jīng)理.

搜索的需求

在開始代碼之前,我想先把搜索的需求明確一下。也就是說我要很清楚地知道我要對(duì)哪些數(shù)據(jù)做搜索功能。

下面就是一個(gè)例子:

{
    "name": "Billy",
    "company": "Google",
    "city": "London",
    "event": "key-note-presentation-new-york-05-2016",
    "responded": true,
    "response": "I will be attending",
    "managers": [
        "Tom Jones",
        "Joe Bloggs"
    ],
}

總結(jié)一下上面數(shù)據(jù)想表達(dá)的搜索的條件:

客人的名字是 "Billy",來自 "Google" 公司,目前居住在 "London",已經(jīng)對(duì) "key-note-presentation-new-york-05--2016" 的活動(dòng)邀請(qǐng)做出了回復(fù),并且回復(fù)的內(nèi)容是 "I will be attending",負(fù)責(zé)跟進(jìn)這位客人的銷售經(jīng)理是 "Tom Jones" 或者 "Joe Bloggs"。
開始 --- 最佳實(shí)踐

我是一個(gè)堅(jiān)定不移的極簡(jiǎn)主義者,我堅(jiān)信少即是多。下面就讓我們以最簡(jiǎn)單的方式探索出解決這個(gè)需求的最佳實(shí)踐。

首先,在 ?routes.php 文件中添加如下代碼:

Route::post("/search", "SearchController@filter");

接下來,創(chuàng)建 ?SearchController.

php artisan make:controller SearchController

添加前面路由中明確的?filter()? 方法:


由于我們需要在 filter 方法中處理請(qǐng)求提交的數(shù)據(jù),所以我把 Request 類做了依賴注入。Laravel 的服務(wù)容器 會(huì)解析這個(gè)依賴,我們可以在方法中直接使用 Request 的實(shí)例,也就是 $request。User 類也是同樣道理,我們需要從中檢索一些數(shù)據(jù)。

這個(gè)搜索需求有一點(diǎn)比較麻煩的是,每個(gè)參數(shù)都是可選的。所以我們要先寫一系列的條件語(yǔ)句來判斷每個(gè)參數(shù)是否存在:

這是我初步寫出來的代碼:

public function filter(Request $request, User $user)
{
    // 根據(jù)姓名查找用戶
    if ($request->has("name")) {
        return $user->where("name", $request->input("name"))->get();
    }

    // 根據(jù)公司名查找用戶
    if ($request->has("company")) {
        return $user->where("company", $request->input("company"))
            ->get();
    }

    // 根據(jù)城市查找用戶
    if ($request->has("city")) {
        return $user->where("city", $request->input("city"))->get();
    }

    // 繼續(xù)根據(jù)其他條件查找

    // 再無(wú)其他條件,
    // 返回所有符合條件的用戶。
    // 在實(shí)際項(xiàng)目中需要做分頁(yè)處理。
    return User::all();
}

很明顯,上面的代碼邏輯是錯(cuò)誤的。

首先,它只會(huì)根據(jù)一個(gè)條件去檢索用戶表,然后就返回了。所以,通過上面的代碼邏輯,我們根本無(wú)法獲得姓名為 "Billy", 而且住在 "London" 的用戶。

實(shí)現(xiàn)這種目的的一種方式是嵌套條件:

// 根據(jù)用戶名搜索用戶
if ($request->has("name")) {
    // 是否還提供了 "city" 搜索參數(shù)
    if ($request->has("city")) {
        // 基于用戶名及城市搜索用戶
        return $user->where("name", $request->input("name"))
            ->where("city", $request->input("city"))
            ->get();
    }
    return $user->where("name", $request->input("name"))->get();
}

我確信你可以看到這在兩個(gè)或者三個(gè)參數(shù)的時(shí)候起作用,但是一旦我們添加更多選項(xiàng),這將會(huì)難以管理。

改進(jìn)我們的搜索 api

所以我們?nèi)绾巫屵@個(gè)生效,而同時(shí)不會(huì)因?yàn)榍短讞l件而變得瘋狂?

我們可以使用 User 模型繼續(xù)重構(gòu),來使用?builder?而不是直接返回模型。

public function filter(Request $request, User $user)
{
    $user = $user->newQuery();

    // 根據(jù)用戶名搜索用戶
    if ($request->has("name")) {
        $user->where("name", $request->input("name"));
    }

    // 根據(jù)用戶公司信息搜索用戶
    if ($request->has("company")) {
        $user->where("company", $request->input("company"));
    }

    // 根據(jù)用戶城市信息搜索用戶
    if ($request->has("city")) {
        $user->where("city", $request->input("city"));
    }

    // 繼續(xù)執(zhí)行其他過濾

    // 獲得并返回結(jié)果
    return $user->get();
}

好多了!我們現(xiàn)在可以將每個(gè)搜索參數(shù)做為修飾符添加到從 ?$user->newQuery() 返回的查詢實(shí)例中。

我們現(xiàn)在可以根據(jù)所有的參數(shù)來做搜索了, 再多參數(shù)都不怕.

一起來實(shí)踐吧:

$user = $user->newQuery();

// 根據(jù)姓名查找用戶
if ($request->has("name")) {
    $user->where("name", $request->input("name"));
}

// 根據(jù)公司名查找用戶
if ($request->has("company")) {
    $user->where("company", $request->input("company"));
}

// 根據(jù)城市查找用戶
if ($request->has("city")) {
    $user->where("city", $request->input("city"));
}

// 只查找有對(duì)接我公司銷售經(jīng)理的用戶
if ($request->has("managers")) {
    $user->whereHas("managers", function ($query) use ($request) {
        $query->whereIn("managers.name", $request->input("managers"));
    });
}

// 如果有 "event" 參數(shù)
if ($request->has("event")) {

    // 只查找被邀請(qǐng)的用戶
    $user->whereHas("rsvp.event", function ($query) use ($request) {
        $query->where("event.slug", $request->input("event"));
    });
    
    // 只查找回復(fù)邀請(qǐng)的用戶( 以任何形式回復(fù)都可以 )
    if ($request->has("responded")) {
        $user->whereHas("rsvp", function ($query) use ($request) {
            $query->whereNotNull("responded_at");
        });
    }

    // 只查找回復(fù)邀請(qǐng)的用戶( 限制回復(fù)的具體內(nèi)容 )
    if ($request->has("response")) {
        $user->whereHas("rsvp", function ($query) use ($request) {
            $query->where("response", "I will be attending");
        });
    }
}

// 最終獲取對(duì)象并返回
return $user->get();

搞定,棒極了!

是否還需要重構(gòu)?

通過上面的代碼我們實(shí)現(xiàn)了業(yè)務(wù)需求,可以根據(jù)搜索條件返回正確的用戶信息。但是我們能說這是最佳實(shí)踐嗎?顯然是不能。

現(xiàn)在是通過一系列條件判斷的嵌套來實(shí)現(xiàn)業(yè)務(wù)邏輯,而且所有的邏輯都在控制器里,這樣做真的合適嗎?

這可能是一個(gè)見仁見智的問題,最好還是結(jié)合自己的項(xiàng)目,具體問題具體分析。如果你的項(xiàng)目比較小,邏輯相對(duì)簡(jiǎn)單,而且只是一個(gè)短期需求的項(xiàng)目,那么就不必糾結(jié)這個(gè)問題了,直接照上面的邏輯寫就好了。 

然而,如果你是在構(gòu)建一個(gè)比較復(fù)雜的項(xiàng)目,那么我們還是需要更加優(yōu)雅且擴(kuò)展性好的解決方案。

編寫新的搜索?api

當(dāng)我要寫一個(gè)功能接口的時(shí)候,我不會(huì)立刻去寫核心代碼,我通常會(huì)先想想我要怎么用這個(gè)接口。這可能就是俗稱的「面向結(jié)果編程」(或者說是「結(jié)果導(dǎo)向思維」)。

「在你寫一個(gè)組件之前,建議你先寫一些要用這個(gè)組件的測(cè)試代碼。通過這種方式,你會(huì)更加清晰地知道你究竟要寫哪些函數(shù),以及傳哪些必要的參數(shù),這樣你才能寫出真正好用的接口。

因?yàn)閷懡涌诘哪康氖呛?jiǎn)化使用組件的代碼,而不是簡(jiǎn)化接口自身的代碼。」 ( 摘自:?c2.com)

根據(jù)我的經(jīng)驗(yàn),這個(gè)方法能幫助我寫出可讀性更強(qiáng),更加優(yōu)雅的程序。還有一個(gè)很大的額外收獲就是,通過這種階段性的驗(yàn)收測(cè)試,我能更好地抓住商業(yè)需求。因此,我可以很自信地說我寫的程序可以很好地滿足市場(chǎng)的需求,具有很高商業(yè)價(jià)值。

以下添加到搜索功能的代碼中,我希望我的搜索 api 是這樣寫的:

return UserSearch::apply($filters);

這樣有著很好的可讀性。 根據(jù)經(jīng)驗(yàn), 如果我查閱代碼能想看文章的句子一樣,那會(huì)非常美妙。像剛剛的情況下:

搜索用戶時(shí)加上一個(gè)過濾器再返回搜索結(jié)果。

這對(duì)技術(shù)人員和非技術(shù)人員都有意義。

我想我需要新建一個(gè) UserSearch 類,還需要一個(gè)靜態(tài)的 apply 函數(shù)來接收過濾條件。讓我開始吧:


最簡(jiǎn)單的方式,讓我們把控制器中的代碼復(fù)制到 apply 函數(shù)中:

newQuery();

        // 基于用戶名搜索
        if ($filters->has("name")) {
            $user->where("name", $filters->input("name"));
        }

        // 基于用戶的公司名搜索
        if ($filters->has("company")) {
            $user->where("company", $filters->input("company"));
        }

        // 基于用戶的城市名搜索
        if ($filters->has("city")) {
            $user->where("city", $filters->input("city"));
        }

        // 只返回分配了銷售經(jīng)理的用戶
        if ($filters->has("managers")) {
            $user->whereHas("managers", 
                function ($query) use ($filters) {
                    $query->whereIn("managers.name", 
                        $filters->input("managers"));
                });
        }

   
    // 搜索條件中是否包含 "event’ ?
        if ($filters->has("event")) {

            // 只返回被邀請(qǐng)參加了活動(dòng)的用戶
            $user->whereHas("rsvp.event", 
                function ($query) use ($filters) {
                    $query->where("event.slug", 
                        $filters->input("event"));
                });

        
            // 只返回以任何形式答復(fù)了邀請(qǐng)的用戶
            if ($filters->has("responded")) {
                $user->whereHas("rsvp", 
                    function ($query) use ($filters) {
                        $query->whereNotNull("responded_at");
                    });
            }

          
            // 只返回以某種方式答復(fù)了邀請(qǐng)的用戶
            if ($filters->has("response")) {
                $user->whereHas("rsvp", 
                    function ($query) use ($filters) {
                        $query->where("response", 
                            "I will be attending");
                    });
            }
        }

        // 返回搜索結(jié)果
        return $user->get();
    }
}

我們做了一系列的改變。 首先, 我們將在控制器中的 $request 變量更名為 filters 來提高可讀性。

其次,由于 newQuery() 方法不是靜態(tài)方法,無(wú)法通過 User 類靜態(tài)調(diào)用,所以我們需要先創(chuàng)建一個(gè) User 對(duì)象,再調(diào)用這個(gè)方法:

$user = (new User)->newQuery();

調(diào)用上面的 UserSearch 接口,對(duì)控制器的代碼進(jìn)行重構(gòu):


好多了,是不是?把一系列的條件判斷交給專門的類處理,使控制器的代碼簡(jiǎn)介清新。

下面進(jìn)入見證奇跡的時(shí)刻

在這篇文章的例子中,一共有 7 個(gè)過濾條件,但是現(xiàn)實(shí)的情況是更多更多。所以在這種情況下,只用一個(gè)文件來處理所有的過濾邏輯,就顯得差強(qiáng)人意了。擴(kuò)展性不好,而且也不符合 S.O.L.I.D. principles 原則。目前,apply()? 方法需要處理這些邏輯:

檢查參數(shù)是否存在

把參數(shù)轉(zhuǎn)成查詢條件

執(zhí)行查詢

如果我想增加一個(gè)新的過濾條件,或者修改一下現(xiàn)有的某個(gè)過濾條件的邏輯,我都要不停地修改 UserSearch 類,因?yàn)樗羞^濾條件的處理都在這一個(gè)類里,隨著業(yè)務(wù)邏輯的增加,會(huì)有點(diǎn)尾大不掉的感覺。所以對(duì)每個(gè)過濾條件多帶帶建個(gè)類文件是非常有必要的。

先從 Name 條件開始吧。但是,就像我們前面講的,還是想一下我們需要怎樣使用這種單一條件過濾的接口。

我希望可以這樣調(diào)用這個(gè)接口:

$user = (new User)->newQuery();
$user = static::applyFiltersToQuery($filters, $user);
return $user->get();

不過這里再使用 $user 這個(gè)變量名就不合適了,應(yīng)該用 $query 更有意義。

public static function apply(Request $filters)
{
    $query = (new User)->newQuery();

    $query = static::applyFiltersToQuery($filters, $query);

    return $query->get();
}

然后把所有條件過濾的邏輯都放到 applyFiltersToQuery() 這個(gè)新接口里。

下面開始創(chuàng)建第一個(gè)條件過濾類:Name.

where("name", $value);
    }
}

在這個(gè)類里定義一個(gè)靜態(tài)方法 apply(),這個(gè)方法接收兩個(gè)參數(shù),一個(gè)是 Builder 實(shí)例,另一個(gè)是過濾條件的值( 在這個(gè)例子中,這個(gè)值是 "Billy" )。然后帶著這個(gè)過濾條件返回一個(gè)新的 Builder 實(shí)例。

接下來是 City 類:

where("city", $value);
    }
}

如你所見,City 類的代碼邏輯跟 Name 類相同,只是過濾條件變成了 "city"。讓每個(gè)條件過濾類都只有一個(gè)簡(jiǎn)單的 apply() 方法,而且方法接收的參數(shù)和處理的邏輯都相同,我們可以把這看成一個(gè)協(xié)議,這一點(diǎn)很重要,下面我會(huì)具體說明。

為了確保每個(gè)條件過濾類都能遵循這個(gè)協(xié)議,我決定寫一個(gè)接口,讓每個(gè)類都實(shí)現(xiàn)這個(gè)接口。


我為這個(gè)接口的方法寫了詳細(xì)的注釋,這樣做的好處是,對(duì)于每一個(gè)實(shí)現(xiàn)這個(gè)接口的類,我都可以利用我的 IDE ( PHPStorm ) 自動(dòng)生成同樣的注釋。

下面,分別在 Name 和 City 類中實(shí)現(xiàn)這個(gè) Filter 接口:

where("name", $value);
    }
}

以及

where("city", $value);
    }
}

完美。現(xiàn)在已經(jīng)有兩個(gè)條件過濾類完美地遵循了這個(gè)協(xié)議。把我的目錄結(jié)構(gòu)附在下面給大家參考一下:

這是到目前為止關(guān)于搜索的文件結(jié)構(gòu)。

我把所有的條件過濾類的文件放在一個(gè)多帶帶的文件夾里,這讓我對(duì)已有的過濾條件一目了然。

使用新的過濾器

現(xiàn)在回過頭來看 UserSearch 類的 applyFiltersToQuery() 方法,發(fā)現(xiàn)我們可以再做一些優(yōu)化了。

首先,把每個(gè)條件判斷里構(gòu)建查詢語(yǔ)句的工作,交給對(duì)應(yīng)的過濾類去做。

// 根據(jù)姓名搜索用戶
if ($filters->has("name")) {
    $query = Name::apply($query, $filters->input("name"));
}

// 根據(jù)城市搜索用戶
if ($filters->has("city")) {
    $query = City::apply($query, $filters->input("city"));
}

現(xiàn)在根據(jù)過濾條件構(gòu)建查詢語(yǔ)句的工作已經(jīng)轉(zhuǎn)給各個(gè)相應(yīng)的過濾類了,但是判斷每個(gè)過濾條件是否存在的工作,還是通過一系列的條件判斷語(yǔ)句完成的。而且條件判斷的參數(shù)都是寫死的,一個(gè)參數(shù)對(duì)應(yīng)一個(gè)過濾類。這樣我每增加一個(gè)新的過濾條件,我都要重新修改 UserSearch 類的代碼。這顯然是一個(gè)需要解決的問題。

其實(shí),根據(jù)我們前面介紹的命名規(guī)則, 我們很容易把這段條件判斷的代碼改成動(dòng)態(tài)的:

AppUserSearchFiltersName

AppUserSearchFiltersCity

就是結(jié)合命名空間和過濾條件的名稱,動(dòng)態(tài)地創(chuàng)建過濾類(當(dāng)然,要對(duì)接收到的過濾條件參數(shù)做適當(dāng)?shù)奶幚恚?/p>

大概就是這個(gè)思路,下面是具體實(shí)現(xiàn):

private static function applyFiltersToQuery(
                           Request $filters, Builder $query) {
    foreach ($filters->all() as $filterName => $value) {

        $decorator =
            __NAMESPACE__ . "Filters" . 
                str_replace(" ", "", ucwords(
                    str_replace("_", " ", $filterName)));

        if (class_exists($decorator)) {
            $query = $decorator::apply($query, $value);
        }

    }

    return $query;
}

下面逐行分析這段代碼:

foreach ($filters->all() as $filterName => $value) {

遍歷所有的過濾參數(shù),把參數(shù)名(比如 city)賦值給變量 $filterName,參數(shù)值(比如 London)復(fù)制給變量 $value

$decorator =
            __NAMESPACE__ . "Filters" . 
                str_replace(" ", "", ucwords(
                    str_replace("_", " ", $filterName)));

這里是對(duì)參數(shù)名進(jìn)行處理,將下劃線改成空格,讓每個(gè)單詞都首字母大寫,然后去掉空格,如下例子:

"name"            => AppUserSearchFiltersName,
"company"         => AppUserSearchFiltersCompany,
"city"            => AppUserSearchFiltersCity,
"event"           => AppUserSearchFiltersEvent,
"responded"       => AppUserSearchFiltersResponded,
"response"        => AppUserSearchFiltersResponse,
"managers"        => AppUserSearchFiltersManagers

如果有參數(shù)名是帶下劃線的,比如 has_responded,根據(jù)上面的規(guī)則,它將被處理成 HasResponded,因此,其相應(yīng)的過濾類的名字也要是這個(gè)。

if (class_exists($decorator)) {

這里就是要先確定這個(gè)過濾類是存在的,再執(zhí)行下面的操作,否則在客戶端報(bào)錯(cuò)就尷尬了。

$query = $decorator::apply($query, $value);

這里就是神器的地方了,PHP 允許把變量 $decorator 作為類,并調(diào)用其方法(在這里就是 apply() 方法了)。現(xiàn)在再看這個(gè)接口的代碼,發(fā)現(xiàn)我們?cè)俅螌?shí)力證明了磨刀不誤砍柴工。現(xiàn)在我們可以確保每個(gè)過濾類對(duì)外響應(yīng)一致,內(nèi)部又可以分別處理各自的邏輯。

最后的優(yōu)化

現(xiàn)在 UserSearch 類的代碼應(yīng)該已經(jīng)比之前好多了,但是,我覺得還可以更好,所以我又做了些改動(dòng),這是最終版本:

newQuery()
            );

        return static::getResults($query);
    }
    
    private static function applyDecoratorsFromRequest(Request $request, Builder $query)
    {
        foreach ($request->all() as $filterName => $value) {

            $decorator = static::createFilterDecorator($filterName);

            if (static::isValidDecorator($decorator)) {
                $query = $decorator::apply($query, $value);
            }

        }
        return $query;
    }
    
    private static function createFilterDecorator($name)
    {
        return return __NAMESPACE__ . "Filters" . 
            str_replace(" ", "", 
                ucwords(str_replace("_", " ", $name)));
    }
    
    private static function isValidDecorator($decorator)
    {
        return class_exists($decorator);
    }

    private static function getResults(Builder $query)
    {
        return $query->get();
    }

}

我最后決定去掉 applyFiltersToQuery() 方法,是因?yàn)楦杏X跟接口的主要方法名 apply() 有點(diǎn)沖突了。

而且,為了貫徹執(zhí)行單一職責(zé)原則,我把原來 applyFiltersToQuery() 方法里比較復(fù)雜的邏輯又做了拆分,為動(dòng)態(tài)創(chuàng)建過濾類名稱,和確認(rèn)過濾類是否存在的判斷,都寫了多帶帶的方法。

這樣,即便要擴(kuò)展搜索接口,我也不需要再去反復(fù)修改 UserSearch 類里的代碼了。需要增加新的過濾條件嗎?簡(jiǎn)單,只要在 AppUserSearchFilters 目錄下創(chuàng)建一個(gè)過濾類,并使之實(shí)現(xiàn) Filter 接口就 OK 了。

結(jié)論

我們已經(jīng)把一個(gè)擁有所有搜索邏輯的巨大控制器方法保存成一個(gè)允許打開過濾器的模塊化過濾系統(tǒng),而不需要添加修改核心代碼。 像評(píng)論里?@rockroxx所建議的,另一個(gè)重構(gòu)的方案是把所有方法提取到?trait 并將?User? 設(shè)置成 ?const? 然后由?Interface 實(shí)現(xiàn)。

class UserSearch implements Searchable {
    const MODEL = AppUser;
    use SearchableTrait;
}

如果你很好的理解了這個(gè)設(shè)計(jì)模式,你可以?利用多態(tài)代替多條件。

代碼會(huì)提交到?GitHub?你可以 fork,測(cè)試和實(shí)驗(yàn)。

如何解決多條件高級(jí)搜索,我希望你能留下你的想法、建議和評(píng)論。

文章轉(zhuǎn)自:https://learnku.com/laravel/t... 

更多文章:https://learnku.com/laravel/c...

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31090.html

相關(guān)文章

  • php 學(xué)習(xí)指南及技術(shù)干貨

    摘要:安全生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù)一個(gè)兼容標(biāo)準(zhǔn)的過濾器一個(gè)生成隨機(jī)數(shù)和字符串的庫(kù)使用生成隨機(jī)數(shù)的庫(kù)一個(gè)安全庫(kù)一個(gè)純安全通信庫(kù)一個(gè)簡(jiǎn)單的鍵值加密存儲(chǔ)庫(kù)一個(gè)結(jié)構(gòu)化的安全層一個(gè)試驗(yàn)的面向?qū)ο蟮陌b庫(kù)一個(gè)掃描文件安全的庫(kù) Security 安全 生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù) HTML Purifier-一個(gè)兼容標(biāo)準(zhǔn)的HTML過濾器 RandomLib-一個(gè)生成隨機(jī)數(shù)和字...

    lifefriend_007 評(píng)論0 收藏0
  • php 學(xué)習(xí)指南及技術(shù)干貨

    摘要:安全生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù)一個(gè)兼容標(biāo)準(zhǔn)的過濾器一個(gè)生成隨機(jī)數(shù)和字符串的庫(kù)使用生成隨機(jī)數(shù)的庫(kù)一個(gè)安全庫(kù)一個(gè)純安全通信庫(kù)一個(gè)簡(jiǎn)單的鍵值加密存儲(chǔ)庫(kù)一個(gè)結(jié)構(gòu)化的安全層一個(gè)試驗(yàn)的面向?qū)ο蟮陌b庫(kù)一個(gè)掃描文件安全的庫(kù) Security 安全 生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù) HTML Purifier-一個(gè)兼容標(biāo)準(zhǔn)的HTML過濾器 RandomLib-一個(gè)生成隨機(jī)數(shù)和字...

    skinner 評(píng)論0 收藏0
  • 前端練級(jí)攻略(第二部分)

    摘要:是文檔的一種表示結(jié)構(gòu)。這些任務(wù)大部分都是基于它。這個(gè)實(shí)踐的重點(diǎn)是把你在前端練級(jí)攻略第部分中學(xué)到的一些東西和結(jié)合起來。一旦你進(jìn)入框架部分,你將更好地理解并使用它們。到目前為止,你一直在使用進(jìn)行操作。它是在前端系統(tǒng)像今天這樣復(fù)雜之前編寫的。 本文是 前端練級(jí)攻略 第二部分,第一部分請(qǐng)看下面: 前端練級(jí)攻略(第一部分) 在第二部分,我們將重點(diǎn)學(xué)習(xí) JavaScript 作為一種獨(dú)立的語(yǔ)言,如...

    BWrong 評(píng)論0 收藏0
  • Laravel深入學(xué)習(xí)6 - 應(yīng)用體系結(jié)構(gòu):解耦事件處理器

    摘要:別堵塞了傳輸層大多數(shù)事件處理器被當(dāng)作傳輸層組件。解耦事件處理器開始本命題前,我們來使用一個(gè)示例。假想下把隊(duì)列處理器用來發(fā)送消息給用戶。盡量避免在事件處理器中摻雜太多的業(yè)務(wù)邏輯。 聲明:本文并非博主原創(chuàng),而是來自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證90%的原汁性,另外因?yàn)槭抢斫夥g,肯定會(huì)有錯(cuò)誤的...

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

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

0條評(píng)論

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