Laravel使用Eloquent同步AD JSON用户数据的增改实现方法
Eloquent 实现AD用户全量同步方案
核心以extensionAttribute2(AD侧工号)作为本地用户表和AD数据的唯一匹配标识,全程使用User模型即可完成「删除冗余数据、新增缺失用户、更新变更字段」三步同步逻辑。
前置配置
- 打开
app/Models/User.php,将所有需要从AD同步的字段加入$fillable白名单,示例:
protected $fillable = [ 'name', 'email', 'extensionAttribute2', // 按需补充部门、手机号、职位等其他同步字段 ];
- 若使用批量upsert方案,需要给users表的
extensionAttribute2字段添加唯一索引,新建迁移执行以下代码即可:
Schema::table('users', function (Blueprint $table) { $table->integer('extensionAttribute2')->unique()->change(); });
完整同步代码
可直接替换原有逻辑,优化了原代码中ID数组构造的冗余操作,同时补齐新增、更新逻辑:
// 读取并清洗AD导出的JSON文件 $strJsonFileContents = file_get_contents(public_path('ADusers.json')); $bom = pack('H*','EFBBBF'); $strJsonFileContents = preg_replace("/^$bom/", '', $strJsonFileContents); $strJsonFileContents = stripslashes($strJsonFileContents); $strJsonFileContents = stripslashes($strJsonFileContents); $strJsonFileContents = str_replace('/', '', $strJsonFileContents); // 解析JSON为数组格式,方便后续操作 $adUsers = json_decode($strJsonFileContents, true); // 直接提取AD侧所有有效工号数组,省去原逻辑中implode后再explode的冗余步骤 $adEmpIds = array_filter(array_map(fn($user) => (int)($user['extensionAttribute2'] ?? 0), $adUsers)); // 1. 删除本地存在、但AD中已不存在的冗余用户 // 若模型开启软删除且需要硬删除冗余数据,可将delete()替换为forceDelete() $deleteCount = User::whereNotIn('extensionAttribute2', $adEmpIds)->delete(); // 2. 构造待同步的格式化数据,按本地表字段和AD返回字段做映射即可 $syncData = []; foreach ($adUsers as $adUser) { if (empty($adUser['extensionAttribute2'])) continue; // 过滤无效AD条目 $syncData[] = [ 'extensionAttribute2' => (int)$adUser['extensionAttribute2'], 'name' => $adUser['displayName'] ?? '', 'email' => $adUser['mail'] ?? '', // 按需补充其他同步字段 'created_at' => now(), 'updated_at' => now(), ]; } // 3. 批量执行新增/更新:匹配到对应工号则更新指定字段,匹配不到则新建记录 User::upsert( $syncData, ['extensionAttribute2'], // 唯一匹配字段 ['name', 'email', 'updated_at'] // 指定需要检测更新的字段列表,和上方构造的字段对应 );
小数据量可选方案
如果AD用户总量在千级以内,不需要追求批量写入性能,可以用更灵活的updateOrCreate逐行处理,无需提前创建唯一索引,支持在同步时加入自定义逻辑:
foreach ($adUsers as $adUser) { if (empty($adUser['extensionAttribute2'])) continue; User::updateOrCreate( ['extensionAttribute2' => (int)$adUser['extensionAttribute2']], [ 'name' => $adUser['displayName'] ?? '', 'email' => $adUser['mail'] ?? '', // 其他同步字段 ] ); }
注意事项
- 不要直接同步AD返回的密码字段到本地,除非确认AD导出的哈希规则和Laravel密码哈希兼容,否则会导致本地用户登录异常
- 若User模型开启软删除,查询冗余用户时可加上
->withTrashed()避免误判已软删的用户 - 建议同步前对AD数据做基础校验,过滤工号为空、邮箱格式非法的无效条目,减少同步报错
内容的提问来源于stack exchange,提问作者Sims Anderson
相关产品推荐
相关产品推荐

