New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IntegerType returns unexpected results with UUID #12509
Comments
sdustinh, please include the CakePHP version number you are using in your description. It helps us debug your issue. -- |
We could change the check in |
|
How do you use both types interchangeably? |
@lorenzo URLs mostly. Super simple example to illustrate the point without detracting from the issue... I have records that were created with primary keys that have a UUID (or some other unique string) on them. Then there are printed labels that were intended to be consumed with a barcode scanner (inventory system). This lets me print out a label using a UUID which references a record which could be rotated out at some point in the future (e.g. A piece of hardware dies and needs to be swapped out). The scanner can always hit a single URL like The example initially reported by this issue is really specific to UUID but can be reproduced with any string that PHP would try to cast:
As the application grows and there are more integrations (e.g. Saltstack, customer APIs, developers in other departments, etc) which want to reference the same record in different ways: // DevicesTable.php
public function findDevice(Query $query, array $options = []): Query
{
return $query->where([
'OR' => [
[$this->aliasField('id IN') => (array)$options['device']],
[$this->aliasField('uuid IN') => (array)$options['device']],
[$this->aliasField('label IN') => (array)$options['device']],
[$this->aliasField('serial_number IN') => (array)$options['device']],
[$this->aliasField('ip_assignment IN') => (array)$options['device']],
],
]);
}
// DevicesController.php
public function search()
{
$queryParams = $this->request->getQueryParams();
$devices = $this->Devices->find('all', $queryParams)->limit(10);
$this->set('devices', $devices);
$this->set('_serialize', ['devices']);
}
// DeviceUuidMiddleware.php
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next): ResponseInterface
{
if ((bool)preg_match('^/\/devices\/' . Router::UUID . '/', $request->getRequestTarget()) !== false) {
$request = $this->replaceDeviceUuid($request); // /devices/6a88accf-a34e-4dd9-ade0-8d255ccaecbe -> /devices/1
}
return $next($request, $response);
} The application itself is only ever concerned with the primary key, but the device can be accessed using any of the other unique references to it in the same way as the primary key. |
The best we can do is to throw an exception, which by the looks of what you are doing, is definitely not what you want, as it would break your nice finder. |
Definitely throw the exception - that is what is best for the framework. My application should not dictate what is best for the framework. I'll handle relevant changes on my end. |
@sdustinh Any interest in putting together a pull request for this? |
@markstory Of course. Just the changes discussed? |
@markstory On the |
I went ahead and just piggy backed the |
This is a (multiple allowed):
I understand that this is arguably a bug, but in the course of legitimate usage it has caused some problems so I'm listing it as a bug for this issue. The IntegerType.php has a small but really annoying bug that pops up occasionally in my application and it a pain to track down every time. If you pass a UUID to query conditions where the field is an integer the
IntegerType
will convert the UUID to an integer and return unexpected results. Consider the following:In the above example, I use
toArray()
to illustrate the point butfirst()
would return the incorrect record as well. The following results are returned...This is a real example that has happened up at least 2 times in my application. What happens is when the UUID is converted to an integer by php - if the UUID happens to begin with an integer - PHP is returning numeric values to until it reaches non-numeric values.
This causes application code to return very unexpected results. It's actually so obscure that it makes writing a test to check for it very difficult, too. The first time it popped up I just fixed it and moved on, but it is starting to happen more when I want to use
id
anduuid
interchangeably.I haven't experienced it with any of the other database types, but I imagine this bug might present itself wherever a cast is being performed. For example using
on
oroff
in theBoolType
could be caught withfilter_var($value, FILTER_VALIDATE_BOOLEAN)
.If anyone else has this problem, hopefully you've used a finder because the solution can be a little verbose. Alternatively, you can extend the
IntegerType
and patch it yourself.The text was updated successfully, but these errors were encountered: