Warning: This page has not been updated in over over a year and may be outdated or deprecated.
videos:doctrine_migration
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | Last revisionBoth sides next revision | ||
videos:doctrine_migration [2023/03/17 11:08] – [Video Discussion: Doctrine Migration] demiankatz | videos:doctrine_migration [2023/03/20 16:43] – [Transcript] demiankatz | ||
---|---|---|---|
Line 11: | Line 11: | ||
// This is a raw, unprocessed transcript courtesy of YouTube. // | // This is a raw, unprocessed transcript courtesy of YouTube. // | ||
- | // Coming soon... // | + | so today I wanted to talk about uh a |
+ | project that's going to be a big part of | ||
+ | viewfind release 10 which is migration | ||
+ | to Doctrine as a new database | ||
+ | abstraction layer and in order to do | ||
+ | that I also wanted to provide a little | ||
+ | context about why viewfind uses a | ||
+ | database and how we currently interact | ||
+ | with the database so that some of the | ||
+ | changes that are coming up will be more | ||
+ | apparent | ||
+ | so first of all why does viewfind user | ||
+ | relational database at all we' | ||
+ | primarily interested in searching solar | ||
+ | or using external apis | ||
+ | so why database well because even though | ||
+ | viewfind relies on lots of external data | ||
+ | it does need to keep track of some | ||
+ | persistent things internally primarily | ||
+ | user accounts even if you're not using | ||
+ | the database as the primary source of | ||
+ | user data you know if you're using an | ||
+ | external authentication method viewfind | ||
+ | still has to keep track of users so that | ||
+ | it has something that it can associate | ||
+ | with user generated content which is | ||
+ | also stored in the database so things | ||
+ | like tags favorites comments Etc | ||
+ | uh we also use the database to track | ||
+ | search history | ||
+ | and there are some optional things that | ||
+ | we can use the database for like storing | ||
+ | sessions | ||
+ | or tracking record changes | ||
+ | um as you can see some of these things | ||
+ | are optional a lot of these things can | ||
+ | be disabled if you don't actually want | ||
+ | to track them in the database but there | ||
+ | are good useful reasons for having this | ||
+ | data if you find in many situations | ||
+ | so having established that we need a | ||
+ | database why use a database abstraction | ||
+ | layer there are a few of you a few | ||
+ | benefits for this | ||
+ | one is of course to protect against | ||
+ | vulnerabilities you know SQL injection | ||
+ | is a really common uh way of breaking | ||
+ | into sites and if you use an abstraction | ||
+ | layer that forces proper escaping and so | ||
+ | forth you're less likely to accidentally | ||
+ | leave some vulnerability somewhere | ||
+ | uh abstraction layers also make | ||
+ | cross-platform support a lot easier so | ||
+ | by using abstraction if you find is able | ||
+ | to support MySQL or postgres using the | ||
+ | same code that would be harder to do | ||
+ | without you know an extra layer in there | ||
+ | uh and it also ensures some consistency | ||
+ | of style or approach throughout the code | ||
+ | base because there are many ways to | ||
+ | interact with databases but if we pick | ||
+ | one particular way then code in one | ||
+ | place is more likely to look like code | ||
+ | in another place which makes everything | ||
+ | easier to maintain | ||
+ | so uh currently our database abstraction | ||
+ | layer is something called laminasdb | ||
+ | which used to be called zendb so why did | ||
+ | we choose this | ||
+ | well this was originally part of Zend | ||
+ | framework and when we converted | ||
+ | viewfinds code to use zenframework more | ||
+ | than a decade ago the PHP ecosystem was | ||
+ | a lot different and uh buying into a | ||
+ | framework was more about using that | ||
+ | framework for absolutely everything | ||
+ | because we hadn't yet gotten wonderful | ||
+ | things like composer and the current | ||
+ | ecosystem of packages | ||
+ | so labinos DB was selected largely | ||
+ | because it was there and it just was the | ||
+ | thing to use which is not to say that | ||
+ | it's a bad Library uh it of course | ||
+ | offered all the advantages of | ||
+ | abstraction layers that I already talked | ||
+ | about and it has a kind of neat | ||
+ | object-oriented query Builder that has | ||
+ | some benefits like making it possible to | ||
+ | extend a method that builds a query and | ||
+ | then inject parameters without having to | ||
+ | do crazy string manipulation | ||
+ | so you know laminas DB wasn't bad | ||
+ | so why are we talking about using | ||
+ | Doctrine now | ||
+ | well the big reason is that laminasdb is | ||
+ | no longer really being maintained and | ||
+ | the laminasdb community suggests you | ||
+ | should use doctors | ||
+ | and of course Doctrine is a library | ||
+ | that's been around for a very long time | ||
+ | it's widely adopted and it has good | ||
+ | support so it is a logical replacement | ||
+ | if we're going to have our existing | ||
+ | layer taken away from us | ||
+ | and of course it still offers all of the | ||
+ | advantages of using an abstraction layer | ||
+ | so let's talk about how viewfinds | ||
+ | current architecture with luminos DB is | ||
+ | set up | ||
+ | there are currently two types of classes | ||
+ | that manage interaction with the | ||
+ | database | ||
+ | there are what we call tabled gateways | ||
+ | which are you know classes representing | ||
+ | tables in the database so there' | ||
+ | one-to-one relationship between these | ||
+ | classes and the database tables | ||
+ | and the classes contain methods that are | ||
+ | used for fetching data from the database | ||
+ | and to some extent writing data back in | ||
+ | again | ||
+ | the table gateways are uh complemented | ||
+ | by row gateways which of course | ||
+ | represent rows in the database and these | ||
+ | also contain methods for reading and | ||
+ | writing data so a common pattern is that | ||
+ | you call a method on a table Gateway | ||
+ | that returns a set of row gateways back | ||
+ | to you and then you can manipulate these | ||
+ | Road gateways and each one has a save | ||
+ | method that you can use to write it back | ||
+ | into the database | ||
+ | some of our custom row gateways also | ||
+ | have methods that do all kinds of stuff | ||
+ | like pull related things from other | ||
+ | tables or whatever so there' | ||
+ | power but it's also a little bit | ||
+ | unstructured and potentially confusing | ||
+ | so I I wouldn' | ||
+ | strong design that we love | ||
+ | I already mentioned that query building | ||
+ | is done through a fluent object-oriented | ||
+ | interface which is kind of neat but also | ||
+ | sometimes kind of unreadable | ||
+ | um and the data that comes back uh | ||
+ | through the row gateways and table | ||
+ | gateways basically behaves like PHP | ||
+ | array objects which means that each data | ||
+ | element can be interacted with as if it | ||
+ | were an array or as if it was an object | ||
+ | more or less interchangeably which is | ||
+ | really convenient but also tends to | ||
+ | result in inconsistent code because we | ||
+ | have some templates that treat things as | ||
+ | arrays and some things that treat things | ||
+ | as objects and there' | ||
+ | primary reason to it so this is | ||
+ | something else we could stand to clean | ||
+ | up | ||
+ | so what am I proposing to change if we | ||
+ | switch to Doctrine | ||
+ | I still think we want to have two types | ||
+ | of database classes but I think there' | ||
+ | a a better division now | ||
+ | so instead of row and table gateways I | ||
+ | think we should have database Services a | ||
+ | database service is just a class that | ||
+ | contains logically related methods that | ||
+ | interact with the database and handle | ||
+ | all of the read and write functionality | ||
+ | so probably it makes sense to start off | ||
+ | with our database Services being more or | ||
+ | less equivalent to the table gateways in | ||
+ | the old code | ||
+ | but in this model we're no longer locked | ||
+ | in with the one-to-one correlation | ||
+ | between uh table and class so instead we | ||
+ | can think about things more logically | ||
+ | and we can have classes that handle | ||
+ | related functionality regardless of what | ||
+ | parts of the database it's interacting | ||
+ | with and I think that this will just be | ||
+ | a little bit cleaner in the long run | ||
+ | and instead of row gateways we have | ||
+ | entity classes which is a core part of | ||
+ | Doctrine so these represent table rows | ||
+ | just like the luminos DB Road gateways | ||
+ | do but | ||
+ | um they also contain annotations which | ||
+ | explain the structure of the database | ||
+ | this is a lot of how the doctrine | ||
+ | framework actually operates is that by | ||
+ | examining these entity classes and | ||
+ | looking at the annotations within them | ||
+ | it understands how to read and write the | ||
+ | database uh sort of somewhat magically | ||
+ | but | ||
+ | uh in any case | ||
+ | the entities are just there to represent | ||
+ | data and describe the structure of the | ||
+ | database but they do not contain | ||
+ | action-oriented methods you're not going | ||
+ | to save things to the database by | ||
+ | calling a method on an entity you' | ||
+ | going to pass an entity to a database | ||
+ | service and the service is going to do | ||
+ | that that work and I think that by | ||
+ | having a stricter separation of concerns | ||
+ | here | ||
+ | we'll end up with cleaner code | ||
+ | additionally a query building is done | ||
+ | through something called dql Doctrine | ||
+ | query language which is basically just | ||
+ | SQL except instead of table names you | ||
+ | put in the names of entity classes and | ||
+ | then the doctrine code Works its magic | ||
+ | to translate that into real SQL uh | ||
+ | there' | ||
+ | Builder that can generate dql so that | ||
+ | kind of uh thing is still an option but | ||
+ | I think we'll only use it when we need | ||
+ | to use it as opposed to all the time | ||
+ | because for simple things just writing a | ||
+ | little string of dql is probably more | ||
+ | straightforward and readable | ||
+ | and in the end all data is either going | ||
+ | to be represented with entity classes or | ||
+ | simple arrays no more array objects | ||
+ | which will make it much more clear how | ||
+ | to interact with the data in fact I'm | ||
+ | thinking we might consider | ||
+ | putting a two array method on all of our | ||
+ | entity classes so that everything can | ||
+ | just be treated as an array and then we | ||
+ | know what we're doing templates can be | ||
+ | more consistent we can use better typing | ||
+ | Etc | ||
+ | so advantages of migration I've already | ||
+ | talked about some of these as I've been | ||
+ | proposing the new structure but to | ||
+ | highlight a few more first of all we | ||
+ | have to do it at least we have to leave | ||
+ | laminasdb because it's at end of life we | ||
+ | can't stay there forever | ||
+ | um I think that switching to the idea of | ||
+ | uh database Services instead of table | ||
+ | gateways uh requires us to rewrite a lot | ||
+ | of code which lets us move away from | ||
+ | some very old early viewfind code that | ||
+ | we still have in place that's a little | ||
+ | bit more magical than I would like just | ||
+ | as one example all of our controllers | ||
+ | inherit a get table method which they | ||
+ | use to get access to table gateways and | ||
+ | it all happens with sort of low-level | ||
+ | calls to service managers and it's it's | ||
+ | just not very explicit | ||
+ | I'm hoping we can move to more | ||
+ | dependency injection that makes the | ||
+ | relationships between the parts of our | ||
+ | code more clear and easier to understand | ||
+ | as we're refactoring all of this | ||
+ | uh as I said before it's also an | ||
+ | opportunity to use more consistent data | ||
+ | representations in our templates | ||
+ | and I think this is an opportunity to | ||
+ | greatly increase our test coverage | ||
+ | because if we're using services to do | ||
+ | all of our reading and writing instead | ||
+ | of this sort of mix of doing some work | ||
+ | on row classes that come out of table | ||
+ | gateways and some work on the table | ||
+ | gateways themselves Etc it gets really | ||
+ | hard to Mock and simulate that but I | ||
+ | think we can come up with cleaner | ||
+ | interfaces that are easier to test and | ||
+ | that potentially could greatly increase | ||
+ | our project' | ||
+ | currently one of our greatest strengths | ||
+ | of course there are challenges to doing | ||
+ | all this in addition to advantages | ||
+ | the biggest being that this is a huge | ||
+ | volume of work we have a lot of database | ||
+ | code in viewfind even though viewfind is | ||
+ | not the most database driven of | ||
+ | applications so we're going to have to | ||
+ | rewrite a lot of code we're going to | ||
+ | have to test a lot of things it's going | ||
+ | to take time I'm hoping that the work | ||
+ | can also be distributed among a few | ||
+ | people because it's a lot for one person | ||
+ | to do | ||
+ | um additionally there are some Advanced | ||
+ | features that may be particularly tricky | ||
+ | uh you know for example the way that | ||
+ | right now the user login system those | ||
+ | user objects are tied up with user table | ||
+ | row gateways | ||
+ | there' | ||
+ | make sure that all works cleanly we also | ||
+ | have our database upgrader which is part | ||
+ | of the upgrade tool that automatically | ||
+ | examines the database schema and applies | ||
+ | changes to make it match uh viewfind' | ||
+ | latest released schema | ||
+ | that's using really low level luminos DB | ||
+ | stuff that may not have exact | ||
+ | equivalence in Doctrine maybe some work | ||
+ | though you know this challenge may also | ||
+ | be an opportunity because right now for | ||
+ | example the database upgrader is totally | ||
+ | linked to my SQL and postgres users have | ||
+ | to do things in a more manual way | ||
+ | perhaps we can use doctrine' | ||
+ | Library database abstraction layer to um | ||
+ | do some of the same things in a more | ||
+ | platform agnostic way that will require | ||
+ | some investigation | ||
+ | in any case uh that's sort of the high | ||
+ | level and maybe not so high level look | ||
+ | at uh what we have and what's coming | ||
+ | um I also have a link here to the pull | ||
+ | request which has some work in progress | ||
+ | on getting Doctrine to work and though | ||
+ | dharma' | ||
+ | working on uh making some progress on | ||
+ | that pull request | ||
+ | and of course you can contact me anytime | ||
+ | if you uh have any thoughts or questions | ||
+ | or concerns | ||
---- struct data ---- | ---- struct data ---- | ||
properties.Page Owner : | properties.Page Owner : | ||
---- | ---- | ||
videos/doctrine_migration.txt · Last modified: 2023/05/09 18:15 by crhallberg