所以目前,我有一个用于商业地点的表格,以便从实际的商家表格中分隔这些地点。
在此表中,我想存储经度和纬度,显然我无法让用户输入,而不需要他们做我真正想要避免的手动工作。
所以我写了一个课程,以便为进入数据库准备好经度和纬度。
我已经在线阅读了关于在模型中执行setLongitudeAttribute()
功能的内容,但我将它从他们输入的整个地址中删除,因此我需要捕获整个请求,然后把它输入我自己。
我知道我可以在控制器中执行此操作并执行自定义插入,但我不知道是否可以将其全部包含在模型中。
所以基本上要打破它。
模型然后处理请求,以便根据地址设置经度和纬度。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Http\Calls\LongitudeLatitude;
class BusinessLocation extends Model
{
/**
* @var array
*/
protected $fillable = [
'business_id',
'address_line_1',
'address_line_2',
'address_line_3',
'address_line_4',
'postcode',
'longitude',
'latitude'
];
/**
* @var string
*/
protected $address;
protected function setAddressLine1Attribute($value)
{
$this->address .= $value . '+';
$this->attributes['address_line_1'] = $value;
}
protected function setAddressLine2Attribute($value)
{
$this->address .= $value . '+';
$this->attributes['address_line_2'] = $value;
}
protected function setAddressLine3Attribute($value)
{
$this->address .= $value . '+';
$this->attributes['address_line_3'] = $value;
}
protected function setAddress4Attribute($value)
{
$this->address .= $value . '+';
$this->attributes['address_line_4'] = $value;
}
protected function setPostcodeAttribute($value)
{
$this->address .= $value;
$this->attributes['postcode'] = $value;
$this->setCoordinates();
}
protected function setCoordinates()
{
$long_lat = new LongitudeLatitude();
$coords = $long_lat->get($this->address);
$this->attributes['longitude'] = $coords['longitude'];
$this->attributes['latitude'] = $coords['latitude'];
}
答案 0 :(得分:0)
首先,正如你正确提到的那样,在模型中编写这个逻辑并不是一个很好的做法,但是在控制器中。
如果我是你,我会将模型逻辑留给模型,其余部分留给控制器和其他对象,以及#34;转换&#34;输入。这甚至可以通过一些javascript库从客户端完成,只需将lat和long发送到服务器(您的选择)。
如果您仍想在模型中创建方法/设定器,我建议您在任何整合的库中获得一些灵感,并且更正式,最好,例如:Laravel Cashier(https://laravel.com/docs/5.6/billing ),在单独的逻辑单元中为模型提供额外的行为。
如果您想遵循Laravel Cashier方法,它会使用特征来应用行为: https://github.com/laravel/cashier/blob/7.0/src/Billable.php
它使用官方条带包(在您的情况下,可能是您编写的类,或任何其他类似Google Maps SDK)以及其他帮助程序和数据对象,这将使您的模型在内存和使另一个对象负责附加逻辑(更容易测试和维护),同时它也会将行为嵌入到模型中。
关于您的代码......
你不能保证设置者按照你想要的顺序执行(或者你不应该信任它总是这样做),所以,如果你想继续你已经拥有的代码,我会建议将$this->setCoordinates();
移动到其他位置,例如creating
,updating
和saving
等事件观察者:
https://laravel.com/docs/5.6/eloquent#events
每次调用时都会评估地址,如下所示:
public function setCoordinates()
{
$address = $this->attributes['address_line_1'] . '+' .
$this->attributes['address_line_2'] . '+' .
$this->attributes['address_line_3'] . '+' .
$this->attributes['address_line_4'] . '+' .
$this->attributes['postcode'];
$long_lat = new LongitudeLatitude();
$coords = $long_lat->get($address);
$this->attributes['longitude'] = $coords['longitude'];
$this->attributes['latitude'] = $coords['latitude'];
}
请注意,该方法是公共的,因此您可以从事件观察者调用它。
还有其他业务逻辑因素需要考虑:
- 你想给手动填充坐标的可能性吗?如果没有,您应该从$fillable
数组中删除它们。
- 每次更新任何地址字段时,您真的需要评估坐标吗?然后你可能想要一个status属性来验证坐标是否是原始的(在地址字段中setters将pristine设置为false,在坐标getter中检查值是否为null或者它是不是pristine,如果是,则设置再次坐标。)