SPLObjectStorage Basics0:51
have to think about that too much. But if you are working on asynchronous applications with php, or you have these long-running processes where you do have to be careful, again, this is something to be aware of. Okay, but first, a little history. In the past, if you did want to associate an object with a piece of data, you might reach for the SPL object storage. So you could set up a store here, and then notice I'm going to set the key to object and the value to foobar. Now, if I were to var_dump the store, sure enough, our key is that object. And in fact, it has to be, I can't associate a string, it's not going to work. And the same is true for WeakMaps. And I'll bring that back. Okay, so now, if I wanted to grab the value that is associated with that key, the object, it works. Okay, but here's the issue here. Let me comment that out. This approach can restrict garbage collection. Here's what I mean.
Garbage Collection Problem1:41
value that is associated with that key, the object, it works. Okay, but here's the issue here. Let me comment that out. This approach can restrict garbage collection. Here's what I mean. I bring this back to dumping the store, I can see that reference to the object. But now let's imagine at some point we are done with the object, it's automatically removed, or I can be explicit, we do unset. All right, well, even though I want to clean up here, if I were to var_dump the store again, you'll notice it didn't get cleaned up, we still have a reference to that generic class. In fact, I think I can say store current. And sure enough, there's no garbage collection going on here. Okay, so this is what WeakMaps solve. If I instead replace this to a WeakMap, give it a run, pay attention right here, we run it, oh yeah, current, I don't need that anymore. Let's bring it back. But we give it a run. And notice now, the second time we dump the store, we have performed
WeakMap Event Use Case3:23
like the typical event dispatcher, you're going to dispatch an event. Let's set that up. And maybe you want to record how many times a particular event has been dispatched. Okay, well, that's a good example of something that isn't necessarily relevant to the event instance itself. And yet we still want there to be a link. Here's an event object. How many times has it been called? So a WeakMap could allow for this. Let me show you. We'll say dispatchCount. And I'm going to make this a WeakMap. We can type it if you want. Let's go ahead and instantiate that. But in this case, I will do it in line here. Okay, so now our dispatcher has a property for the count, and the type of that property is a WeakMap. So now, think about it. I could say dispatchCount for this event. So in the past, you might do something like get the string, and then you would associate it with this, which you can still do. But yeah, in this case, it's kind of nice to make the key the
event. So in the past, you might do something like get the string, and then you would associate it with this, which you can still do. But yeah, in this case, it's kind of nice to make the key the object. That's the thing we are interested in. Now, I can't yet say ++ because we haven't initialized it. So I'll show you kind of the old school way, and then we'll clean it up. But yeah, you might say something like, well, if we don't have anything for the dispatchCount for that event, then make it equal to 0. We're initializing it. Then at that point, you could increment it. And then down here, dispatch the event. You, of course, would need to add listeners for that event. You get the idea. But we're not going to build the whole thing. Okay, I think we're ready to try it out. So I'm going to instantiate our dispatcher. We ultimately want to call dispatch and then give it the event. So let's do this. Class SomeEvent like that,
Testing Dispatch Counting5:00
we're ready to try it out. So I'm going to instantiate our dispatcher. We ultimately want to call dispatch and then give it the event. So let's do this. Class SomeEvent like that, and then we will instantiate it. All right, are we all on the same page? So we have our dispatcher. We're going to call dispatch, where ultimately, in real life, you would iterate over all listeners and call their respective handlers. But in our case, we're just doing this initial portion where we keep a record of how many times you've dispatched the event. So now if I were to var_dump the dispatcher after that's done, sure enough, we can see our dispatchCount is a WeakMap, where one of the keys is the event that was fired, and the value is one because we only dispatched it once. If elsewhere in your application, you fire it two more times, now you'll see that's equal to three. Let's do another one. How about another event? Okay.
dispatched it once. If elsewhere in your application, you fire it two more times, now you'll see that's equal to three. Let's do another one. How about another event? Okay. Let's do this down here. Like so. So now we should have two for some events, and one, excuse me, for another event. And sure enough, we do. So again, the key thing to understand here is if this was an array, this wouldn't work, and you'll see PhpStorm blow up here. An array can't define an object as the key. Again, you can get around it pretty easily. You would just want to do something like that in this case. But nonetheless, a WeakMap is an option if you want to take that approach. And again, even outside of the garbage collection benefits. Otherwise, in this case, you could still use SPLObjectStorage. Okay. So finally, let's just clean up. I'll extract a method here like incrementDispatches or something like that. Give it a run,
Refactor with Null Coalescing6:46
in this case, you could still use SPL object storage. Okay. So finally, let's just clean up. I'll extract a method here like incrementDispatches or something like that. Give it a run, that's still going to work. Next, don't forget, we're using PHP 8 here. You don't need to do things like this. Instead, you could say this dispatchCount event, if it's not set, then initialize it to zero. So try to pinpoint those areas in your application because you'll do it often. Those areas where you say, well, if this thing is not set, then set it to the given value. Anytime you encounter that, you can replace it with this, which is much cleaner. Give it a run, it still works.
