我们找到 Laravel 的模型源码:

<?php

namespace Illuminate\Database\Eloquent;

use Exception;
use ArrayAccess;
use JsonSerializable;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\ConnectionResolverInterface as Resolver;

abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{

可以看到模型实现了 UrlRoutable 的接口,来看下这个接口的源码:

<?php

namespace Illuminate\Contracts\Routing;

interface UrlRoutable
{
    /**
     * Get the value of the model's route key.
     *
     * @return mixed
     */
    public function getRouteKey();

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName();

    /**
     * Retrieve the model for a bound value.
     *
     * @param  mixed  $value
     * @return \Illuminate\Database\Eloquent\Model|null
     */
    public function resolveRouteBinding($value);
}

有三个方法 getRouteKey() , getRouteKeyName()resolveRouteBinding() 。今天来分析下 getRouteKey() 方法的作用。我们来看下 Model 中对于 getRouteKey() 的实现:

public function getRouteKey()
    {
        return $this->getAttribute($this->getRouteKeyName());
    }
        
    public function getRouteKeyName()
    {
        return $this->getKeyName();
    }
        
        public function getKeyName()
    {
        return $this->primaryKey;
    }

上面的代码可以很明显的看到 getRouteKey() 的作用就是获取主键 ID 值,那么这个方法有什么作用呢?在哪里使用呢?这个其实从接口的名字就可以看出 UrlRoutable 意味着其使用场景在 url 生成的地方。再继续分析下去之前呢,我们来看下 route() 函数附带参数的写法:

route('post.edit', ['id' => $post->id]);
// ==
route('post.edit', $post);

上面两种写法的作用是一样的,而下面的写法就是接口 UrlRoutable 赋予的功能,我们找到 route() 函数背后的代码:

文件: Illuminate\Routing\UrlGenerator

public function route($name, $parameters = [], $absolute = true)
    {
        if (! is_null($route = $this->routes->getByName($name))) {
            return $this->toRoute($route, $parameters, $absolute);
        }

        throw new InvalidArgumentException("Route [{$name}] not defined.");
    }
        
        protected function toRoute($route, $parameters, $absolute)
    {
        return $this->routeUrl()->to(
            $route, $this->formatParameters($parameters), $absolute
        );
    }
        
        public function formatParameters($parameters)
    {
        $parameters = Arr::wrap($parameters);

        foreach ($parameters as $key => $parameter) {
            if ($parameter instanceof UrlRoutable) {
                $parameters[$key] = $parameter->getRouteKey();
            }
        }

        return $parameters;
    }

上面我摘取了这些函数调用的栈,从最后一个成员函数 formatParameters() 可以看出,当中的 instanceof UrlRoutable 语句在这里调用了,也就是在这里实现了 route() 函数参数传入数组可以传入模型也是可以的了。