In php you can create an anonymous function as a parameter to any other function that requires a function as the input. But you run into a small problem pretty quickly. When you create an anonymous function in PHP it has no access to variables outside of it’s curly braces. So what do you do if your anonymous function needs values from outside?
The above code searches a database gets all the values then uses array_map to flatten the result into one array of values Notice the anonymous function to array_map and the use statement. You can separate the values after use with a comma to include multiple variables.
I had to google to find this answer on Stackexchange because I can’t find anything in the docs. Apparently this is something new so you don’t have to jump through the old circus hoops of the past.
Apparently you can add a flags section like this to one of the index definitions of your Entity definition.
flags={“fulltext”}
Now when you do a doctrine diff and then migrate your column will have a full text index. I checked this and it works, but it is apparently not documented, not yet anyways. I am glad this useful feature exists and look forward to learning more in the future.
By the way the @ORM/Index section goes within a table section like this
So the idea is to be able to use the Symfony VarDumper component to be able to dump values when sending an AJAX request and view them for debugging while in development mode, but not in production mode.
Create a new directory
To do this you will need to create an event subscriber and listen for the kernel.response event. To do this you create a new directory inside your root directory, I called mine EventSubscribers, the name doesn’t matter you could call yous BlueWaffle and it will work exactly the same.
Create a new file
Inside this new directory create a new subscriber class, I called mine AjaxDumpSubscriber. You can make your subscriber implement
implementsEventSubscriberInterface
I am not sure if that is needed, I saw it somewhere in the docs. They never mentioned if it was needed so I am assuming it is maybe needed.
interface EventSubscriberInterface
{
/**
* Returns an array of event names this subscriber wants to listen to.
*
* The array keys are event names and the value can be:
*
* * The method name to call (priority defaults to 0)
* * An array composed of the method name to call and the priority
* * An array of arrays composed of the method names to call and respective
* priorities, or 0 if unset
*
* For instance:
*
* * ['eventName' => 'methodName']
* * ['eventName' => ['methodName', $priority]]
* * ['eventName' => [['methodName1', $priority], ['methodName2']]]
*
* The code must not depend on runtime state as it will only be called at compile time.
* All logic depending on runtime state must be put into the individual methods handling the events.
*
* @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
*/
public static function getSubscribedEvents();
}
The full class
The entire class should look like this, from what I can tell. This is working code.
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class AjaxDumpSubscriber implements EventSubscriberInterface
{
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [KernelEvents::RESPONSE];
}
public function onKernelResponse(ResponseEvent $event)
{
if (!$event->getKernel()->isDebug()) {
return;
}
$request = $event->getRequest();
if (!$request->isXmlHttpRequest()) {
return;
}
$response = $event->getResponse();
//set this one value only if this is in development mode
$response->headers->set('Symfony-Debug-Toolbar-Replace', 1);
}
}
That is it, now you can dump() values like normal… but you can’t view them like normal, not in Symfony 5.4, not for me anyways .
This only partially works, maybe I missed something or I expect something? Most of the time when you use dump() there will be an icon in the profiler bar that indicates debug output was output aka. dump() was used. Usually you can click on it and quickly see the values that were dumped. This feature doesn’t work with AJAX requests at the moment, from what I can observe.
Instead you need to click the response when it indicates in the profiler then click the Debug tab on the left panel to see your dump() values.
Links
The VarDumper component. -> Docs link you must install this before you can dump anything.
The profiler component -> Docs link you need this to see dumped stuff, even though it doesn’t work properly with the VarDumper
Would you the shittiest network coverage possible? Do you enjoy important dropped calls? Do you like a noisy background when you talk? Do you like missing lots of calls and text messages only to get bombarded once your POS phone actually finds a signal good enough to communicate with the network? Do you like saying “Can you hear me now?”
THEN YOU WOULD LOVE AT&T’s shitty network coverage. The locations where AT&T actually work are VERY ANEMIC. Their coverage sucks EVERYWHERE.
Out of all of the mobile carriers the world knows… AT&T has the absolute shittiest, worst coverage known to man. I would like to know where the hell they think their phones even work? Because they don’t work where I live, and they don’t work in even some big cities like Cape Coral Florida FFS.
I mean it is so bad it is like they are trying to be horrible.
This is a work in progress. I’ll keep updating it with time. Most of my articles are for me so I can remember what I did and the problems I had and how I solved them.
I’d suggest updating your composer packages more often than just when you are moving to a newer version of Symfony. That alone is the most time consuming part. If you keep your packages updated it is less work when you need to update to minor/major new versions.
Read the documentation about this subject first. This is a walk through or an overview with a little more information than the docs, along with some jokes.
First you need to know some things about composer, so read the docs, watch some videos, do some googling, learn more and refresh your brain.
Next you’ll need to be fairly knowledgeable of .git and it’s many commands and how it functions. Read that link to the short little book that quickly explains most of it, you only really need like the first 3 -4 chapters fresh in your mind.
Yes you must.
Unless your app is tiny an simple, I suggest you practice updating your app first and take notes so that you can have a smoother flow when you update your actual project. For example if you try to update your composer packages all to the latest, you will find conflicts and other issues, some will need to be downgrade some etc.
For me it is a lot less stressful to clone my app in a different directory and quickly try the process and take notes and make sure not to push back to the main repo… unless I just get lucky and shit magically works 100%. I messed up a lot during this process the first time. I had not fully updated my app and some things were left all the way from version like 3.4?
It depends on how old your app is aka Symfony version. How well it has been kept updated and much more, like what bundles you use etc.. This can take many hours depending on the size of your project, how much you know about git, how much you know about composer and how good your google skills are.
You can either create a new directory and pull your project and play around first or you can also branch your code. You will need to commit every time you run composer recipes:update or it won’t let you run it again. This means you could be making lots of commits and later diffing and merging and resolving conflicts. This is why I said you will need to be fairly good with GIT, just read the first few chapters of the book.
Each line you see above in the require sections, may need to be updated.
You could have more lines than this depending on your project size and complexity
This to me is one of the most complicated and time consuming parts. This is where the printed composer.json file comes in handy to let you see what all you are using and take notes next to each one when you go to packagist to look them up and find the latest versions of each. One problem you will find when updating is conflicts, you will need to downgrade some things in order to work with others. So you make a change to the latest package and then later another bundle you use needs an older version and so composer downgrades it.
This is only the first part of the battle.
Now you know!!!
Here is the output I got after updating the package/bundle versions and using composer update, after running composer recipes:update. Basically I ran the composer update command after running the composer recipes:update command, a little out of order.
You can see some things were downgraded.
Below is the packagist page for twig, notice it is v3.3.8 that is the number you need if you want to update to the latest version.
Packagist for twig
You need to do that for each package you want updated. For Symfony it is mostly easy, as you can change minor versions from like 5.1 to 5.4 and run composer update. For others you need to write the version down and add it to composer and then run update, read the output and follow it.
I also suggest running composer update after every change. Don’t make the mistake I once made and hop right along and change a bunch then try to update. OH HELL COMES UPON YOU IF YOU DO THAT. You will have mistakes, conflicts to resolve etc. It is much easier to make one change, update, fix/change and move to the next.
For many of these composer packages you will need to read the output carefully and possible update dependencies. That is one of the main reasons I say go slow one at a time.
The Log of Changes
Read the changes carefully
You will need to view the change log changes and hunt for possible places in your code where code changes need to be made. Like I said from just version 5.3 to 5.4 there is a lot. You may have to dig even further back if your version is older like 5.1 or 5.2ish etc. That is what I’ve been doing, some of my bundles were ancient.
This part is sort of painful and slow too. What I did was check the deprecation’s listed in app profiler bar, make one change check it again… What I found to help was to use my IDE PHPStorm’s find and replace feature to find all the places where object xxx was used and replace it with yyy. Some of the notices might make you say WTF and scratch your head.
Uhm, wait… what?
And you must google and search and figure it out. It was not fun. It required many curse words.
Composer Recipes
This is the next step.
This is something I’ve just heard of. I am figuring this out currently and will update this section as I figure it out, ruin some shit, take screenshots etc. Here is the Symfony release article about this feature with more info.
But this so far is how I’ve destroyed my app(the local copy)
DO NOT RUN THE WEBPACK ENCORE UPDATE, it destroys your F***ing encore configuration by replacing it.
Remember these updates are not interactive. They don’t show you what they are going to do ahead of time and ask you if it is ok. They don’t ask you if you’d like to do xyz. They just do shit, tell you there was a conflict and BOOM it is up to you to find the files and fix them. You use git status or other commands to see what was changed, where etc. Then you open the file and delete the parts you don’t want. Maybe there is a better way, but this is how I did it. The ours>>> === theirs >>> didn’t make much sense to me, it didn’t seem to follow the way it should work in several files, some were better than others. It was hard to see what changes happened in the file. The longer the file, the harder it was to discern the changes. Like I said I WRECKED some shit the first few times.
The only way I can figure to update Webpack is to rename the file that gets destroyed then copy/cut/replace with my working code again. This is the reason I said to practices before you do a ANYTHING. The first time around you are bound to WRECK YOUR APP. My first time I lost all kinds of configuration etc. I totally wrecked my app locally and had to delete the whole damn folder and clone my repo and start again. The second time I did a little better and that is when I decided to write this article. The third time as the charm… except for Webpack.
Here is a short video demonstrating some of the coolness of composer recipes:update, it works pretty good, but you got to play with it and learn WTF is going on first. LOL
I need to capture one with conflicts and show that next. I’ll pull from an older commit later and redo the process and capture more. I screwed up the version in the video by blindly updating Webpack, it fubared my precious config.
This article is a work in progress and will be further updated much more in the future. I don’t feel it is complete yet, I’d like to cover more details, more screenshots etc..
So how do you set/configure a value like an upload directory in one location in Symfony so that you can easily use it in your app later? It is actually easier than it even sounds.
Symfony has this handy system you can use to set parameters once and fetch them later. Here in this SymfonyCast under the section about moving an uploaded file, you will see this line.
Forget a moment about the full string. $this->getParameter() is what I want to focus on. The Symfony documentation metions accessing configuration parameters. And that $this->getParameters() is how you get to them.
The docs go further and say this is how you access them in the controller. To get them in your services you should autowire them and if you need them in services often you should bind them. I’ll add that below.
If you mostly need parameters in controllers, setting them as parameters like below is easy. If you need them in multiple services, then binding them is easier.
You can set your own parameters in the file /app/config/services.yaml under a section named… “Parameters” or “bind” them globally under the _defaults section.
Mostly controllers
Lets look at how to do that really quickly. Here is what is in the top portion of my file.
# /app/config/services.yaml
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
app.db_user: '%env(DATABASE_USER)%'
app.db_pass: '%env(DATABASE_PASSWORD)%'
app.user_uploads_dir: '%kernel.project_dir%/uploads'
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
The whole file is really long I just wanted enough to show a small section so you could identify it visually. You can find more about the configuration parameters in the docs here.
See the parameters section. There are three parameters I have set. app.user_upload_dir: ‘%kernel.project_dir%/uploads’ is one I made up for my own use. With that syntax I don’t have to add anything to the end of it like in the SymfonyCast code above.
I think it shows this type change later in the SymfonyCast too. You should read that full SymfonyCast if you are interested in learning how to work with uploads in Symfony 5+ Here is another great SymfonyCast all about configuration in Symfony 5+ I highly suggest you read it.
But anyways like the docs show, if I need the value of the uploads directory inside a controller, I simply access it like this.
And I don’t have to worry about misspelling it, and it can be changed in one location now if it ever needs to be changed.
Here is another link from the Symfony documentation about configuration overall.
Using Bind
Using bind seems to work more easily in more places. I am not sure of any disadvantages, the main advantage seems to be ease of use. The other methods require you to autowire some other service and call some specific method. My memory sucks, so this is the easier way for me . LOL
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
# autowire this variable name to get the value below
$userUploads: '%kernel.project_dir%/uploads'
Now to use the value of $userUploads all I do is add it to the Controller route definition as a parameter or add it to the __construct() of a Service class aka any other class.
Example uses
For a Controller router method.
public function save_user_image(Request $request, Security $security,
MessageBusInterface $messageBus, $userUploads): JsonResponse
For a Service constructor.
public function __construct(LoggerInterface $exceptionsLogger, $userUploads)
{
$this->exceptionLogger = $exceptionsLogger;
$this->userUploadsDir = $userUploads . '/';
}
How do you view the parameters?
If you are using bind, you simply look at what you have defined in the services.yaml file.
To see what parameters you can access use the following command. Only values you have defined under the “parameters” section of the services.yaml file and the parameters that symfony sets internally are visible with this command.
php bin/console debug:container --parameters
That will output a really long list of all of the parameters and info about them like this.
A list of the Symfony parameters you can use
There are literally hundreds of them. So many I am willing to bet if you need to use something or know where it is, this will show you.
If you like SPAM THEN AT&T IS YOUR PROVIDER OF CHOICE.
AT&T the spam network
That could be another title for this article. This is the MOST GREEDY OF THE MOST GREEDY POS COMPANIES ON EARTH.
Lets face it AT&T is the absolute worst cell carrier out there. Their coverage TOTALLY SUCKS ASS MAJORLY. I was down in Fort Myers Florida in the city and couldn’t get service. I get shit service where I live. Hell I can’t think of many places AT&T actually works.
That isn’t even the worst part. The worst part is I have to leave my phone on SILENT. WHY? WHY YOU ASK? Because of constant spam texts and calls. This is a money making SCAM by AT&T and the government should stop it.
It shouldn’t be legal for a company to charge you over $100 a month for service and then say… Well you know if you don’t give us an extra $3.99 per month WE WILL OPEN THE FLOOD GATES TO HELL ON YOUR ASS AND SEND YOU 50 SHIT TEXT MESSAGES AND PHONE CALLS A DAY.
You can bet your ass AT&T when I get the money I will leave your shit sucking service in a split second. And I will continue to warn everyone I encounter about your shitty, spam filled money grabbing BS actions.
Your customers shouldn’t have to pay you extra just to not have YOU SEND SPAM YOU MORONS.
T-mobile offers spam blocking for FREE. IMAGINE THAT??? WOW NO SPAM FOR FREE!!!
See how many people you can lose AT&T you dishonest assholes
So maybe you are looking into how to use Symfony in a more Event Driven way. Or maybe you want to speed up your apps response time to users. Or maybe the article title sounds interesting so you are reading this.
Under the hood Symfony has something called an EventDispatcher system. You can see this at work by opening your Symfony profiler, the dark row at the bottom of your developer page.
Symfony profiler tab/row thingy
Every time a page is loaded Symfony executes many event listeners/subscribers. You can see a list of these inside your profiler by clicking pretty much any of the options in the profiler bar. Click the one that tells you the load time for example or even the 200 response. Click the “Events” tag to see the events.
You will see something like this :
Symfony EventDispatcher list of events.
You can listen to any of these events and perform an action based on them. The information is in the documentation link above. This allows you to create an event or subscribe to one that happens on every request, whether ajax or page loading.
The messenger component on the other hand, allows you to create custom events or send messages to handlers. This is handy for when handling a request requires multiple steps, or reaching out to another website/service or heavy processing like image and video uploads.
The messenger component is useful for asynchronous activities and processing. This is really useful for uploads in your application. Do you really need the user to sit there and watch a spinny wheel for many seconds while you process their image? Or would it be better to take the upload and return to the user as quickly as possible while the system performs the operations in the background? You always want the experience to be the best for the user.
Summary
In the end it is up to you to review both methods and figure out which system woks best for you particular use case.
So a use case for the EventDispatcher is more like, store the page name the user is on before processing for analytics or redirecting. Or catch errors/exceptions and handle them in some specific way. Or just do something when x happens. EventDispatcher is ONLY Synchronous so anything you do here adds to the time it takes to finish the request/response cycle for the user.
If you want an Excellent explanation and deep dive into how to use the EventDispatcher, I suggest reading this SymfonyCast on how the Http Request/Response cycle and events work.
Messenger on the other hand is good for things like handling an image upload since you may be using something like S3 object storage and that may have network issues. Messenger can be either synchronous or asynchronous. The messenger component helps you build an asynchronous processing system so that your users experience is as quick as possible for slow processing events.
Don’t do this to your users.
In general the Messenger Component is good for building an Event driven system to make your app feel quicker to the user. User experience is #1.
If you want a deep dive into the Messenger Component, how it works and how to use it to the fullest. I suggest you read this SymfonyCast it goes deep into the subject and will answer all of the questions you have after reading this article and the documentation about the component.
When your git push fails but you don't realize it until later ...
Programming Joke.
Modern web development keeps getting easier by the day
How does a mechanic start their day? They go to work. They get their tools and start working.
How does a carpenter start their day? They go to work. They pick up their tools and begin where they left off the previous day.
How does a web developer start their day? They go to work. Turn on their computer. Start up the needed programs. Discover updates are needed. Start to do the updates. Failures happen. Spend entire day finding every bug and quirk in every piece of software they use. Maybe their OS shit the bed. Maybe their frameworks need updating… So they spend 4 hours googling and fixing errors in the first tool. Get to the next tool, same thing, spend 2 hours fixing it. Get to the next tool and have to spend 4 hours googling, updating and fixing it. In the midst of all of that they wreck a few things and have to restart a few dozen times. Finally 10 hours later their tools are maybe ready for programming the next day.
These days as a web developer you spend more time fixing your tools than programming. Programming in Web languages is the absolute worst of the worst.
If web developers were mechanics we would be ordering new tools every day and waiting for them to arrive before we could start work because the previous days tools were either broken, stolen or worked entirely differently today than they did yesterday… and the manufacturers docs were not updated, so we have to just play with them until we figure out how they work now.
programmers tools are all like…
Now to fix the Github issue with composer.
Side note: a long time ago I’d get these types of errors when simply pushing my code to my own repository.
“gitHub API limit (0 calls/hr) is exhausted, could not fetch https://api.github.com/graphql. Create a GitHub OAuth token to go over the API rate limit. You can also wait until ? for the rate limit to reset.”
Aren’t we all just like..
When you get that error while trying to use composer…
Because of GitHub’s rate limits on their API it can happen that Composer prompts for authentication asking your username and password so it can go ahead with its work.
If you would prefer not to provide your GitHub credentials to Composer you can manually create a token using the procedure documented here.
Now Composer should install/update without asking for authentication.
I don’t know about you, but Composer has never once prompted me for any password. It sort of just started doing this.
Here is what I randomly got today while trying to update a Symfony project.
Calculating CHANGELOG…GitHub API limit (0 calls/hr) is exhausted, could not fetch https://api.github.com/search/issues?q=a1a70353f64f405cfbacfc4ce860af623442d6e5. Create a GitHub OAuth token to go over the API rate limit. You can also wait until ? for the rate limit to reset.
Composer never asked for any authentication password. I do notice this error it is finally prompting for a github token below this error in another message. I have no idea when this began, I used composer a few weeks ago it seems and this wasn’t an issue.
You can enter the token there and it says it saves it. DON’T DO THAT. Stop now. Do not create and enter the token at this prompt or you will be dreadfully sorry, you will get nothing but errors about the malformed token if you do. DON’T DO IT. Hit ctrl+c to quit or close your terminal, but whatever you do, do not enter that token yet, until you have the latest version of Composer installed.
If your version composer is not the latest version then update it(2.2.9 as of this article) To do this, if you installed composer locally then you delete the composer.phar file in your project folder. If you installed it globally then you need to go to that directory probably in
/usr/local/bin/composer
where composer is the filename not a directory. Delete the composer file. You will see suggestions online that you can just run those commands and you don’t need to delete composer. That didn’t work for me. I only got permission denied errors instead. So I rage deleted the damn thing and issued the commands again and
El magico
Wow like magic it works now
No more permission denied now you summonabich!!! LOL
Then rerun the commands to install composer either locally or globally. I prefer globally so I don’t have to screw around with updating each project.
Then you need to create this special token to use Composer.
This isn’t a real article it is a link to an article that explains this process. This way I can find this information again later when I need it and also google can find this question for others in the future and they can find the Symfony cast with the info they need. And…. this is now one of the most popular articles on the site. LOL
Lets find the answers
I found this bit of interesting information in this SymfonyCast here. I had wondered about this when I was creating AJAX calls to Symfony routes.
I was playing with the new Javascript Fetch API and with sending accepted response types. In the end I decided to leave all that off and just get what is returned.
Read the linked SymfonyCast section to get an understanding of the steps/process Symfony is using to decide what content type to return in the headers.
I’d suggest reading that entire SymfonyCast it contains a hell of a lot of useful information.