-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Introduce WellKnownTextConverter interface #2839
Conversation
* @author Benjamin Eberlei <kontakt@beberlei.de> | ||
* @since 2.0 | ||
*/ | ||
interface WellKnownTextConverter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first, I named that RequiresSqlConversion
, tell me what you prefer, or if you'd like something else. After reading this, I assumed conversion would always be to and from well know text, maybe it's wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like this name but don't have better proposal ATM, let's think about it...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah me neither :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where does "WellKnown" come from? I don't understand that interface name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all types extend the base Type
class, and it has default implementations for the conversion methods, why do we need an additional interface? The caller doesn't need to know if any conversion is happening within the type implementation, it can just call convert()
and let the type take care of the conversion.
I'm not an ORM user, so could you explain briefly what problem is being solved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SenseException Ctrl+F "well-know" in the link I gave
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@morozov this PR is pedantic; it does not solve any issue, it's just about architectural beauty: if you have a boolean method + methods that should be taken into account only if the boolean method returns true, it just begs to be rewritten with an interface. Note that this will make the Type
class less long with 3 methods that don't do anything removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But in any case, the caller should either call a method on the object to see if it implements the WKT representation, or check if it implements the interface? The second is even worse because it has to know about two interfaces (Type
and WKT
) instead of one (Type
).
Is it possible to avoid having the caller call this "marker" method at all and just expect it call the convert()
method instead?
I don't see beauty in making the Type interface smaller because there's still type-related logic which is implemented on the caller side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@morozov Please have a look at #2841, the motivation behind this should be clearer.
Basically it's just about killing Type
god object, splitting it into smaller pieces and also making consuming Type classes more lightweight (99% of types don't even need this typeof conversion at all, so why would they need to have dummy methods).
* | ||
* @return string | ||
*/ | ||
public function convertFromWellKnownTextSQL(string $sqlExpr, AbstractPlatform $platform): string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I deliberately picked other method names than in the old API, so that I could add type hinting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, since this is targeting 2.7 which will probably require PHP 7.2 (according to current policy of releasing for latest stable PHP), you could add parameter typehints without breaking public API. Not return type though, those could only be done later in 3.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the RC2 is released, so maybe the final release will come quite soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ETA @ end of november.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces between return types. The return types will stay in the interface, right? :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not return type though, those could only be done later in 3.0.
@SenseException not completely sure what @Majkl578 meant with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those methods are new, so my guess is, that type widening isn't relevant here and the interface's API with the return type can stay as it is. Return types aren't covered in type widening and he just mentioned that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return types will stay in the interface
Not in 2.x, adding return types to ancestors is a BC break, only parameter types are acceptable (and even those only as of PHP 7.2).
As I outlined on Slack, it may be easiest to just not add types at all now, just introduce the interface and add types later when master requires PHP 7.2+.
edit
Those methods are new
Of course, fine for new method names, my point was about original ones, sticking with without convertToDatabaseValueSQL without introducing new renamed methods.
@@ -305,6 +305,7 @@ public function canRequireSQLConversion() | |||
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform | |||
* | |||
* @return string | |||
* @deprecated implement WellKnownTextConverter::convertFromWellKnownTextSQL instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be removed in doctrine 3, along with the 2 other functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not implementing the new interface though, which is optional and is not needed for any of the native types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but existing types that do this type of conversion should implement it, if there are any (maybe not).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not find any in the codebase
1318862
to
6f72905
Compare
6f72905
to
c615861
Compare
ping |
* | ||
* @return string | ||
*/ | ||
public function convertFromWellKnownTextSQL(string $sqlExpr, AbstractPlatform $platform): string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, since this is targeting 2.7 which will probably require PHP 7.2 (according to current policy of releasing for latest stable PHP), you could add parameter typehints without breaking public API. Not return type though, those could only be done later in 3.0.
* @author Benjamin Eberlei <kontakt@beberlei.de> | ||
* @since 2.0 | ||
*/ | ||
interface WellKnownTextConverter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like this name but don't have better proposal ATM, let's think about it...
* | ||
* @author Roman Borschel <roman@code-factory.org> | ||
* @author Benjamin Eberlei <kontakt@beberlei.de> | ||
* @since 2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@since
and @author
should be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can trust git for this kind of things.
@@ -305,6 +305,7 @@ public function canRequireSQLConversion() | |||
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform | |||
* | |||
* @return string | |||
* @deprecated implement WellKnownTextConverter::convertFromWellKnownTextSQL instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but existing types that do this type of conversion should implement it, if there are any (maybe not).
* | ||
* @return string | ||
*/ | ||
public function convertToWellKnownTextSQL(string $sqlExpr, AbstractPlatform $platform): string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces between return types.
c615861
to
5213ef6
Compare
Rebased |
docs/en/reference/types.rst
Outdated
|
||
<<<<<<< HEAD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@greg0ire rebase introduced issues here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Damn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
5213ef6
to
4cc6d30
Compare
It removes the need for canRequireSqlConversion.
4cc6d30
to
ba55938
Compare
Does anyone have a better idea? |
Whatever the name is, I still don't like the idea of having a separate interface which the caller should check against.
But introduces the need for checking Currently, types only can convert values but cannot build SQL which is needed for some of them. Therefore, instead of just converting values, types should be responsible for building SQL overall: interface Type
{
function buildQuery(Query Builder $builder, $value);
}
class Integer implements Type
{
function buildQuery(Query Builder $builder, $value)
{
return $builder->createPositionalParameter($value, PDO::PARAM_INT);
}
}
class Point implements Type
{
function buildQuery(Query Builder $builder, $value)
{
return sprintf(
'Point(%s, %s)',
$builder->createPositionalParameter($value->x),
$builder->createPositionalParameter($value->y)
);
}
} With this approach, the consumer of the interface doesn't have to make any assumptions, it just delegates the logic of building type-specific query fragments to the type. Always. |
Conversion is not always needed, it's an optional feature, which is exactly what interfaces are for. If I understand well, you propose to get rid of the existing check altogether? I don't know the implications, but that sound like a bigger BC-break... |
O-kay…
It's not about whether somebody needs it or not, it's about what features constitute a type. If it turns out that depending on the type, SQL may be different, then it's up to the type to decide what exactly that SQL should look like (even if there's no additional SQL in most cases), not to the caller — whether it needs/wants to call SQL-specific methods on the type. Following your logic, the
Yes, I'm saying that the calling code shouldn't do any introspection (checking) on the type. I propose, as long as we're doing an API cleanup, introduce a cleaner and more consistent API. Otherwise, it's a replacement for one workaround with another. Yes, a marker interface is a bit better than checking if a method exists, but it's still the same from the caller's standpoint — it still needs to perform a check. The BC concern is secondary. If the new API is better for developers, they will be glad to migrate. |
Well, probably with better naming, but yeah, pretty much. At the moment it's not needed because as you said, only the String type has a length, so dbal/lib/Doctrine/DBAL/Types/Type.php Line 144 in 954ce2e
I find that cleaner than calling X methods that do nothing 90% of the time, and maybe you do too, but if seems you have other ideas in mind, like moving more logic from the caller to the type itself? That does sound like a good plan 🤔 especially if it allows to expose less methods publicly. Closing then. |
It removes the need for canRequireSqlConversion.
If you are ok with this, I will write a follow up PR on the ORM that will:
canRequireSQLConversion
,convertToDatabaseValueSQL
,convertToPHPValueSQL
. That would probably mean using reflection https://stackoverflow.com/a/17663347/353612