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

Laravel中如何每秒动态刷新Carbon生成的时间?

嗨,这个问题我在开发内容管理系统时也遇到过!Carbon 的 diffForHumans() 方法生成的人类可读时间确实很贴心,但它是服务器渲染阶段生成的静态文本,页面不刷新的话,自然不会自动更新。下面给你几个实用的解决方案,你可以根据自己的场景选择:


方案一:前端自行计算相对时间(推荐,无额外HTTP请求)

这个思路是把原始的时间戳/ISO时间存在页面元素的属性里,然后用 JavaScript 模拟 Carbon 的 diffForHumans() 逻辑,定时更新文本。优点是完全在前端处理,不用给后端加负担。

步骤:

  1. 渲染页面时存储原始时间:
    在输出时间的地方,把模型的 created_at 转换成 ISO 格式,存在元素的 data-timestamp 属性里,同时保留初始的 diffForHumans() 结果作为初始文本:

    <span class="time-ago" data-timestamp="{{ $post->created_at->toISOString() }}">
        {{ $post->created_at->diffForHumans() }}
    </span>
    
  2. 编写JS的相对时间计算函数:
    写一个函数来模拟 Carbon 的时间转换逻辑,处理“刚刚”“X分钟前”“X小时前”“昨天”等场景:

    function formatTimeAgo(timestamp) {
        const date = new Date(timestamp);
        const now = new Date();
        const diffMs = now - date;
        const diffSeconds = Math.floor(diffMs / 1000);
        const diffMinutes = Math.floor(diffSeconds / 60);
        const diffHours = Math.floor(diffMinutes / 60);
        const diffDays = Math.floor(diffHours / 24);
    
        // 匹配Carbon的输出逻辑
        if (diffSeconds < 60) return '刚刚';
        if (diffMinutes < 60) return `${diffMinutes}分钟前`;
        if (diffHours < 24) return `${diffHours}小时前`;
        if (diffDays === 1) return '昨天';
        if (diffDays < 30) return `${diffDays}天前`;
        // 更久的时间可以按月份/年份处理,根据需求扩展
        return date.toLocaleDateString();
    }
    
  3. 定时更新所有时间元素:
    页面加载时先更新一次,然后设置定时器(比如每分钟更新一次),确保时间动态变化:

    function updateAllTimeAgo() {
        document.querySelectorAll('.time-ago').forEach(el => {
            const timestamp = el.getAttribute('data-timestamp');
            el.textContent = formatTimeAgo(timestamp);
        });
    }
    
    // 页面初始化时执行
    document.addEventListener('DOMContentLoaded', () => {
        updateAllTimeAgo();
        // 每隔60秒更新一次,可根据需求调整间隔
        setInterval(updateAllTimeAgo, 60000);
    });
    

方案二:定时通过AJAX请求后端更新时间

如果不想自己写JS的时间逻辑,或者需要严格和后端 Carbon 的输出完全一致,可以用这个方法:定时向后端发送请求,获取最新的 diffForHumans() 结果。

步骤:

  1. 后端新增接口:
    比如在 Laravel 里新增一个路由和控制器方法,接收模型ID,返回对应的相对时间:

    // routes/web.php
    Route::get('/api/time-ago/{post}', function(\App\Models\Post $post) {
        return response()->json(['time' => $post->created_at->diffForHumans()]);
    });
    
  2. 前端定时请求更新:
    给时间元素加上模型ID的属性,然后定时请求接口更新文本:

    <span class="time-ago" data-post-id="{{ $post->id }}">
        {{ $post->created_at->diffForHumans() }}
    </span>
    
    function fetchAndUpdateTime(el, postId) {
        fetch(`/api/time-ago/${postId}`)
            .then(res => res.json())
            .then(data => {
                el.textContent = data.time;
            })
            .catch(err => console.error('更新时间失败:', err));
    }
    
    document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll('.time-ago').forEach(el => {
            const postId = el.getAttribute('data-post-id');
            // 初始加载
            fetchAndUpdateTime(el, postId);
            // 每分钟更新一次
            setInterval(() => fetchAndUpdateTime(el, postId), 60000);
        });
    });
    

    注意:如果页面里有大量内容,这个方法会产生较多HTTP请求,可能影响性能,适合内容不多的场景。


额外提示:前端框架场景下的简化处理

如果你用 Vue/React 这类框架开发,可以把时间处理逻辑封装成组件或过滤器,结合框架的生命周期和定时器来实现动态更新。比如在 Vue 里:

<template>
  <span>{{ timeAgo }}</span>
</template>

<script>
export default {
  props: ['timestamp'],
  data() {
    return {
      timeInterval: null
    }
  },
  computed: {
    timeAgo() {
      // 这里调用上面的formatTimeAgo函数
      return formatTimeAgo(this.timestamp);
    }
  },
  mounted() {
    this.timeInterval = setInterval(() => this.$forceUpdate(), 60000);
  },
  beforeUnmount() {
    clearInterval(this.timeInterval);
  }
}
</script>

内容的提问来源于stack exchange,提问作者Axel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:43:47