Categories
Uncategorized

PHP how to use values from outside an anonymous function

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?

Meet use

You simply use the use keyword like this.

$columnsToSearch = array($columnToSearch);
$searchSql = SqlQueryBuilder::buildMatchesInTextSearchQuery($text, $columnsToSearch, $searchMode);
$dbConn = $this->mysql->getDbConnection();
$st = $dbConn->prepare($searchSql);
//$this->doPDOBindCalls($st, $whereColumns);
$st->execute();
$result = $st->fetchAll();
$st->closeCursor();
$this->mysql->closeDbConnection();
$values = array();
if(is_array($result)){
    $values = array_map(function ($value) use ($columnToSearch){
        return $value[$columnToSearch];
    },$result);
}

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.

Categories
Software Development Web Development

How to add a fulltext index in Doctrine with Symfony 5+

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”}

@ORM\Index(name="hashtag_fulltext", columns={"image_hashtag"}, 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

 @ORM\Table(name="images",
*     indexes={@ORM\Index(name="allowResaleIndex", columns={"allow_resale"}),
*     @ORM\Index(name="collectionId", columns={"collection_id"}),
*      @ORM\Index(name="conentRating", columns={"content_rating"}),
*      @ORM\Index(name="modifyType", columns={"modify_type"}),
*     @ORM\Index(name="is_published", columns={"published_status"}),
*     @ORM\Index(name="languageCode", columns={"language_code_id"}),
*     @ORM\Index(name="ownerId", columns={"owner_user_id"}),
*     @ORM\Index(name="title", columns={"title"}),
*      @ORM\Index(name="useType", columns={"use_type"}),
*     @ORM\Index(name="visibilityIndex", columns={"visibility"})})

It is fairly tricky syntax and sort of hard on the eyes to spot issues.

Categories
Software Development Web Development

Symfony 5+ how to view dump output with AJAX requests

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

 implements EventSubscriberInterface

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.

Then add the method stub for

getSubscribedEvents()

Here is what the github source code comment says about this method

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

Creating an EventSubscriber -> Docs link

Using event subscribers -> docs link

 

Categories
rants

AT&T THE NOWHERE NETWORK

CAN YOU HEAR ME NOW????

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.

STEER CLEAR OF AT&T. Shitty service, shitty coverage and tons of shitty spam. IT truly is the spam network.

 

 

Categories
Software Development Web Development

How to update Symfony minor versions

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.

yoda practice meme
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.

Doing Research!!!

You will want to check the change log. This Symfony article mentions how to find that information in the changelog. This symfonycast article has some more good information about Symfony recipes.

Most of all look closely at the output and read what it tells you. I’d recommend you spend a day or two messing around unless your app is tiny.

If you are upgrading from 5.* to 5.4 then here is a long list of things you need to consider. change log

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.

You might want to refresh your mind of the Symfony configurations because some of it will be changes to configs, some have changed and some may be different than what your current version uses. Make sure you choose the right version of Symfony to match yours in the left top corner when reading the docs.

symfony docs version example
Choose the version that matches the one you are upgrading to.

Step 1ish Updating composer.json

Here is my composer.json for example

{
    "type": "project",
    "name": "sogi/sogi",
    "description": "A total waste of my time",
    "license": "proprietary",
    "require": {
        "php": "^8.1",
        "ext-ctype": "*",
        "ext-fileinfo": "*",
        "ext-gd": "*",
        "ext-iconv": "*",
        "ext-json": "*",
        "ext-memcached": "*",
        "ext-pdo": "*",
        "ext-redis": "*",
        "aws/aws-sdk-php": "^3.209",
        "cocur/slugify": "^4.0",
        "composer/package-versions-deprecated": "^1.10",
        "doctrine/annotations": "^1.13.2",
        "doctrine/common": "^3.2",
        "doctrine/doctrine-bundle": "^2.5.5",
        "doctrine/doctrine-migrations-bundle": "^3.2",
        "doctrine/orm": "^2.11.1",
        "friendsofsymfony/jsrouting-bundle": "^2.7",
        "phpdocumentor/reflection-docblock": "^5.2",
        "ramsey/uuid": "^4.2",
        "ramsey/uuid-doctrine": "^1.7",
        "sensio/framework-extra-bundle": "^5.1",
        "symfony/asset": "5.4.*",
        "symfony/config": "5.4.*",
        "symfony/console": "5.4.*",
        "symfony/dotenv": "5.4.*",
        "symfony/event-dispatcher": "5.4.*",
        "symfony/expression-language": "5.4.*",
        "symfony/flex": "^1.3.1",
        "symfony/form": "5.4.*",
        "symfony/framework-bundle": "5.4.*",
        "symfony/http-client": "5.4.*",
        "symfony/intl": "5.4.*",
        "symfony/mailer": "5.4.*",
        "symfony/messenger": "5.4.*",
        "symfony/mime": "5.4.*",
        "symfony/monolog-bundle": "^3.1",
        "symfony/notifier": "5.4.*",
        "symfony/process": "5.4.*",
        "symfony/property-access": "5.4.*",
        "symfony/property-info": "5.4.*",
        "symfony/proxy-manager-bridge": "5.4.*",
        "symfony/runtime": "5.4.*",
        "symfony/security-bundle": "5.4.*",
        "symfony/security-csrf": "5.4.*",
        "symfony/security-http": "5.4.*",
        "symfony/serializer": "5.4.*",
        "symfony/string": "5.4.*",
        "symfony/translation": "5.4.*",
        "symfony/translation-contracts": "2.3.*",
        "symfony/twig-bundle": "5.4.*",
        "symfony/validator": "5.4.*",
        "symfony/web-link": "5.4.*",
        "symfony/webpack-encore-bundle": "^1.13.2",
        "symfony/yaml": "5.4.*",
        "symfonycasts/reset-password-bundle": "^1.1",
        "twig/extra-bundle": "3.2.1",
        "twig/twig": "3.2.1"
    },
    "require-dev": {
        "dama/doctrine-test-bundle": "^6.3",
        "doctrine/doctrine-fixtures-bundle": "^3.4.1",
        "symfony/browser-kit": "5.4.*",
        "symfony/css-selector": "5.2.*",
        "symfony/debug-bundle": "^5.2",
        "symfony/maker-bundle": "^v1.28.0",
        "symfony/phpunit-bridge": "^5.2",
        "symfony/stopwatch": "^5.2",
        "symfony/var-dumper": "5.2.*",
        "symfony/web-profiler-bundle": "^5.2"
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": {
            "*": "dist"
        },
        "sort-packages": true,
        "allow-plugins": {
            "symfony/flex": true,
            "symfony/runtime": true
        }
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },
    "replace": {
        "paragonie/random_compat": "2.*",
        "symfony/polyfill-ctype": "*",
        "symfony/polyfill-iconv": "*",
        "symfony/polyfill-php72": "*",
        "symfony/polyfill-php71": "*",
        "symfony/polyfill-php70": "*",
        "symfony/polyfill-php56": "*"
    },
    "scripts": {
        "auto-scripts": {
            "cache:clear": "symfony-cmd",
            "assets:install %PUBLIC_DIR%": "symfony-cmd"
        },
        "post-install-cmd": [
            "@auto-scripts"
        ],
        "post-update-cmd": [
            "@auto-scripts"
        ]
    },
    "conflict": {
        "symfony/symfony": "*"
    },
    "extra": {
        "symfony": {
            "allow-contrib": true,
            "require": "5.4.*"
        }
    }
}

Each line you see above in the require sections, may need to be updated.

cat that is a lot meme
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.

gi joe half the battle meme
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

holy change log batman meme
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.

Categories
Software Development Web Development

How to set application values for easy reuse in Symfony 5+

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.

$destination = $this->getParameter('kernel.project_dir').'/public/uploads';

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.

$uploadsDir = $this->getParameter('app.user_uploads_dir');

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

The documentation on this subject isn’t great, it quickly glosses over the subject.

The best info I could find on bind and how it works is actually in a SymfonyCast like usual.

Below is what  I have set for example.

# 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.

symfony output parameters
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.

Categories
rants

AT&T the SPAM NETWORK

You can’t get worse service than AT&T.

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

And isn’t this just fucking cute. They publish propaganda pieces like this telling people they are fighting the problem. GTFO You lieing fucking assholes. You expect people who pay for your shitty suck balls service to believe more of your bullshit lies? Sure you are helping stop spam to your customers WHO PAY YOU EXTRA FOR A FUCKING APP MORONIC ASSHOLES.

 

Categories
Web Development

Symfony Messenger vs EventDispatcher learn more

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.

too fast meme
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.

Categories
Software Development Web Development

How to fix Composer GitHub API limit (0 calls/hr) is exhausted … errors

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…

Well the Composer docs say the following

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.

Find your version with

 
//globally installed
composer --verision

//or loally installed
php composer.phar --version

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 magic meme
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.

You are special and need a special token!

How to create and use the token? That is explained in the Composer Docs here. You go to the github page seen below

create github token
Create github token

Don’t choose any of the Scopes, just choose to create this useless token, it doesn’t need them.

You will next see this screen.

Now you copy that token. Open your terminal and use the following command with your token where the word token is.

//locally installed composer
php composer.phar config github-oauth.github.com token
//globally installed like I suggested
composer config --global github-oauth.github.com token

And now composer should be working again.

boom how it is done baby meme
Trial and error until it works

 

Categories
Web Development

How does Symfony decide what content type to return in a response?

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

yoda questions meme
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.