Laravel模型基础上增加before、after事件方法
Laravel模型基础上增加before、after事件方法
树懒在编码 发表于9个月前
Laravel模型基础上增加before、after事件方法
  • 发表于 9个月前
  • 阅读 13
  • 收藏 0
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

Laravel框架本身没有自带beforeSave、afterSave的方法事件,但是可以自行加上这些,类似Yii框架,本身就自带这些方法,这类方法就像一个事件、触发器,可以在模型save之前,做一些属性值改变或者更多逻辑补充。

列举一下可以增加哪些before/after事件方法

  • before/afterCreate() 
  • before/afterSave()
  • before/afterUpdate()
  • before/afterDelete()
  • before/afterValidate()

如何给Model增加这些方法呢?

首先要给所有model定义一个基类,然后所有model都继承这个基类,

<?php namespace libs\Eloquent;
abstract class Model extends \Illuminate\Database\Eloquent\Model {

}

定义基类之后,我们来看看 \Illuminate\Database\Eloquent\Model,既然要添加对模型的操作,还是得深入了解一下。找到boot方法,上面有注释

/**
	 * The "booting" method of the model.("引导"模型的方法)
	 *
	 * @return void
	 */
	protected static function boot()
	{
		$class = get_called_class();

		static::$mutatorCache[$class] = array();

		// Here we will extract all of the mutated attributes so that we can quickly
		// spin through them after we export models to their array form, which we
		// need to be fast. This will let us always know the attributes mutate.
          // 在这里我们将提取的所有变异属性,这样我们可以很快旋转通过他们出口模型后数组形式,我们需要快。这将让我们永远知道变异的属性。
		foreach (get_class_methods($class) as $method)
		{
			if (preg_match('/^get(.+)Attribute$/', $method, $matches))
			{
				if (static::$snakeAttributes) $matches[1] = snake_case($matches[1]);

				static::$mutatorCache[$class][] = lcfirst($matches[1]);
			}
		}

		static::bootTraits();
	}

那么可以从这里入手,在自己定义的基类上重写一下这个方法

/**
     * The "booting" method of the model.("引导"模型方法)
     * 覆盖之前/之后附加方法挂钩到模型事件。
     * @see \Illuminate\Database\Eloquent\Model::boot()
     * @return void
     */
    public static function boot() {
        parent::boot();
        $myself   = get_called_class();
        $hooks    = array('before' => 'ing', 'after' => 'ed');
        $radicals = array('sav', 'validat', 'creat', 'updat', 'delet');
        foreach ($radicals as $rad) {
            foreach ($hooks as $hook => $event) {
                $method = $hook.ucfirst($rad).'e';
                if (method_exists($myself, $method)) {
                    $eventMethod = $rad.$event;
                    self::$eventMethod(function($model) use ($method){
                        return $model->$method($model);
                    });
                }
            }
        }
    }

接着就是其他所有的model层,举个栗子

<?php namespace ifish\Model\Ad;

use libs\Eloquent\Model;
class Ad extends Model
{

    protected $table = 'ad_ad';

    protected $guarded = ['id'];

    public $timestamps = false;

    public function beforeCreate() {
        $this->channel = 'android';
        //或者不返回,因为只有一个布尔假将停止操作
        return true;
    }
}

只要调用create方法就会触发对应事件,例如

Ad::create($data);
//调用save必须在model内增加beforeSave或者afterSave
Ad::save($data);

之前在公司项目中,大量使用mysql触发器,遇到过的应该懂的,反正就一句话,不好维护,出问题了,不好定位,之后只能改造一下,把触发器都抽离,能用before/after就用,不用可以用观察者,反正怎么灵活怎么来。

原文地址:http://www.codinglee.com/103.html

共有 人打赏支持
粉丝 0
博文 2
码字总数 872
×
树懒在编码
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: