You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel中JSON列操作:CV表多联系方式存储与视图回显

嘿,刚好我之前做过类似的多联系方式存储场景,给你一步步捋清楚怎么实现,分控制器处理提交和视图展示两部分来说:

一、控制器处理表单提交数据

首先,你需要先处理前端提交的phone[]和email[]数组,这里要注意过滤空值(避免用户留空输入框导致存空字符串到JSON里),然后直接存入JSON字段就行——Laravel对JSON列的支持很友好,直接传数组就会自动序列化,不用手动json_encode。

1. 先给模型加字段映射(关键!)

在你的Cv模型里添加$casts属性,这样从数据库取出数据时,JSON列会自动转成数组,不用每次手动解码:

// app/Models/Cv.php
class Cv extends Model
{
    use HasFactory;

    protected $fillable = [
        // 其他可填充字段...
        'phone',
        'email'
    ];

    protected $casts = [
        'phone' => 'array', // 自动把JSON转成数组
        'email' => 'array'
    ];
}

2. 控制器的存储/更新逻辑

以store方法为例,先做验证,再过滤空值,最后存入数据库:

// app/Http/Controllers/CvController.php
public function store(Request $request)
{
    // 验证提交的数据,手机号的正则可以根据你的需求调整
    $validated = $request->validate([
        'phone.*' => 'nullable|string|regex:/^1[3-9]\d{9}$/', // 国内手机号示例
        'email.*' => 'nullable|email',
        // 其他CV字段的验证规则...
    ]);

    // 过滤掉空的手机号和邮箱,只保留有内容的项
    $phones = array_filter($validated['phone'] ?? []);
    $emails = array_filter($validated['email'] ?? []);

    // 创建CV记录,直接传数组给JSON字段即可
    Cv::create([
        // 其他字段赋值...
        'phone' => $phones,
        'email' => $emails
    ]);

    return redirect()->route('cvs.index')->with('success', '简历创建成功');
}

如果是update方法,逻辑类似,把create换成update就行。

二、视图中检索展示数据

分两种场景:详情页展示,和编辑页回显并支持新增/删除输入框。

1. 详情页展示联系方式

因为模型加了$casts,$cv->phone和$cv->email直接是数组,循环展示即可:

<!-- resources/views/cvs/show.blade.php -->
<div class="contact-info">
    <h3>联系方式</h3>
    
    <div class="phones">
        <h4>手机号</h4>
        @if(count($cv->phone) > 0)
            <ul>
                @foreach($cv->phone as $phone)
                    <li>{{ $phone }}</li>
                @endforeach
            </ul>
        @else
            <p>暂无手机号</p>
        @endif
    </div>

    <div class="emails">
        <h4>邮箱</h4>
        @if(count($cv->email) > 0)
            <ul>
                @foreach($cv->email as $email)
                    <li>{{ $email }}</li>
                @endforeach
            </ul>
        @else
            <p>暂无邮箱</p>
        @endif
    </div>
</div>

2. 编辑页回显并支持动态添加/删除

这里要把已有的联系方式渲染成输入框,同时支持用户新增或删除输入框,用简单的JS就能实现:

<!-- resources/views/cvs/edit.blade.php -->
<div class="form-group">
    <label for="phones">手机号</label>
    <div class="phone-inputs">
        <!-- 回显已有的手机号 -->
        @foreach($cv->phone as $index => $phone)
            <div class="input-row">
                <input type="text" name="phone[]" value="{{ old('phone.'.$index, $phone) }}" class="form-control">
                <button type="button" class="btn btn-danger remove-btn">删除</button>
            </div>
        @endforeach
        <!-- 如果没有手机号,默认显示一个空输入框 -->
        @if(empty($cv->phone))
            <div class="input-row">
                <input type="text" name="phone[]" value="{{ old('phone.0') }}" class="form-control">
            </div>
        @endif
    </div>
    <button type="button" class="btn btn-secondary mt-2" id="add-phone">添加手机号</button>
</div>

<div class="form-group mt-4">
    <label for="emails">邮箱</label>
    <div class="email-inputs">
        @foreach($cv->email as $index => $email)
            <div class="input-row">
                <input type="text" name="email[]" value="{{ old('email.'.$index, $email) }}" class="form-control">
                <button type="button" class="btn btn-danger remove-btn">删除</button>
            </div>
        @endforeach
        @if(empty($cv->email))
            <div class="input-row">
                <input type="text" name="email[]" value="{{ old('email.0') }}" class="form-control">
            </div>
        @endif
    </div>
    <button type="button" class="btn btn-secondary mt-2" id="add-email">添加邮箱</button>
</div>

<!-- 动态添加/删除输入框的JS -->
<script>
// 通用的删除按钮逻辑
document.querySelectorAll('.remove-btn').forEach(btn => {
    btn.addEventListener('click', function() {
        this.parentElement.remove();
    });
});

// 添加手机号输入框
document.getElementById('add-phone').addEventListener('click', function() {
    const container = document.querySelector('.phone-inputs');
    const inputRow = document.createElement('div');
    inputRow.className = 'input-row mt-2';
    inputRow.innerHTML = `
        <input type="text" name="phone[]" class="form-control">
        <button type="button" class="btn btn-danger remove-btn ml-2">删除</button>
    `;
    container.appendChild(inputRow);
    // 给新添加的删除按钮绑定事件
    inputRow.querySelector('.remove-btn').addEventListener('click', function() {
        this.parentElement.remove();
    });
});

// 添加邮箱输入框(逻辑和手机号一致)
document.getElementById('add-email').addEventListener('click', function() {
    const container = document.querySelector('.email-inputs');
    const inputRow = document.createElement('div');
    inputRow.className = 'input-row mt-2';
    inputRow.innerHTML = `
        <input type="text" name="email[]" class="form-control">
        <button type="button" class="btn btn-danger remove-btn ml-2">删除</button>
    `;
    container.appendChild(inputRow);
    inputRow.querySelector('.remove-btn').addEventListener('click', function() {
        this.parentElement.remove();
    });
});
</script>
一些额外的小提示
  • 过滤空值的array_filter很重要,不然用户提交空输入框的话,JSON里会存空字符串,影响数据整洁
  • 如果需要对JSON列里的手机号/邮箱做查询,Laravel也支持,比如Cv::whereJsonContains('phone', '138xxxx1234')->get()
  • 验证规则里的nullable是必须的,因为允许单个输入框为空,但提交后会被过滤掉

内容的提问来源于stack exchange,提问作者priMo-ex3m

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:54:06