2017-04-26 20 views
6

Tôi đã xem this video và lúc 7:10, anh ấy thêm phụ thuộc db và đang sử dụng đóng để gán giá trị.Tại sao phải sử dụng đóng cửa để chuyển nhượng thay vì gán trực tiếp giá trị cho khóa?

Câu hỏi của tôi là tại sao không chỉ sử dụng giao trực tiếp thay vào đó, tôi muốn nói là không làm điều này:

$container['db'] = $capsule; 

tương đương để làm điều này:

$container['db'] = function ($container) use ($capsule) { 
    return $capsule; 
} 

Nếu không, sự khác biệt là gì và cách nào tốt hơn?

Trả lời

2

TLDR bởi vì việc xác định các phụ thuộc như đóng cửa làm cho thùng chứa phụ thuộc có thể xây dựng chúng theo yêu cầu, do đó bạn không cần phải lo lắng về thứ tự định nghĩa và quản lý phụ thuộc của chúng theo cách thủ công.

Pimple là Dependency Injection Container, nó được cho là giúp bạn thiết lập các đối tượng của bạn bằng cách quản lý phụ thuộc của họ một cách dễ dàng và thuận tiện.

Nếu bạn trực tiếp gán giá trị cho một chìa khóa, Pimple gọi giá trị mà một tham số , và khi bạn cần truy cập quan trọng mà, nó chỉ đơn giản trả về giá trị chính xác:

$container['sample-param'] = 'foo'; 
echo $container['sample-param']; 
//output: foo 

Nhưng điểm mấu chốt là , điều này sample-param không yêu cầu bất kỳ thiết lập, nó chỉ đơn giản là một giá trị và chúng tôi đang tốt với điều đó. Nhưng giả sử thiết lập dịch vụ sau:

$container['myService'] = function($c) { 
    $service = new \Some\Complicated\Service(); 
    //this service depends on cache service 
    $service->setCache($c['cache']); 
    return $service; 
} 

$container['cache'] = function($c) { 
    $cache = new \Cache\Driver(); 
    //our cache driver needs a db connection 
    $cache->setDbConnection($c['db']); 
    return $cache; 
} 

$container['db'] = function($c) { 
    //our database connection requires some parameters 
    $dbConnection = new \Database\Connection($c['db-config']); 
    return $dbConnection; 
} 

$container['db-config'] = [ 
    'username' => 'foo', 
    'password' => 'bar', 
    'host' => 'localhost' 
]; 

//Now we want to user our service: 
$container['myService']->doSomething(); 

Hãy chú ý đến thứ tự mà tôi đã sử dụng để xác định các khóa khác nhau trong vùng chứa.

myService cần cache nhưng định nghĩa bộ nhớ cache xuất hiện sau định nghĩa myService. Và đây là nơi Pimple đang giúp đỡ, và đây là lý do tại sao chúng tôi vượt qua container để đóng cửa mỗi, bởi vì Pimple là để xây dựng phụ thuộc của chúng tôi theo yêu cầu. Khi chúng ta cần truy cập myService Pimple xem xét lưu trữ dữ liệu nội bộ của nó, nếu nó đã xây dựng và lưu trữ thành công myService thành công, nó sẽ trả về cùng một cá thể đó, nếu không nó sẽ gọi đóng của chúng ta để xây dựng nó. Và khi đóng cửa của chúng tôi được gọi, nó sẽ hỏi Pimple ($ c là container Pimple) để cung cấp cho nó dependecies (trong trường hợp này là dịch vụ cache). Nhược điểm áp dụng cùng một điều trên bộ nhớ cache, nếu nó không được xây dựng nào được nêu ra, nó sẽ xây dựng nó và như vậy ... cho đến khi nó được vào phần yêu cầu params đơn giản như db-config mà sẽ ngay lập tức trở lại. Và trong chuỗi các cuộc gọi đóng cửa này, đối tượng của chúng ta và tất cả các phụ thuộc của nó được xây dựng.

Bây giờ hãy tưởng tượng điều gì sẽ xảy ra nếu chúng tôi sử dụng các giá trị đơn giản thay vì đóng cửa? Trong trường hợp đó, khi chúng tôi muốn xây dựng myService, chúng tôi phải quản lý các phụ thuộc của nó. Chúng tôi phải đảm bảo các phụ thuộc của nó được xác định trước chúng tôi xác định dịch vụ và chúng tôi phải xử lý các vấn đề khác liên quan đến việc quản lý các phụ thuộc. Trong trường hợp đó, chúng tôi không thể chỉ định myServicegiả định của chúng tôi có dịch vụ cache, sẽ được xác định sau.

-1

Nó hoàn toàn khác. Đầu tiên một $container['db'] = $capsule;
nghĩa là $container mảng có một chìa khóa db và quan trọng đó là bằng $capsule, thứ hai có nghĩa là bạn có một mảng $containerdb then chốt có giá trị đóng cửa. Bạn có thể thấy sự khác biệt khi đổ hai kết quả:

Đóng dụ:

$capsule = 1; 
$container['db'] = function ($container) use ($capsule) { 
    return $capsule; 
}; 
var_dump($container); 

Kết quả:

Array(1) { 
    ["db"]=> 
    object(Closure)#1 (2) { 
    ["static"]=> 
    array(1) { 
     ["capsule"]=> 
     int(1) 
    } 
    ["parameter"]=> 
    array(1) { 
     ["$container"]=> 
     string(10) "<required>" 
    } 
    } 
} 

không đóng cửa dụ:

$capsule = 1; 
$container['db'] = $capsule;  
var_dump($container); 

Kết quả:

result array(1) { 
    ["db"]=> 
    int(1) 
} 

Bạn có thể đọc về các bao đóng trong hướng dẫn sử dụng php để hiểu rõ hơn về vai trò của chúng. PHP Closures Manual

+1

Có, rõ ràng là loại dữ liệu của giá trị sẽ khác nhau. Những gì tôi thấy khó hiểu là làm thế nào để họ khác nhau về các trường hợp sử dụng và chức năng, và tại sao sử dụng một trong những khác? – tareq

+0

Nếu bạn nên trả lại $ capsule mà không có bất kỳ thay đổi nào, mà không có bất kỳ chức năng nào bạn có thể chỉ đơn giản là sử dụng phiên bản không đóng, nhưng nếu bạn có một số logic bạn nên sử dụng bao đóng (ví dụ nhân nó hoặc cái gì khác) –

0

Trong video đó, anh đang sử dụng khung công tác Slim cho vùng chứa theo mặc định là sử dụng Pimple cho vùng chứa của nó.

http://pimple.sensiolabs.org/

Trong tài liệu hướng dẫn trên trang đó nó đề cập đến những điều sau

Dịch vụ Định nghĩa Một dịch vụ là một đối tượng mà không một cái gì đó như là một phần của một hệ thống lớn hơn. Ví dụ về dịch vụ: kết nối cơ sở dữ liệu, công cụ tạo mẫu hoặc bưu phẩm. Hầu như bất kỳ đối tượng toàn cầu nào cũng có thể là dịch vụ .

dịch vụ được định nghĩa bởi các chức năng vô danh mà trả về một thể hiện của một đối tượng :

// define some services 
$container['session_storage'] = function ($container) { 
    return new SessionStorage('SESSION_ID'); 
}; 

$container['session'] = function ($container) { 
    return new Session($container['session_storage']); 
}; 

Chú ý rằng các chức năng ẩn danh có quyền truy cập vào các ví dụ chứa hiện tại, cho phép tham chiếu đến các dịch vụ hoặc các thông số khác.

Theo thiết kế các container mong đợi để gọi một hàm

container Pimple của thực hiện các giao diện \ArrayAccess(seen here), và điều đó có nghĩa là họ có thể làm cho hành động đối tượng như một mảng trong khi không nhất thiết phải là một.Trong mã nguồn bạn sẽ nhận thấy offsetSetoffsetGet, đó là những gì xảy ra khi bạn làm:

$container['a'] = function($c){ return new Blah();} 

$thing = $container['a']; 

tl; dr Đó là một điều cụ thể chứa mụn, không phải là một điều PHP cụ thể.

Các vấn đề liên quan