Referencing specific database records in your code

00:05.72
Chris Morrell
All right? welcome back to another episode of overengineered the podcast where we ask the very important question. What's the absolute best way to do things that don't really matter I'm Chris Morerell and I have my friends bogden karhenko and Skyler Katz back with me today. Um, continuing on the theme of what we're calling season 1 but with a little different twist. Welcome back guys.

00:31.76
Bogdan Kharchenko
Hello everybody and I will say Chris it's not exactly useless you know this does have a point I think we're we're doing the lord's work here.

00:31.98
Skyler Katz
Um, hello hello.

00:46.70
Chris Morrell
Ah, yeah I mean it's been. It's been really fun and I I do feel like at least for myself I've gotten some clarity on the way to approach certain things.

00:53.48
Bogdan Kharchenko
For sure for sure. Yeah I'm super excited to talk about the things that we have lined up for us today. So we'll see.

01:02.26
Chris Morrell
Yeah, so this is like this is kind of following on the topic of um, you know last couple episodes were data migrations or migrations schema migrations and how you manage your data around there and this is. Sort of related in that what we wanted to talk about today is um, you've got data in your database. You've got records in your database that you need to reference and code. Um and how you do that so to sort of set the stage. Um imagine ah that you're that there was this laircast. Ah, series that I was watching about building a stock tracker. Um, and so the idea was you know you want to track the playstation 5 stock at a bunch of different vendors. Um, and so we need a record in a vendors table for For example, best buy or maybe Amazon or. Trying to think ah I was going to say circuit city but I know circuit city hasn't existed for many years um and we need. We're also going to write you know, custom commands that will scrape those sites for stock and they need to be specific to that. Individual vendor because each site operates differently so the code in our codebase needs to understand ah specific records in the database and there are a bunch of different ways that we've approached it and each time.

02:34.48
Chris Morrell
I've always been like this feels not great, but it's fine. It works and that's the whole That's the whole theme of this show. So I thought it'd be a perfect thing to so to pick up so I guess maybe first let's just. Just run through some of the approaches that we have done and maybe what we what we don't like about them.

02:55.93
Skyler Katz
Yeah, that sounds great I Think let's see I've I've done things where you're just like find by slug and pass in the slug. Best Best dash by Um, which. Is okay except that maybe somebody doesn't do it by slu and does it by name somewhere else. So Then you're like fine by name. Best space by ah, we've also also done like ah constants on the on the vendor model so you like Vendor Colon Colon Best buy to Like. At least then it's it's kind of in code and can be renamed but it it always feels gross to to do that or like what if what if you don't have it in the database yet. Um and then and then what happens in ah in the code.

03:39.85
Chris Morrell
Yeah,, that's a big one every time I mean I think that that's really what always becomes the frustration for me is whatever solution you come up with is usually fine until you get to the testing story where the data doesn't necessarily exist yet. And that's you know that's sort of where it um dovetails in with our previous conversation because maybe um, maybe you have solved this problem a different way by having a perfect way to always have the data that you expect in your database.. Although you know. Still am not certain that that's not a pipe dream. Um, so I you know if you're in a scenario where you know your test your test database always has those records in it. Um. That's maybe not a problem but then you're dealing with the same issues of like do you want to seed a bunch of data that you're only going to need in certain tests. Um, but yeah, yeah I mean more recently I've used slugs in our codebase which has to account for a lot of legacy Data. We have. Done Plenty of just hard coding special Ids you know and maybe storing them in an enom. Ah that feels super gross and also becomes a problem with testing um and I know that you know for example, like sushi is a good. We talked about that a little bit I think on the last.

05:10.51
Chris Morrell
Last Maybe not but it it kind of came up around this idea of seeding databases like sushi is just a way to have ah or an array of of content that you can query through eloquent but I don't really feel like sushi works here because. It's a separate database Connection. You're not going to be able to do like you know where has on that relationship or you know it's It's always going to by design be isolated from the rest of your database. Um, and then like the other thing that I. Think is a really interesting approach I I don't know if it's I don't know if it always is solving exactly the same problem but in a bunch of places more recently? What? what? Ah I've found myself reaching for is actually you know storing the. Fully qualified class name of the class that handles that record in the database so instead of fetching the the um vendor in our code. We just fetch the vendor and and instantiate the object that is responsible for handling that vendor which you know in a lot of cases. You can You can probably do because you know for example for for our example instead of having like a custom best buy.

06:37.42
Chris Morrell
Command like a scrape best buy and scrape Amazon command that you run on a schedule you could just have a command that fetches all the vendors instantiates the scraper for that vendor based on the the class that's that's stored in the database and then. Execute the scraper. Um, but then you know you're kind of back to needing to um, move more logic into your database because then it's like oh well I want to scrape best buy every hour and I want to scrape Amazon every 15 minutes right so now do I have to go in and you know add ah some sort of timing info to the database so that I know how frequently each scraper needs to run. Um, you know the the more you move. Um.

07:34.48
Chris Morrell
What really ought to be done in code into to the database just there's a bunch of overhead associated with that. So I think it it can fall apart. Are there any other approaches that are missing.

07:43.40
Bogdan Kharchenko
Yeah I mean so I was going to comment I mean is kind of piggybacking on what Skyler mentioned is just having some sort of like enom class or like a bunch of constants that kind of reference you know so-called slugs right? So in this vendor example, we'll have like a best buy slug. And maybe Amazon and Target and so on in circuit city and you know like there's ah I think like I've done it. Ah both ways where you would go and say like give me you know you know this vendor buy this referenced enum and you can get that model out and then you can do whatever else you want to do with it. I think there is another kind of step um iteration of this is to use scopes. You know you could just have a scope that says best buy you know because it's very specific but you know you're still in the hard world a hardcoded world of things where you know you're passing a bunch of slugs around everything like that. So I think um, you know, ultimately what you were getting to Chris is having like a data base drivenven solution because otherwise even if you have you know some sort of handler. Um, it's still referencing some sort of class. Um. You know that will need to get nued up and something needs to happen. Um, but you know if you do have for example, these values like you alluded to having some sort of like timing like when should Amazon get Scraped. You know when should buszz bike get scraped and then we don't even need to know the concept of Amazon.

09:18.57
Bogdan Kharchenko
Or bus buy or circuit City like we just know that this is just data that's driven through a database. So I think that's probably the happy world. You know somehow? um in my mind.

09:33.96
Chris Morrell
Um, yeah I mean I don't know I guess I'm just not convinced because in a lot of cases then you're you know you're just dealing with having to add um you know add a bunch of junk to your model. That really should I don't know and my mind really should be code. Maybe maybe that's not true and and obviously there are cases where you know if you want this scrape timing to be configurable by the end user if you're like building this for a company and someone in the company needs to. Be able to adjust the scrape timing for for some reason then of course you're going to need to push that to the database anyway, um, and arguably you're going to want some sort of much more configuration-driven system in that case. Um. But even then it still needs to understand like how to scrape best buy because best buy is you know going to need to be scraped differently than Amazon you know it can't all I mean I guess you could have like some sort of wild like x-path based ah configuration in the database. But. I think that's again, kind of a pipe dream like you can't cover every scenario.

10:51.37
Bogdan Kharchenko
Yeah I I would agree I would agree I think like most of the time you would be dealing with like an Api right? You're not like going on their website and maybe doing some scraping and you know maybe there's api keys involved or even if it is scraping the website. Maybe you need to be logged in or something. So.

11:06.54
Chris Morrell
Right.

11:08.53
Bogdan Kharchenko
I totally get that there's like specific handlers for each vendor but it's almost like well if you have a job in a background that says like hey find me all of the vendors and I need to go you know scrape today you get the vendors. Back and you know then you can determine like okay well this slug is say Amazon like going back to like this constants idea. Ah you know like and this for Amazon you have to go you know new up this class and you know the benefit of that versus storing the actual class name is that. If you do refactor your code and move the class name around. You don't have to change the database entry you know because you have like a unique slug that references a vendor. Um, so I'm not saying everything has to be in a database I think ultimately it will still have to be like delegated to something but I think it's. Pretty reasonable to say that like hey you know I want to say for example, like turn scraping for Amazon off today. Ah you know and that has to be like a database configuration. So I think having another database configuration that says you know. Ah, what's the frequency of the scraping or whatever the situation is in the database is not too far fetched.

12:27.61
Chris Morrell
Um, oh Skyler we can't hear you um there you go.

12:30.84
Skyler Katz
And that's that's interesting. Ah apparently I muted myself in in the software. Ah I mean I was going to say like 1 1 potential approach is like I almost think of it as like a repository.

12:48.84
Skyler Katz
Of of like you have a best buy model and it just extends the vendor model but you can call like new best buy or best buy fetch or best buy get or something that that that's going to create the underlying eloquent. Record if it doesn't exist in the database yet. Maybe it's like first or create um and then you can work with your best by class but it is just a it's going to the return type is the is just the regular eloquent vendor model. Um.

13:23.55
Skyler Katz
And you're able to kind of like use that in the code.

13:27.52
Chris Morrell
Um, that's a that's actually I'm I'm constantly fascinated have have either of you used parental the the single table inheritance package I'm constantly interested in this idea and I've never really used it for anything.

13:42.27
Bogdan Kharchenko
I've heard of it I feel like I've looked at it hey even who trying to remember the name of it. So I'm glad that you remembered it Chris but I have parental parent.

13:46.53
Skyler Katz
I think does that a Titan package.

13:51.28
Chris Morrell
Um, yeah, yeah I know I know someone who uses it? um and it it solves some problems for them. But I think um, it's a little you know it's also adding some abstractions or.

14:07.99
Chris Morrell
I think you know my sense is that there are some rough edges I don't want to speak speak for that for it too much because I haven't had the experience with it. But um I feel like when I was sort of source diving I just looking at the code I got just worried that. As soon as you started to color outside the lines at all like if you're starting to do um you know, sort of more complex relational ah things where 1 or more of the models are using parental um, you know doing like the relation create method or something like that. I wasn't sure if it handled all those situations. Maybe it does but I do like conceptually this idea of um, you know having your vendor model and then having. Couple of specific implementations of the vendor model that get instantiated based on some criteria in the database. Um, because that it would be really nice to be able to say like when I care about it all I can just say like all I care is that this is a vendor. But in this this case I care that it's specifically the best buy vendor and that best buy vendor class and not only um, you know have its own identity but you could also implement custom functionality. That's just for that vendor I think that's pretty.

15:34.41
Chris Morrell
It's a neat idea. But I've never really exported that much.

15:37.40
Bogdan Kharchenko
Yeah I will agree I think you know now that you mentioned it I feel like that is actually a really good solution I think the the question is does this work in reality you know some of the things that I could think about like yeah, do you have like a default attribute on the best buy model. Ah, that extends the parent vendor model that like you know constrains it to the best buy slug more or less is that how it would work if essentially oh.

16:07.70
Skyler Katz
Um, and in my mind like it doesn't extend the actual eloquent model like maybe it extends some some interface that's like your vendor. Like your prefixed vendor like specific vendor that has just 1 method. That's like get or fetch or like whatever that is and it's going to just it's going to It's going to do the thing that's like get by slug best buy but it's in that 1 place and maybe it's like first or new so that if for some reason it's tet like in your test.

16:26.72
Bogdan Kharchenko
Osc.

16:30.98
Bogdan Kharchenko
Right? I see.

16:40.98
Skyler Katz
It's not you don't have to create it ahead of time. It's just going to create that on the fly. Um and everywhere else like you just can can like get that and that way you don't have to worry about oh man I'm overriding an eloquent method or I'm I'm doing something crazy like best buy.

16:48.39
Bogdan Kharchenko
So.

16:59.89
Skyler Katz
Ah, without scope and then like find slug target and you're like doing something crazy ridiculous in your code bases like this is just all it does is gets the the model and then your your return is your vendor model. You're not having to deal with with anything else.

17:18.50
Chris Morrell
Yeah, no I well I think that that's getting closer to to the solution that I've I've been leaning towards um before before we get down get sort of further down the this path though. Ah, the the one other thought that I had and this is probably an awful idea. But again we we have a bunch of cases where we have just literally hardcoded Ids um, and that's just because we're dealing with legacy data that already existed. And there is no slug column and for whatever reason, um, you know at the time the choice was made to just use the the hardcoded id and I and I think yeah I don't know. But anyway um, a part of me was like what if you just.

18:12.63
Chris Morrell
What if you just by default for a table where you knew this was going to be the case or maybe you just decided by default across the board you just in your initial migration set the auto increment value to a thousand or ten thousand or you know some some number where. You just reserve say the first 10000 ids to known hardcoded Ids right? So if you just set the auto increment to 10000 then any automatically generated records either if you're just seeding data for tests or if you're creating data data through like a crud interface. Um, the first record that you would create would be you know with id 10001 or whatever 10000 um, and.

19:06.15
Chris Morrell
Everything then you could just say like if I need ah to know that this one specific vendor exists I just hard code id one for that vendor and then I just know that vendor one is always going to be this one. You still kind of have to you. You still have to come to the same sort of first or create type solution. Um, but it does allow you to avoid having some sort of unique slug. Um I don't know if that's really beneficial I mean the performance. Improvement of doing like an integer based lookup is so minimal you know with an index slug column that it doesn't really matter. Um I just thought it was kind of an interesting idea.

19:56.81
Bogdan Kharchenko
So yeah, now it's is' definitely an interesting take I feel like we've all been there just reserve some ah you know, subset of I ideas in a database and you know then you can reference the id and then you know you have to make an entire podcast series to talk about why? That's a bad idea. Um i. I did want to piggyback on what Skyler mentioned as far as like having this repository per se I feel like on 1 hand I kind of like this idea. But I think in reality you know most of the time you're diving into like. A series of relationships right? You may be looking for something right? and you want to be able to say like well I want to get all the products that best buy has right? So it's like you know, give me all the products where has you know ah some sort of vendor of. The thing best buy and I feel like then you're going back to the place where you're just dumping a bunch of these um you know repository calls that say like just give me this give me this and I I still feel like going back to like more of a scope solution. Um, you know is more like elegant. Ah, rather than having another class because that way you could just say like well here's like the 5 or 10 vendors that we have and there's the scopes they exist you know and then that's just how you reference them so I don't know that's just my initial you know.

21:29.72
Bogdan Kharchenko
Thinking behind you know, just fetching 1 record, you know you know I feel like it's that's great when your data base is simple but I feel like once you have a very complex relation structure. It could get a little gnarly. You're going to have to like pass that stuff around. In different closures because you're going to pull it up initially and so on.

21:52.36
Chris Morrell
Um, yeah I mean so that so so there are 2 things that that makes me think of one is I think that this pattern particularly applies to um.

22:01.58
Skyler Katz
Is.

22:11.99
Chris Morrell
To to models that are almost singleton-ish in nature you know where? um, arguably ah you only need to load it from the database once for as many times as you would need it. That's not always the case and. Think a lot of times. Um, you know you can kind of shoot yourself in the foot by passing the same copy of a model around um and you know accidentally mutating something or loading. Loading a scoped relationship or something like that. But ah, you know there's a part of me that that thinks this type of this type of model you can um you could almost treat it as like something that you can resolve out of the container as a singleton right? and like. Even you know you could use the container as the mechanism for um, fetching it perhaps um and then yeah I mean the the the direction that I've been kind of leaning and we we have sort of a very naive version of this in the codebase now is this. This what we're calling directories where it's essentially just a ah class that knows about these special special records and ah and it just does sort of a first to create where it's looking for the record by slug and then it's creating it with.

23:46.50
Chris Morrell
Default data and that way everywhere in the code Base. You can just call the directory most of the time. It's just going to be loading the record from the database but from a test perspective. Um, you're loading it or you're you're creating it at the same time. Um, and you know that's kind of. Like what you were talking about Skyyler except for it's just a single you know single object responsible for fetching any different number of named items and I feel like there's an opportunity for um I you know I think that this is a place where there's an opportunity to.

24:14.26
Skyler Katz
Down.

24:23.99
Chris Morrell
Abstract this out into a package that handles a lot of the stuff that we are talking about because I can imagine sort of in this world like vendor colon col directory ah arrow best buy and that gives you some sort of object that you can then. Either get a singleton instance of best buy right? If you just want to have that vendor and you you know, know that you're just you're kind of going to treat it as a read-only um, model. Ah, you could call get maybe on it to get a new copy of that that. Particular model and both both of those under the hood would do a first or create. Um, but then I imagine a way where you could essentially have some helper functions on that that object where you could pass in a builder and have it add constraints to that builder. Um, and maybe even through some like macros um or some like some of the automated hooks that eloquent gives you you might even be able to sort of have magic dynamic scopes for any of those named. Um. Name directory items I feel like that like in my mind, there's a way to do this I don't know if there are any major roadblocks for it. But I I like that idea of having just like a single place that's responsible for um, anything that can be mutated and then you know like.

25:59.97
Chris Morrell
I'm going in there and changing the slug in my directory I need to also create a migration or something that's going to update the slug in the database if there's a chance that that model already exists with the old slug. You know like it gives you sort of this one point of. Control over that that connection between the database and the codebase.

26:24.47
Skyler Katz
Yeah I mean that's it's an interesting It's an interesting approach I feel like there's like you know we I feel like ah the approach that I was I was taking and even the directory approach is like how do I get this one model specifically. And then Bogdan's bringing up this approach of like well I I need to like query off of a specific model and I don't know that the the repository situation that I was recommending like doesn't really solve for that. It only solves for like resolving this one model out of the database like for for onetime use.

26:58.89
Chris Morrell
Yeah.

27:00.66
Skyler Katz
I Think the directory like it. It has the ability to to yeah like add on the builder and create more dynamic relationships I Also think when you're in a situation where you're pulling in a lot of different data and doing a lot of queries like maybe it makes sense to go back to like. Hard coding the slug or it's probably dynamic in nature Anyways, like someone is requesting from the Ui like something specific so you have the id or the slug already from some form field and you don't need the like.

27:33.24
Chris Morrell
I guess.

27:36.34
Skyler Katz
In code specific instance.

27:38.20
Chris Morrell
I Think I think there are lots of cases I don't know I've already certainly excuse me I've come across cases where you you know you want to add that constraint right? even in I don't know. In that scraper example I can imagine Perhaps the um you know the best buyscraper is going to want to fetch all the um, all the prices that are related to the best buy vendor right? So it's going to want to do like select from. Prices where vendor Id equals and and like get a number. Um and so being able to do something where you like do you know?? Ah prices.

28:35.18
Chris Morrell
Ah, related to directory or whatever you know and and that's like a macro that then you just pass in this directory item. Um, and let that be responsible for understanding how to add the like wherein or where constraint. Um.

28:49.27
Skyler Katz
This is.

28:54.50
Chris Morrell
I can imagine there are a lot of places where you'd still want to do that.

28:59.52
Bogdan Kharchenko
So yeah I will also say like I think there's ah probably a few points like 1 Ah, you know we need to like query this data I feel like the other piece of it is also just having a reference to the idea of best buy right? It's kind of like maybe in even in in your ui.

29:13.44
Chris Morrell
Yeah.

29:16.92
Bogdan Kharchenko
Or even in that scraper you may want to like show something sparkly next to the best buy for the best buy vendor. Um, so I feel like just you know, ah that use case of pulling 1 item out is still you know valid you know I don't think it's you know it's not dismissed by like the scope idea or anything like that I think. Um, that is probably 90% of the use case is that let me find best buy so that way I can go and present. You know this best buy so or use the best buy scraper or whatever the case is um yeah I'm not. Dismissing those ideas at all.

29:55.76
Chris Morrell
Um, I yeah I think there are lots of cases where you may you know you may have like to that point hardcoded ui that's like there's a best buy tab at the top of the screen and maybe you know maybe your system's. Can scrape 15 different services but you know that mostly you care about these 3 vendors because those are the big ones and so like in your ui you want to show like a best buy tab that has like a timestamp of the last scrape and maybe the number of records. And like you want to have you know you want to have four tabs 1 for best buy 1 for Amazon 1 for circuit city of course and then the fourth that's just like all other vendors and that's something that sure you could build a whole database schema around like you know, featured vendors or like. You know have like an is featured flag on a vendor and dynamically build those things but like a lot of times I don't know to me that just often feels like um, you're adding a bunch of junk to the database. Just. Because you where you would have usually just you know, added 3 tabs to to the ui you know what? I mean. Um, and so to be able to just set say like quickly you know, give me the latest.

31:29.88
Chris Morrell
Ah, run for these 3 vendors and then give me you know a sum for all vendors that aren't these 3 vendors in in the controller and then just hardcode that ui and that way if I want to show the the best buy tab with like the branded blue and the Amazon tab with the branded yellow like. Don't have to then go into my database and add a vendor highlight color and vendor text color and you know like and and obviously all of that's contextual because you may have you may have an app where you do want those things but I'm kind of talking about the times when you don't right when you you. You need it but you don't you don't need it to be super configurable.

32:15.70
Bogdan Kharchenko
Yeah I feel like you know, ah you make a good point about like just the context of things right? Even this idea of you know should we use like constants you know in 3 places to determine. What is best buy or Amazon or circuit city or do we build like this very very complex. Ah, you know system you know some sort of um, directory structure or like the parental or user parental package. You know I think it all you know, um, does always come back to like you know what is kind of I think the best bang for the buck right? and. And I really feel like you know if if you do need custom colors. You're going to. You know have a lot more database tables than just you know whether or not this thing should run at a certain time. You know those are kind of like just very small little. Peanuts comparing to what you're actually dealing with but yeah I still think you know having like a good data basee driven solution is probably the most optimal way of doing this rather than um. You know, ah kind of ah going back to my like initial point where I made a beginning of the podcast kind of you know how can you like if we were to really over engineer this. How can you make it so that your app doesn't really have any understanding of.

33:45.99
Bogdan Kharchenko
You know what is best buy aside from kind of like some of the custom logic that does the scraping or the api stuff but you know a lot of this stuff needs to be configurable. Um, you know that's my position at least because that way you know? Ah, if there is a code change. Where you're like well we don't want to present Best buy on this tab. You know it's a configuration change in the database and it's you know something that is a no code solution Effectively once you deploy it. So.

34:19.90
Chris Morrell
Um, okay I just had a thought like I I wonder if we can combine the best of of sort of both worlds here. Um in that.

34:29.38
Bogdan Kharchenko
M.

34:36.57
Chris Morrell
if if I have um if I have a trait that I can attach to any class that basically designates that class as being tied to a database model somewhere right? Um, and. That trait just exposes a few of the functions so kind of going back to what Skyler was saying instead of having this single directory that um has lookups for um, a bunch of different things. You'd you'd create individual classes for each of the things that you want to want to look up. Um, but each one of those classes. Really just um, you know pulls in a trait and by default what that trait would do is essentially do a first or create on. Um, where.

35:33.86
Chris Morrell
Some column name equals this This object's fully qualified class name and then you'd have a inverse of that that is a cast right? So um, you know, maybe by Default. We've used the term. We've used the the name handler a bunch So I'm just going to say let's call it handler. Um, so by default if I have a vendor model I could add a handler column to it right? and the handler column I would just do um, a. Ah, what's it called a you know a custom cast for that column that ah handles all the the instantiating the correct version of the handler and and making sure that the class name actually um, implements the. The methods or the interface or you know, whatever all the validation and stuff around that. So if I pull the best buy vendor I can just do best Buy Arrow handler and that gives me this like best buy class which can have a bunch of vendor specific specific custom methods on it. But at the same time I can just do that. You know that best by class Colon Colon Singleton and that will check to see if there is and or or I guess I mean we could even you could just.

37:04.52
Chris Morrell
Implement them as singleton's in the container. So like I could just do app best buy class and then um on that class I can get a copy of the best buy model from it I can get a shared instance of the best buy model. So if I want to you know because i. I know um I know in some cases and I don't want to talk too much about like the specifics because it's like a private codebase but like I know of ah someone's codebase where you know they have this vendor concept and it's very central and they may need to. Have a reference to that vendor in like 10 different places during a single request right? So you don't want to load that vendor. You don't do a you don't want to do it first or create 10 times for that single vendor when. All you're using it for is to get the id you know and the display name or whatever. Um, so I do think you want that concept but I could see I could see sort of having this like fully qualified class name in the database. Um, which you know I don't. I don't think I buy your concern there Bodin because like we already do that you know with polymorphics so much like renaming a model is just you know it's like a thing that you have to take into account. So if you ever wanted to rename one of these handlers.

38:39.57
Chris Morrell
You just have to know that you it has to go you know hand in hand with a migration or something like that I think that's just the reality. Yep yep, yep exactly.

38:46.20
Skyler Katz
You could also implement a morph map situation to ah again though, if you decide to change the the Morph map then you've got to change stuff in the database like I don't.

38:46.70
Bogdan Kharchenko
Right? Yeah, it's a good solution. Yeah.

39:00.15
Chris Morrell
Yeah, ah eventually when you have to change something you have to like renaming models is fraught right? It's just is a tricky thing and um, you know there are tricks we have I know we have that. Um. Command that like scans the entire database for polymorphics and can check it against the Morph map and make sure there's no stray things with old names but like it's it's scary to run that.

39:28.66
Bogdan Kharchenko
Yeah I mean you know I'm not saying that it's not doable or there isn't a way to prevent it I just feel like it's another layer of you know you know you deploy it. It's all fine and then in a year or 2 You're like oh no I'm going to restruct rearchitect. My. Folder structure right? Ah, the good old folder structure and now of a sudden you know it becomes you know like um, an undertaking to move a class from one directory to another. Um, you know so it's ah you know it's just like another thing. Well how can you kind of minimize some of the risk long-term.

39:56.70
Chris Morrell
Yeah, no I get that.

40:04.86
Skyler Katz
I mean I think you could call you know you could call the handler like you could call handler and the cast could like look up the the like known directory of where the handlers are and if 1 exists with the name of the mob like there's waste to.

40:06.70
Bogdan Kharchenko
But going back to.

40:19.61
Bogdan Kharchenko
I Guess yeah.

40:23.18
Chris Morrell
Or you could even have the handler I mean you could just have like a a property on the handler That's like old names you know and it could just do a you know? ah instead of then it would just do a.

40:23.86
Skyler Katz
To do it dynamically.

40:41.14
Chris Morrell
Ah, wear in you know and it could still do. It could still be I think it would still. It could still be pretty performant because it could just do like where slug equals or wear slug in and that way if there is a match on if there's a direct hit on the current.

40:41.57
Bogdan Kharchenko
E.

41:00.12
Chris Morrell
Slug then? um, yeah yeah.

41:02.76
Bogdan Kharchenko
Right? Yeah I'm sure there's a way to figure it out I did want to ah circle back about this singleton idea and you know this code base that's private. You know what is kind of the current solution you know and maybe that's a good way to kind of um. You know, like how does this problem get solved today and um, you know what would be you know, maybe the singleton idea is something viable for you know this example that you mentioned.

41:32.25
Chris Morrell
I I think in in that code bases. There's just ah, there's like a config vial with a bunch of Ids I think that that's and then um, those and then that those are just you know there's some sort of.

41:38.10
Bogdan Kharchenko
Oh I see.

41:48.12
Chris Morrell
Helper function to either just return the already fetched copy for that Id or fetch it fresh if there isn't a copy for that request I think that's how it's done I'm not entirely sure, but it's something like that I know it's I know it's using Hardcoded ids.

41:56.14
Bogdan Kharchenko
I see okay I see interesting. yeah um yeah I mean there is I suppose another world of you know, just using a instead of hitting the database all the time. Maybe it's like some sort of. Cache mechanism where you know this stuff just gets loaded into um you know Redis or you know some other store and which is a lot more performant and you know just has like.

42:16.67
Chris Morrell
Right.

42:29.83
Bogdan Kharchenko
You know bare minimum information such as Id slog and you know display name that you use commonly and that's just what you interact with maybe that's also like a solution to this? yeah.

42:35.39
Chris Morrell
Right.

42:43.32
Chris Morrell
Um, yeah I mean I think yeah yeah I mean and of course then you're you know you're dealing with the downsides of cash too. But I I definitely think I mean I think if if if we were doing this as a package I would definitely.

42:52.51
Bogdan Kharchenko
Sure sure.

43:01.26
Chris Morrell
Imagine that you would have some sort of caching mechanism that was an option where um, you know it was just like configurable and then um, yeah, you would just add some sort of model hooks to to clear the cache whenever a new. New record was saved. Um, potentially you wouldn't even necessarily have to do that in this case but um.

43:25.50
Skyler Katz
I Mean you could just do like a request a request cache where it's just like an array of data that's being cached and then the request ends and it's gone.

43:34.74
Chris Morrell
Right? You only fetch it right? You just fetch it once for the entire request. Yeah yeah, because actually going back. The the reason that the config file with Hardcoded Ids Works is most of the cases.

43:37.60
Bogdan Kharchenko
Or.

43:41.20
Skyler Katz
Muslims.

43:52.48
Chris Morrell
You just need the primary key to do other queries like I think a lot of the times you're just doing like you know, give me all the prices for best buy or you know give me the crawl history for best buy right? like. And so just having the primary key and understanding. It is enough. You don't actually have to pull the best buy record from the database if you just know what the primary key is um, you only kind of need that singleton concept. If. You want to pull it from the database first before you do that that query so that you don't have the hard code Ids anywhere.

44:35.63
Skyler Katz
So what? if this got crazy idea so like some this this handler approach and there's some. There's some method that's like primary key and then there's a that's going to return the primary key and.

44:38.79
Chris Morrell
I Love it already.

44:53.30
Chris Morrell
Yep.

44:54.88
Skyler Katz
Ah there's a command that you run when you deploy that's going to to like do the crazy lookup to like of all of the things to get the primary keys and then basically like store it in some cache. And so every time you call primary key like it's not having to do a database query. It's just returning the thing that already exists like maybe maybe it's writing everything to a to a just like a Json config file or maybe it's pushing it to redis but um, like. The primary key method is going to pull it out of the cache that the command runs on deploy. Um, and that way like if the id is different in your local environment. You just run the run the command to populate the primary keys.

45:38.20
Chris Morrell
The.

45:48.87
Skyler Katz
Doesn't really matter which environment it's in and then you you always have your your primary I don't know if that makes sense.

45:52.77
Chris Morrell
The only problem with that I mean I think that the problem with that is it like what happens if I add a new vendor between deploys.

46:03.97
Skyler Katz
I Mean maybe there's some. There's some observer model event that's going to like cue off the job to re calculate it I mean I guess like if something is is important enough to be.

46:13.43
Chris Morrell
Um, well it doesn't matter right.

46:19.58
Skyler Katz
Something's important enough to be a vendor that has all this special code then you can't really just add something to the database like this is a special thing. You've got to push code out. So.

46:24.72
Chris Morrell
Um, that's exactly what I was Yeah, yeah, yeah, yeah, you're never like the nature of this problem is such that That's never going to be an issue right? You're never.

46:35.52
Skyler Katz
Yes.

46:38.39
Chris Morrell
If you're adding a new vendor that needs to be referenced in code you're you're by definition doing a new deploy. There's no, there's no way.

46:45.87
Skyler Katz
Yeah, you're you're probably adding this record in a migration or a cedar or wherever based off the last 2 episodes you you put it? Yeah, so yeah.

46:55.45
Chris Morrell
Um, or a dragon bite actions or whatever it is. Yeah yeah I mean I I like that just.

47:02.95
Skyler Katz
I Don't know that's ah interesting.

47:09.59
Chris Morrell
Because then your criteria you can use slug. You can use name you can use whatever that you can use some fully quite qualified class name. Um, but essentially you know it could. It could be the type of thing where I'll even know you know I guess using the cache you could just.

47:29.00
Chris Morrell
Have the primary key method look it up in the cache and then you could have a command that warmed the cache and if you don't run the command. It just does it once and then stores it in the cache. But um.

47:47.43
Chris Morrell
Otherwise you know that would just become sort of like an optimization just like you know root cache and and view. You know all all those all those artisan commands that are just for sort of production optimization. That would let you cache all those ids once on deploy. But if you don't do it. It's fine. It would just still do the that first or create one time. The first time you need one of those records in code I like that.

48:19.37
Bogdan Kharchenko
Yeah, that's pretty decent solution. So where do we come from. We started at writing strings straight up in queries to constants to scopes ah to what is the final solution. What what are we thinking.

48:38.58
Bogdan Kharchenko
Is like a really good hands hands-on approach without over over complicating it? Yes, ah.

48:43.12
Chris Morrell
Um, without over-engineering it.

48:47.92
Chris Morrell
Um, I really like the idea of some some object that you know has a bunch of a sort of generic helper functionality around the common use cases. Getting or getting it a copy of the model getting a singleton copy of the model gain the primary key and um foreign key name for the model probably as well as applying the model's constraint in a. Belongs to and has type both you know both sides of the relationship right? So you would be able to just sort of transparently pass a query builder into it and say like add a belongs to constraint to this query builder for this thing. And it would it would then be able to transparently add like where vendor id equals 3 right? or um I mean I guess it's only that side of the relationship that you'd have to.

50:01.47
Skyler Katz
Like you know, like best buy with prices get and like it's going to know it's going to know to be able to do that without executing two queries.

50:03.14
Chris Morrell
Have to worry about.

50:07.40
Chris Morrell
Right.

50:15.58
Chris Morrell
Right? right? Yeah, well it would still execute without executing three queries and still execute the best by well no I Guess if it's a singleton you yeah um.

50:26.12
Skyler Katz
If it. Yeah, if it doesn't exist I think that would necessitate multiple queries. But.

50:33.99
Chris Morrell
Right? Um, and yeah I mean that it seems you know it would take a little bit of time to get it. Get the more complex sides of that right? but it feels to me like you could. You know because models let you um you know Boot Arbitrary Logic um from a trait right? So you could just have it a trait that you could drop on any model that would um. Handle like sort of dynamically setting up scopes for you. So then you could still ah, kind of just automate your your ah scenario of like vendor Colon Colon Best Buy and that would just. Set up the query builder and you could you could publish a ah ah custom caster for the the if you wanted to connect it by like the fully qualified class name in the database. But if you didn't want to. You could just override like the attribute value on this thing to be slug or Id or whatever you wanted and that just becomes the lookup table or the Lookup value. Um.

52:00.59
Chris Morrell
And that seems like it covers everything that we've kind of talked about doesn't it.

52:03.75
Skyler Katz
I Think so.

52:07.90
Bogdan Kharchenko
Is it doable? Yes, Okay, because yeah I feel I mean it's ah it's great to talk about it and concept I feel like you know it's It's nice but I feel like and maybe this is a challenge to some of our listeners like is it possible to create this.

52:07.96
Chris Morrell
I Think it's doable.

52:09.57
Skyler Katz
I Think so.

52:25.25
Bogdan Kharchenko
Ah, you know thing that is a package that you could just somehow expose some of these methods and you know use them. You know, share it with people like I don't know is is that too much to ask for.

52:40.45
Chris Morrell
Um, I mean also I'd be curious to know if this is like is this a common problem for lots of people or um, is it just like a problem that like due to the nature of the of what we work on comes up more often.

52:57.62
Chris Morrell
I Think it's a common problem but I don't know.

52:59.59
Skyler Katz
I mean I've I've run into this in legacy apps that that aren't like non lairravell apps that we're trying to like pull into larave or just it's just P B you got figure out how to get this stuff out.

53:01.41
Bogdan Kharchenko
I'm sure it's a comment from.

53:18.80
Skyler Katz
But also like greenfield lairvell applications where we needed. You know we had a particular model that was super important to the business. You didn't add. You couldn't just add 1 without also adding a bunch of database I mean without adding a bunch of business logic like.

53:35.74
Chris Morrell
Right.

53:38.00
Skyler Katz
Provisioning this model and and doing all sorts of things. So like I don't know I I not that I've experienced hundreds of applications but across the spectrum of of things seems reasonably important.

53:54.50
Chris Morrell
All right? So let's sanity. Check there's the you know the the vendor case I think this feels great for but here's here's another real world case that we have at internetche right? we've got courses and we've got exams um and there are many courses and there are many exams and and many of them. Ah, while important don't have any particular special meaning within the the organization. Um, you know, but we have 1 specific exam that is a core membership requirement right? and we have to. We have to deal with that in a bunch of different ways around checking eligibility for certain things or compliance reasons or you know, um, ah well for all sorts of different reasons and the same is true for courses right? There are something like 12 12 courses that every certified member has to take over the first year of their membership and we need to you know we need to check on. Um their compliance and um, you know present you know present those courses in specific ways. Um, across the website and and for the courses I mean we still do have to hard code references to those courses in a bunch of places. But for the courses. We also do a lot of that dynamically based on database tables. But you know there's 1 exam.

55:26.54
Chris Morrell
You know that I know the idea of by heart because you know we've had to reference it a thousand times. Um would this work for both of those cases I think can't. See why? not.

55:48.58
Bogdan Kharchenko
Yeah I mean I Definitely think it would work. Um, you know I Also maintain my kind of position of this special exam Id is only special now right? and like if it was it were to change. Like there has to be an easy story to transition to another Id you can't just go back and you know update all of those places or even if it gets consolidated into you know some sort of class that you know references this thing in some sort of magic way. I Ultimately think like having a real databaseriven thing is kind of the answer you know where it's like hey give me you know exams that are special. You know I mean to do this stuff. Ah, but ultimately I think it will solve. It.

56:40.43
Chris Morrell
Yeah I mean in the case of the exams the way we do. It is awful right? It's only it's only that way because of legacy reasons right? and we've run into so many weird test failures where in testing. Ah.

56:47.11
Bogdan Kharchenko
Sure yeah.

56:56.69
Chris Morrell
You know now we're accounting for this. But for a while it was like you know a test would just happen to factory up an exam with like a special Id and then a query would fail because like that Id was explicitly excluded from the query for some reason or like.

57:04.69
Bogdan Kharchenko
Who.

57:14.38
Chris Morrell
Something would go weird because you know because that Id was specially reserved and ah I'm pretty sure now for that table in our in our testing migrations we do set the auto increment to like some high number so that. All the known sort of special Ids don't accidentally get created but that was like a lesson that had to be learned so I'm not saying that that is a good way to do it by any means. Um, but I think given that like not every application is greenfield like. Think this solution would work for that scenario even though you know if I was starting from scratch I wouldn't necessarily do it that way.

57:59.47
Bogdan Kharchenko
Right? But does that also expose the issue like you know I hate to kind of dive back into it but you know the fact that we have to reference this id over and over and over again and there was this conflict say in testing. Um. You know because we're kind of like creating this unique constraint and excluding it somewhere like it. You know it just kind of seems to me that you know it's almost like a code smell of relying on a very special id or relying on a certain thing you know because you know. Especially I mean when you have maybe 1 application. That's 1 thing. But if you're deploying your applications in multiple places say think about like wordpress for example, right? like there has to be like a very dynamic way to be able to. Get this data in and out without referring to like a very specific thing maybe like a slug is fine but I feel like when you look at ideas and it gets a little complicated.

59:00.83
Chris Morrell
Yeah I mean there's a part of me that that's still intrigued by the idea of just um, you know, having reserved Id with some some auto increment constraint and just you know just having an enom that. Every time you need a new a new vendor or a new course that's like referenced in code you just add. You know that that you just do the next number you know what I mean but generally I think probably using slugs for anything anything new is.

59:36.41
Bogdan Kharchenko
Right? Okay, yeah.

59:36.76
Chris Morrell
Going to be better.

59:42.30
Chris Morrell
Um, and then you just dynamically load the id from from this system. You know so all your queries still can use the id but you're not relying on that that id is only unique in the current deployment whether that's local testing or Ci or production like you don't have to rely on it being.

59:55.77
Bogdan Kharchenko
Correct. Yeah I like that.

59:58.93
Chris Morrell
A specific id yeah all right? Well I'm curious I'm actually it kind of feels like we landed on a solution that I'm I'm pretty happy with I mean maybe in trying to implement it. It'll turn out. There's a major gap. Um, but I'm curious to see you know if in a week ah it turns out we missed something very obvious or or there's a totally different concern but like I don't know. Maybe we solved it wouldn't that be cool.

01:00:32.11
Skyler Katz
I Would I'm I'm interested to hear back from people that listen to the episode if anyone listens to the episode like what are the things that you're screaming at right now because we've just missed missed the whole thing and you're like this is not solving anything that I'm having to deal with ah.

01:00:49.23
Chris Morrell
Yeah, it's It's been really cool to get feedback so far I mean and and I I feel like some of the responses that we've we've had have been like really insightful and very very very well thought through um so I'd yeah I'd be curious to know if there.

01:00:49.34
Skyler Katz
I'll be I'll be curious.

01:01:07.30
Chris Morrell
Any other approaches to this type of thing that none of us have even thought about.

01:01:12.76
Skyler Katz
Yeah I mean it might be a coincidence but I saw him lairville news someone released like a package that deploys things 1 time. Ah, you know when you deploy and maybe it's coincidence. But maybe they're a listener to the show. So who knows absolutely.

01:01:21.61
Chris Morrell
Um, yeah, that's right I think we can take credit I think I think we should We should take credit for sure. Yeah, all right? sweet Well ah, any any closing thoughts before we call this one.

01:01:37.72
Bogdan Kharchenko
No, we're good. Let's do it.

01:01:37.88
Skyler Katz
I Think we're good.

01:01:38.86
Chris Morrell
We're good all right? Well here we go.

Creators and Guests

Chris Morrell
Host
Chris Morrell
Father of two. Mostly talking about PHP/Laravel/React on Twitter. He/him.
Skyler Katz
Guest
Skyler Katz
YIMBY | PHP | Improv | Cycling | Civics | He/Him
Referencing specific database records in your code
Broadcast by