我正在使用Laravel 5.5和SQLServer开发应用程序。我被要求创建一个“历史记录”表,在该表中我们跟踪UPDATE操作。例如,如果更新票证的描述,则会插入该字段的ID,字段,先前值和新值。
通常,这是通过数据库中的触发器完成的,因此我已经设置了after_update触发器。
现在,我的触发器有效,但是用Eloquent编写查询时无效。如果我使用模型使用的相同连接的PDO对象,则触发器将起作用。如果我在数据库界面中使用相同的连接编写查询,则它们将起作用。但是,如果我用Eloquent编写了相同的查询,则字段会更新,但是触发器不会触发。
我知道观察者的存在像触发器一样,我确实将它们设置为执行几乎相同的操作。但是,我不明白为什么触发器不起作用,并且我想知道这是正常现象还是我的设置在某种程度上有问题。
我在database.php文件中的连接如下所示(默认值已在此处删除):
'uti' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST'),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'prefix' => '',
'charset' => 'iso-8859-1',
'characterset' => 'iso-8859-1',
'collation' => 'French_CI_AS',
],
与触发器一起工作的代码:
use Illuminate\Support\Facades\DB;
$oPdo = DB::connection('uti')->getPdo();
$sQuery = $oPdo->prepare("
UPDATE TICKET SET
T_DESC = :sDesc
WHERE T_CODE = :iCode");
$sQuery->execute([':sDesc' => $sDesc, ':iCode' => $code]);
无法使用的代码:
$oTicket = Ticket::find($code);
$oTicket->T_DESC = $sDesc;
$oTicket->save();
触发器是这样的(表TICKET的每个字段都有更多的'IF UPDATE()'):
USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[after_update_ticket]
ON [dbo].[TICKET]
AFTER UPDATE
AS
BEGIN -- begin trigger
SET NOCOUNT ON
IF EXISTS (SELECT * FROM INSERTED) And EXISTS(SELECT * FROM DELETED)
-- Is an update --
BEGIN -- begin if update
DECLARE @user int = 1;
IF NOT UPDATE (MODIFICATION_DATE) AND NOT UPDATE (MODIFICATION_USER)
BEGIN -- begin if not update
-- If database connection user is letter + number, user id = number
IF (ISNUMERIC(SUBSTRING(USER_NAME(USER_ID (CURRENT_USER)),2, LEN(USER_NAME(USER_ID (CURRENT_USER)))))=1)
BEGIN
SET @user = SUBSTRING(USER_NAME(USER_ID (CURRENT_USER)),2, LEN(USER_NAME(USER_ID (CURRENT_USER))));
END
-- Update MODIFICATION date and user --
UPDATE [TICKET] SET
MODIFICATION_DATE = CURRENT_TIMESTAMP,
MODIFICATION_USER = @user
WHERE CODE = (SELECT T_CODE FROM inserted)
-- History trigger --
IF UPDATE(T_DESC)
BEGIN
INSERT INTO HISTORIQUE
(H_DATE,H_TABLE,H_FIELD,H_BEFORE,H_AFTER,H_CODE,CREATION_USER,CREATION_DATE)
VALUES
(CURRENT_TIMESTAMP,'TICKET','T_DESC',(SELECT T_DESC FROM deleted),(SELECT T_DESC FROM inserted),(SELECT T_CODE FROM inserted),@user,CURRENT_TIMESTAMP)
END
END -- end if no update
END -- end if update
END -- end trigger
我曾尝试研究laravel和eloquent的触发器,但是查看文档和一些stackoverflow问题并没有为我提供有关Eloquent触发器的预期行为的信息。我发现有些人是通过迁移手动创建的,因此我认为它们应该可以工作,但是我找不到帮助我的信息。
谢谢。
更新
Eloquent在字段更新时同时处理created_at和updated_at的自动 updating 方法。 (此处,updated_at定义为MODIFICATION_DATE
)。结果,只有一个查询被发送到数据库:
update [TICKET] set [T_DESC] = 'desc with eloquent', [MODIFICATION_DATE] = '2019-05-02 08:45:53' where [T_CODE] = 16770
由于我的IF NOT UPDATE (MODIFICATION_DATE)
语句在触发器中,因此阻止了它被触发。
我在票证模型中设置了public $timestamps = false;
,以使Laravel不会在updated_at上进行自动更新,并且触发器照常触发。