Skip to content

Illuminate\Cache\Repository#put() type signature incompatible with Illuminate\Support\InteractsWithTime#parseDateInterval() leads to unexpected results #27160

@Ocramius

Description

@Ocramius
  • Laravel Version: master
  • PHP Version: irrelevant
  • Database Driver & Version: irrelevant

Description:

Following this trace:

/**
* Store an item in the cache.
*
* @param string $key
* @param mixed $value
* @param \DateTimeInterface|\DateInterval|float|int|null $minutes
* @return bool
*/
public function put($key, $value, $minutes = null)

Then reaching getMinutes:

public function put($key, $value, $minutes = null)
{
if (is_array($key)) {
$result = $this->putMany($key, $value);
return $result;
}
if (! is_null($minutes = $this->getMinutes($minutes))) {

Then parseDateInterval:

/**
* Calculate the number of minutes with the given duration.
*
* @param \DateTimeInterface|\DateInterval|float|int $duration
* @return float|int|null
*/
protected function getMinutes($duration)
{
$duration = $this->parseDateInterval($duration);

Which is defined as follows:

* If the given value is an interval, convert it to a DateTime instance.
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @return \DateTimeInterface|int
*/
protected function parseDateInterval($delay)
{
if ($delay instanceof DateInterval) {
$delay = Carbon::now()->add($delay);
}
return $delay;
}

There are some type issues here:

  1. Illuminate\Cache\Repository#put() has a possible null as TTL
  2. Illuminate\Cache\Repository#getMinutes() does not accept null as TTL, but can return null
  3. Illuminate\Support\InteractsWithTime#parseDateInterval() does not support null parameters

Besides being a type declaration issue, this leads to the weird side-effect of calling Illuminate\Cache\Repository#put('foo', 'bar', null) being valid, yet not producing a cache entry.

Another (worse) design issue is that Illuminate\Cache\Repository#put('foo', 'bar') (no third argument) is valid according to specification, but effectively dead/misleading code.

This is a design issue strictly related with #10504

Possible fixes

A possible fix is to:

  • introduce a deprecation warning for null being passed to the method
  • add a throwing assertion on the given parameter, so that the 5 supported types of CacheRepository::put() are checked
  • remove support for null in a major release (6.0)

The assertion is completely optional, as a type check in userland would suffice, but the interface is indeed too broad due to the type being too extensive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions