线上环境重置密码的邮件中的链接变成了 localhost

我做到这里, 本地环境测试的结果都是正常的. 但是线上环境重置密码的邮件中的链接变成了 localhost, 如图:file
我上一遍做的是 Laravel 5.5 的版本. 我又打开了上一遍做的线上版本, 测试结果是正常的. 如下图:
file
因为这一节的内容是发送邮件, 这个功能的逻辑是在框架中写好的, 我并没有做多余的修改.
我看了一些讨论, 邮件中的链接内容应该与 toMail 方法有关, 这是 toMail 方法的内容:

/**
 * Build the mail representation of the notification.
 *
 * @param  mixed  $notifiable
 * @return \Illuminate\Notifications\Messages\MailMessage
 */
public function toMail($notifiable)
{
    if (static::$toMailCallback) {
        return call_user_func(static::$toMailCallback, $notifiable, $this->token);
    }

    return (new MailMessage)
        ->subject(Lang::getFromJson('Reset Password Notification'))
        ->line(Lang::getFromJson('You are receiving this email because we received a password reset request for your account.'))
        ->action(Lang::getFromJson('Reset Password'), url(config('app.url').route('password.reset', $this->token, false)))
        ->line(Lang::getFromJson('If you did not request a password reset, no further action is required.'));
}

其中 ->action(Lang::getFromJson('Reset Password'), url(config('app.url').route('password.reset', $this->token, false))) 中的 config('app.url') 指的是 config/app.php 文件中的 'url' => env('APP_URL', 'http://localhost'),
.env 文件中: APP_URL=http://weibo.test

我不清楚具体是哪里的问题, 还是我遗漏了什么.

一切美好的事物都是曲折地接近自己的目标,一切笔直都是骗人的,所有真理都是弯曲的,时间本身就是一个圆圈。 —— 尼采《查拉图斯特拉如是说》
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
长日将尽
最佳答案

解决了! 原因是没有添加消息通知, 5.5的教程中是由消息通知的. 消息通知中重写了 toMail 方法, 如下:

public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('重置密码')
            ->line('这是一封密码重置邮件,如果是您本人操作,请点击以下按钮继续:')
            ->action('重置密码', url(route('password.reset', $this->token, false)))
            ->line('如果您并没有执行此操作,您可以选择忽略此邮件。');
    }

其中 url 指定了邮件中的链接, 使用了 路由 password.reseturl, 并且 route 方法的第三个参数 false 指定了url地址为相对地址, 因此邮件中的链接就是相对于项目地址的了. 即使在线上环境, 链接地址也是正确的.
如果没有重写 toMail 方法, 则发送邮件会调用 \vendor\laravel\framework\src\Illuminate\Auth\Notifications\ResetPassword.php 文件中的 toMail 方法, 就像我在问题中所表述的: 这个方法中的 url 指定的链接地址使用的是: config('app.url'), 也就是 config/app.php 文件中的 'url' . 参考 .env 文件中的内容, 最终指向的都是 localhost.
这份5.7的文档缺少了 消息通知 部分的内容, 还是添上比较好 @Summer

5年前 评论
讨论数量: 20
长日将尽

解决了! 原因是没有添加消息通知, 5.5的教程中是由消息通知的. 消息通知中重写了 toMail 方法, 如下:

public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('重置密码')
            ->line('这是一封密码重置邮件,如果是您本人操作,请点击以下按钮继续:')
            ->action('重置密码', url(route('password.reset', $this->token, false)))
            ->line('如果您并没有执行此操作,您可以选择忽略此邮件。');
    }

其中 url 指定了邮件中的链接, 使用了 路由 password.reseturl, 并且 route 方法的第三个参数 false 指定了url地址为相对地址, 因此邮件中的链接就是相对于项目地址的了. 即使在线上环境, 链接地址也是正确的.
如果没有重写 toMail 方法, 则发送邮件会调用 \vendor\laravel\framework\src\Illuminate\Auth\Notifications\ResetPassword.php 文件中的 toMail 方法, 就像我在问题中所表述的: 这个方法中的 url 指定的链接地址使用的是: config('app.url'), 也就是 config/app.php 文件中的 'url' . 参考 .env 文件中的内容, 最终指向的都是 localhost.
这份5.7的文档缺少了 消息通知 部分的内容, 还是添上比较好 @Summer

5年前 评论
长日将尽

解决了! 原因是没有添加消息通知, 5.5的教程中是由消息通知的. 消息通知中重写了 toMail 方法, 如下:

public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('重置密码')
            ->line('这是一封密码重置邮件,如果是您本人操作,请点击以下按钮继续:')
            ->action('重置密码', url(route('password.reset', $this->token, false)))
            ->line('如果您并没有执行此操作,您可以选择忽略此邮件。');
    }

其中 url 指定了邮件中的链接, 使用了 路由 password.reseturl, 并且 route 方法的第三个参数 false 指定了url地址为相对地址, 因此邮件中的链接就是相对于项目地址的了. 即使在线上环境, 链接地址也是正确的.
如果没有重写 toMail 方法, 则发送邮件会调用 \vendor\laravel\framework\src\Illuminate\Auth\Notifications\ResetPassword.php 文件中的 toMail 方法, 就像我在问题中所表述的: 这个方法中的 url 指定的链接地址使用的是: config('app.url'), 也就是 config/app.php 文件中的 'url' . 参考 .env 文件中的内容, 最终指向的都是 localhost.
这份5.7的文档缺少了 消息通知 部分的内容, 还是添上比较好 @Summer

5年前 评论

哥们,这文件在 /vendor 目录下,而 vendor 目录在提交时会被忽略(因为 .gitignore),如果在 .gitignore 文件中删掉 vendor ,提交时会报警告而且由于太大很慢我就中途 Ctrl+C 了,想问下改了你说的 toMail 方法后是怎么让它生效的,谢谢!

5年前 评论
长日将尽

@LewisC 我明白你的意思了。你确实提醒了我,我在这里说一下我的理解,我也是刚接触没多久,有什么问题欢迎指正。
首先,/vendor 目录确实添加到了 .gitignore 中,这应该是一种规范。该目录是用来存放 composer 依赖包的,但是提交到 git 的时候忽略它, 并不代表线上版本没有必要的依赖包,否则多少功能都没有了。
项目根目录下有一个 composer.jsoncomposer.lock 文件,后者是用来锁定版本的,而在 composer.json 中的指定的依赖会被 Composer 包管理器自动下载。其中就指定了:

"require": {
        "php": "^7.1.3",
        "fideloper/proxy": "^4.0",
        "laravel/framework": "5.7.*",
        "laravel/tinker": "^1.0",
        "overtrue/laravel-lang": "~3.0"
    },

require 表示在任何环境下都依赖的包,也就是说线上环境页依赖了这些包,其中就有 laravel/frameword,里面包含了 laravel 的源码。还记得使用 git push heroku master 推送到线上环境之后终端显示的一大堆 install 吗?那就是在下载线上环境的依赖包。如果你不确定,可以到你的 Heroku 项目页面查看以下:

file
点进去 查看编译日志

file

至于第二点,toMail 方法是如何调用的。我的理解是:toMail 以及消息通知类都是用来自定义消息模板的,也就是说实际上是已邮件的形式发送消息通知。具体的细节,我查看了源码,但是还没有理清。

5年前 评论

不好意思,我可能没有描述清楚我的问题。前面说的重写 toMail 方法应该就是把 vendor\laravel\framework\src\Illuminate\Auth\Notifications\ResetPassword.php 文件下的这行代码 ->action(Lang::getFromJson('Reset Password'), url(config('app.url').route('password.reset', $this->token, false)))中的 config('app.url').去掉就可以了吧,我想问的其实是去掉之后怎么让它在线上环境生效呢?我去掉之后即修改了 ResetPassword.php 文件,但 git commit 的时候说项目是最新的且提交的内容为空,那么 git push 自然也就对原先的版本没有改变,所以修改之后我线上的邮件链接依旧是 localhost ,也就是说我修改了 toMail 方法但它没有在线上环境生效。于是我想到 .gitignore 文件,去掉 vendor ,但提交时有很多警告,且由于 vendor 文件很大提交过程很慢于是我就中止了提交,后来捣鼓来捣鼓去项目都崩了,试过 git 回到以前的某个版本都没用(欲哭无泪),现在打算从头开始,但担心到这里的时候又卡住,所以问下你修改了 toMail 方法是怎么让它生效的,可以具体描述下过程吗,求解惑!

5年前 评论
长日将尽

@LewisC 你没有看明白的我回复。我的意思是:这个 vendor 确实被 ignore 了,提交到 git 上是没有的。但是真正的线上环境是有其中的一些依赖包以及 Laravel 框架的源码的。比如推送到 Heroku 上的时候是会根据 composer.json 文件来下载依赖的。你不应该直接在源码中修改,因为线上的环境是重新下载的源码文件,你的修改就没有了。所以应该添加消息通知,重写必要的类和方法。这样你推送到 git 上和 Heroku 上的代码都包含了你的这一部分修改。你在被 ignore 的文件中做修改,自然是无法在线上生效的。
你再看一下 5.5 版本的 9.3 节添加消息通知的内容。

5年前 评论

好的,我还没看过 5.5 版本的教程,多谢

5年前 评论

问题已解决,现在甚至已经学完了第二本,这个问题卡住我两天,在写回顾笔记的时候觉得得来感谢下你的回答哈哈!

5年前 评论
长日将尽

@LewisC 不用客气,我也只是个新手而已,第二本第一遍还没有学完呢。有什么问题一起讨论,共同进步,这就是社区的意义所在。

5年前 评论

改.env的APP_URL就可以了。

5年前 评论
长日将尽

@hustnzj 我又看了一下,还真的是。 5.5 版本的课程在创建应用的时候,没有修改 .env 文件中的 APP_URL ,但是 5.7 版本的在创建应用的时候就修改了的。是我粗心漏掉了,教程没少内容。:joy:

5年前 评论

所以5.7版本应该怎么修改?我也遇到了一样的问题

5年前 评论
长日将尽

@hustnzj 你好,我有一个疑问。 .env 文件是不被纳入版本管理的,那么线上环境应该也是没有这个文件的。也就是说推送到 Heroku 上是没有 .env 文件的,而且 .env.example 文件是 composer 生成的,里面的 APP_URL 的值是 http://localhost 。那么,Heroku 上是如何获取正确的 APP_URL 呢?因为如果是手动部署,需要复制 .env.example.env ,但是推送到 Heroku 上并没有执行这一步,是 Heroku 自动完成的吗?如果是,又如何查看呢?望解答,谢谢。

5年前 评论

Heroku也可以在线修改文件的

5年前 评论
长日将尽

@hustnzj 这个我是知道的。只是我印象中,教程没有在线修改过 APP_URL 。昨天这位朋友 @HeartThief 问我,我仔细想了一下,发现自己无法确定问题的源头,也无法确定到底需不需要添加消息通知。或许是隔了一段时间,有什么细节是我忘记了的。BTW,感谢你的回复。

5年前 评论

@bouc 问题我已经解决了,一开始已经修改了 APP_URL, 但是还是没有解决问题,后来根据你的思路看了5.5的教程,增加了定制消息通知文件这一步,最后重置密码的链接就正确了。所以我也怀疑是不是5.7版的教程少了这一块内容。

5年前 评论
长日将尽

@HeartThief :joy: 。明白了,隔了一段时间,我已经忘记具体是怎么回事了,感谢。

5年前 评论

@bouc 我是刚做5.7第一遍的萌新,恰好遇到这个问题于是在解决过程中看到你的解答。首先谢谢你和他人的解答,正是在你们的讨论中让我学习到了更多,所以我其实有个小小的建议,不需要在教程中加上消息通知,因为当某些人遇到同样问题的时候,自然会寻求答案,而这个过程其实也是编程进阶的一个过程。 :smirk:

5年前 评论

我也想说是不是你们 env 没改 :joy: :joy:

5年前 评论

请问.env文件怎么改啊?改成什么呢?

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!