在你的 Laravel 职业生涯中,你会多次听到“依赖注入”这个词,所以你不妨熟悉一下它。在我们进入 Laravel 之前,让我们看看依赖注入作为 PHP(或任何编程语言)中的一个概念。
我们应该知道我们可以将对象作为参数传递给方法。我们也可以用继承类打hint,这是对PHP多态性的一个概述。我们可以将对象作为参数传递给构造函数。然后构造函数将在类中设置属性。这称为依赖注入。
在我的 PHP 教程系列中,我们研究了依赖注入。我们可以使用该代码来刷新自己。首先,让我们创建几个类:Lamborghini 和 Ferrari。这些类中的每一个都需要 Car 类。
<?php
require_once("Car.php");
class Lamborghini extends Car {
}
<?php
require_once("Ferrari.php");
class Ferrari extends Car {
}
我们现在可以创建我们的测试类并实例化这些对象。
<?php
// Object Arguments
require_once("Lamborghini.php");
require_once("Ferrari.php");
$lamborghini_diablo = new Lamborghini(1999, "Lamborghini", "Diablo");
$ferrari_f355 = new Ferrari(1996, "Ferrari", "F355");
你觉得上面的代码行得通吗?我们没有向 Lamborghini 和 Ferrari 类添加任何构造函数,但我们将参数传递给构造函数。信不信由你,它确实会起作用。为什么?因为我们已经在Car父类中定义了构造函数参数。如果我们的子类中没有构造函数,它会自动将参数传递给我们的父类。让我们快速浏览一下我们的Car类构造函数。
<?php
require_once('Vehicle.php');
require_once('Engine.php');
require_once('Transmission.php');
class Car extends Vehicle
{
use Transmission, Engine {
Transmission::check_oil_level insteadof Engine;
Engine::check_oil_level as check_engine_oil_level;
}
const HAS_HEADLIGHTS = true;
const HAS_TAIL_LIGHTS = true;
const HAS_TURN_SIGNALS = true;
private int $fuel_type;
private int $hp;
private int $tq;
private string $transmission;
private string $vehicle_type;
private bool $car_on;
public function __construct(int $year,
string $make,
string $model,
string $color = "",
int $fuel_type = 93,
int $hp = -1,
int $tq = -1,
string $transmission = "5 Speed Manual",
string $vehicle_type = "",
float $exterior_height = -1,
float $exterior_width = -1,
float $exterior_length = -1,
string $exterior_um = "in",
float $weight = -1,
string $weight_um = "lbs",
bool $car_on = false
)
{
$this->year = $year;
$this->make = $make;
$this->model = $model;
$this->color = $color;
$this->fuel_type = $fuel_type;
$this->hp = $hp;
$this->tq = $tq;
$this->transmission = $transmission;
$this->vehicle_type = $vehicle_type;
$this->exterior_height = $exterior_height;
$this->exterior_width = $exterior_width;
$this->exterior_length = $exterior_length;
$this->exterior_um = $exterior_um;
$this->weight = $weight;
$this->weight_um = $weight_um;
$this->car_on = $car_on;
}
//...
}
我们现在能做什么?我们可以访问父类中的所有属性和方法(只要它们不是私有的)。所以我们可以调用那些属性和方法。
<?php
// Object Arguments
require_once("Lamborghini.php");
require_once("Ferrari.php");
$lamborghini_diablo = new Lamborghini(1999, "Lamborghini", "Diablo");
echo $lamborghini_diablo->check_engine_oil_level();
$ferrari_f355 = new Ferrari(1996, "Ferrari", "F355");
echo $ferrari_f355->check_oil_level();
伟大的。我们还没有完成任何对象作为参数的传递。
我们要做的是创建一个Driver类。我们Driver类中的第一个方法将是drive() 方法,因为Driver应该可以drive() 开车。我们可以将Car对象作为参数传递给它,然后我们可以使用各种不同的Car方法来帮助我们驾驶汽车。我们将重点关注Car类中的两个方法是turnOn() 方法和drive() 方法。
<?php
class Driver {
public function drive(Car $car) {
echo $car->turnOn();
echo $car->drive();
}
}
我们现在可以回到我们的测试类并实例化对象。
<?php
// Object Arguments
require_once("Lamborghini.php");
require_once("Ferrari.php");
$lamborghini_diablo = new Lamborghini(1999, "Lamborghini", "Diablo");
$ferrari_f355 = new Ferrari(1996, "Ferrari", "F355");
$dino = new Driver();
$dino->drive( $lamborghini_diablo );
刚刚发生了什么?我以为我们指定我们必须将Car类型对象作为参数传递给drive()方法。它在drive() 声明中。
public function drive( Car $car )
这是你关于多态性的课程。由于我们的类Lamborghini和Ferrari类都扩展了Car类,从技术上讲它们是汽车!你猜怎么了?由于Car扩展了Vehicle类,从技术上讲,类Lamborghini和Ferrari类也是车辆!您想知道我们是否可以修改我们的声明以说明以下内容:
public function drive( Vehicle $vehicle )
答案是肯定的!你绝对可以。而且您仍会将 the$lamborghini_diablo 或$ferrari_f355 作为参数传递给该drive() 方法。如果我们将 传递$ferrari_f355 给我们的drive() 方法,我们将得到以下结果:Ferrari F355 has been turned on. I’m driving.
现在让我们做一些不同的事情。int我们创建了、string等类型的类属性?只要看看Car类,您就会看到所有各种不同的属性。我们如何初始化这些属性?从构造函数。在实例化对象时,我们会将参数传递给构造函数,然后构造函数会使用作为参数传递的值来初始化这些属性。与我们将在课堂上所做的相同的概念Driver。我们将指定我们将拥有一个Car基于属性,并且我们将通过我们的构造函数传递一个Car参数并将其分配给我们的Car属性。请记住, aCar只是一种数据类型,例如intor string。
<?php
class Driver {
private Car $car;
public function __construct(Car $car)
{
$this->car = $car;
}
}
我现在不想在这里失去你。请记住,一旦$car 通过我们的构造函数初始化了该属性,我们就可以访问我们所有的Car属性和方法,例如turnOn() 和drive()。因为我们知道我们必须将一种Car类型的对象传递给我们的构造函数并且它必须分配给我们的$car 属性,所以我们可以创建方法以预期我们将能够访问这些Car方法。所以,让我们drive() 在我们的类中重新创建我们的方法Driver。
<?php
class Driver {
private Car $car;
public function __construct(Car $car)
{
$this->car = $car;
}
public function drive() {
echo $this->car->turnOn();
echo $this->car->drive();
echo $this->car->turnOff();
}
}
你知道这是怎么回事吗?让我们在我们的测试文件中运行一个示例,然后遍历代码。
<?php
// Object Arguments
require_once("Lamborghini.php");
require_once("Ferrari.php");
require_once("Driver.php");
$lamborghini_diablo = new Lamborghini(1999, "Lamborghini", "Diablo");
$ferrari_f355 = new Ferrari(1996, "Ferrari", "F355");
$dino = new Driver( $ferrari_f355 );
$dino->drive();
$harrison = new Driver( $lamborghini_diablo );
$harrison->drive();
是时候进行彻底的代码遍历了。
- PHP 进入测试类,需要
Lamborghini, Ferrari, 和Driver类。 - 实例化了一个新
Lamborghini对象,其类型为Car。 - 由于
Lamborghini该类不包含构造函数,因此调用父构造函数并将三个参数传递给父构造函数:1999, Lamborghini, Diablo。 - 实例化了一个新
Ferrari对象,它也是 类型Car。 - 由于
Ferrari该类不包含构造函数,因此调用父构造函数并将三个参数传递给父构造函数:1996, Ferrari, F355。 - 创建一个新对象
Driver并将该$ferrari_f355对象作为参数传递给构造函数。 - 该类使用刚传递给它的对象
Driver初始化了$car自身内部的属性。$ferrari_f355该$car属性现在可以访问 中的所有方法$ferrari_f355。 - 该
drive()方法被调用。 - PHP进入
drive()方法。它看到它正在调用 3 个不同的方法,所有方法都位于$car属性内,从技术上讲,这就是$ferrari_355对象。 - PHP 执行
turnOn(), drive(), 和turnOff()方法。 -
Driver在测试文件中创建一个新对象,并将该$lamborghini_diablo对象作为参数传递给构造函数。 - 该类使用刚传递给它的对象
Driver初始化了$car自身内部的属性。$lamborghini_diablo该$car 属性现在可以访问 中的所有方法$lamborghini_diablo。 - 该
drive()方法被调用。 - PHP进入
drive()方法。它看到它正在调用 3 个不同的方法,所有方法都位于$car属性内,从技术上讲,这就是$lamborghini_diablo对象。 - PHP 执行
turnOn(), drive(), 和turnOff()方法。
通过构造函数传递参数并将其分配给属性就是所谓的依赖注入。
只要您想象参数如何在代码中移动的流程,我相信您会理解依赖注入。简单主题的复杂名称。
我们将在下一篇文章中解决 Laravel 对依赖注入的使用。










