【发布时间】:2021-06-24 18:03:21
【问题描述】:
在什么场景下我们应该使用服务容器而不是直接调用一个新的类? 我从 Laravel 官方文档中读到它主要用于管理类依赖和执行依赖注入,但是我不确定我是否理解正确。
例如工资单应用程序,我们将有一个工资单类、员工类、休假类、时间表类。 因此,要处理每月工资单,工资单类将取决于
- 员工类 (getBasicSalary)
- 请假类 (getUnpaidLeaveCount)
- 时间表类 (getLateHoursCount)
下面是我平时写的(没有任何设计模式)
Class PayrollProcessController
{
public function index(){
$payrollObj = new Payroll();
$payroll->setPayrollMonth('202106');
$payroll->process();
}
}
Class Payroll
{
private $payrollMonth;
public function process()
{
// loop employee from database
foreach ($employees as $employee_id){
$salary = $this->calculateNetSalary($employee_id);
// save into db
}
}
public function calculateNetSalary($employee_id)
{
$employee = Employee::find($employee_id);
$basicSalary = $employee->getBasicSalary();
$basicSalaryPerDay = $basicSalary / date('t');
$basicSalaryPerHour = $basicSalaryPerDay / 8;
$leaveTakenDay = Leave::getUnpaidLeaveCount( $employee->getId(), $this->payrollMonth);
$leaveDeductionAmount = $basicSalaryPerDay * $leaveTakenDay;
$timesheetLateHours = Timesheet::getLateHoursCount($employee->getId(), $this->payrollMonth);
$lateDeductionAmount = $basicSalaryPerHour * $timesheetLateHours;
$netSalary = $basicSalary - $leaveDeductionAmount - $lateDeductionAmount;
return $netSalary;
}
}
如果应用服务容器概念,
Class PayrollProcessController
{
public function index(Payroll $payroll){
$payroll->setPayrollMonth('202106');
$payroll->process();
}
}
Class Payroll
{
public function process()
{
// loop employee from database
foreach ($employees as $employee_id){
$employee = app(Employee::class);
$employee = $employee->find($employee_id);
$leave = app(Leave::class);
$timesheet = app(Timesheet::class);
$salary = $this->calculateNetSalary($employee, $leave, $timesheet);
// save into db
}
}
public function calculateNetSalary(Employee $employee, Leave $leave, Timesheet $timesheet)
{
$basicSalary = $employee->getBasicSalary();
$basicSalaryPerDay = $basicSalary / date('t');
$basicSalaryPerHour = $basicSalaryPerDay / 8;
$leaveTakenDay = $leave->getUnpaidLeaveCount( $employee->getId(), $this->payrollMonth);
$leaveDeductionAmount = $basicSalaryPerDay * $leaveTakenDay;
$timesheetLateHours = $timesheet->getLateHoursCount($employee->getId(), $this->payrollMonth);
$lateDeductionAmount = $basicSalaryPerHour * $timesheetLateHours;
$netSalary = $basicSalary - $leaveDeductionAmount - $lateDeductionAmount;
return $netSalary;
}
}
问题:
-
上述概念正确吗?我可以看到服务容器允许我将工资单、员工、时间表、休假类移动到 laravel 包中,以便我可以安装在另一个 laravel 应用程序中(主要好处是我可以重用代码并覆盖类如果需要,在服务提供者中指定类路径)
-
我再次查看了服务容器文档 https://laravel.com/docs/8.x/container#when-to-use-the-container,是这样写的:
首先,如果您编写一个实现接口的类,并且希望在路由或类构造函数中对该接口进行类型提示,则必须告诉容器如何解析该接口。其次,如果您正在编写一个 Laravel 包并计划与其他 Laravel 开发人员共享,您可能需要将包的服务绑定到容器中。
所以我可以说除非我们将工资单模块发布为 laravel 包供其他人使用或编写单元测试,否则使用服务容器没有意义?
-
如果我们看一下 opencart 的注册类,是不是类似于 Laravel 的服务容器? https://github.com/opencart/opencart/blob/e22ddfb060752cd8134abbfb104202172ab45c86/upload/system/framework.php#L9
-
以opencart为例,Language类是单例设计模式,而registry是容器设计模式?
$language = new \Opencart\System\Library\Language($config->get('language_code')); $language->addPath(DIR_LANGUAGE); $language->load($config->get('language_code')); $registry->set('language', $language);
【问题讨论】:
标签: php laravel design-patterns containers