Video: The Racist History Of Gun Control

Video: The Racist History Of Gun Control

https://ift.tt/2PFbKZ5


Video: The Racist History Of Gun Control

All throughout the nation, people are calling for the destruction of anything and everything they can see that might even be minutely related to slavery and racism that permeates so much of American history.

While this racism is typically overstated to some degree, any honest look at our nation’s history has to acknowledge that racism has been a part of that history. It’s been there for far too much of our country’s time on this planet.

These days, the destruction of statues has been the predominant way of pushing back against that history, yet there’s another racist legacy that still exists in this country.

The funny thing is, the people ripping down the statues? They tend to support that legacy.

In particular, gun control. Check out this video from The Daily Caller.

None of this was new to me. I’ve seen it all before and it’s correct. Gun control rose out of a desire to see black men and women be unable to fight back against the racism that surrounded them.

Here in Georgia, up until 2010, it was illegal to carry a firearm at a “public gathering.”

The history of that law stems from an incident during Reconstruction. A number of black legislators had been removed from their offices illegally. In Camilla, Georgia–not too far from my own home, actually–a group of African-American men and women decided to march to a Republican rally as part of a protest.

In the woods along the march route, white men with guns opened fire, killing about a dozen people and injuring as many as 30 others. In response, many of the marchers got guns of their own.

The incident was known as the Camilla Massacre and, in response, lawmakers made it illegal to bring guns to any public gathering.

You see, gun control was passed in this era with a nod and a wink. It was understood that no white sheriff or prosecutor would go after a white man carrying a gun illegally, only the blacks. It was a decision meant to unevenly apply laws so they only hurt one portion of the population.

Even today, such laws still have a similar effect.

While police routinely apply the laws against anyone who breaks them–at least in theory–these laws have a disproportionate impact on African American men and women. They’re the ones who are typically hamstrung in their attempts to lawfully purchase firearms. They’re the ones killed because they couldn’t buy a gun to protect themselves and their families. And yeah, they’re the ones prosecuted for violating gun control laws when they step outside the system.

If these protestors are serious about destroying all of America’s racist legacy, then why don’t they join us in standing against this particular racist legacy? Some of us–the very people they typically call racist bigots, I should add–have been opposing this particular legacy for years now. We’d love to welcome them to the fold so we can eradicate this particular blight from our nation.

Somehow, though, I suspect none of them are interested. What a shame.

Author’s Bio:

Tom Knighton


Tom Knighton is a Navy veteran, a former newspaperman, a novelist, and a blogger and lifetime shooter. He lives with his family in Southwest Georgia. He’s also the host of Unloaded TV on YouTube.

https://ift.tt/2w2n5Gd

guns

via Bearing Arms https://ift.tt/2WiVJN5

August 10, 2020 at 12:02PM

A Study That Gets it Right: Gun Laws Change Nothing

A Study That Gets it Right: Gun Laws Change Nothing

https://ift.tt/33zdknv


By Robert B. Young, MD

I routinely castigate lousy research by prejudiced academics who make their careers publishing poorly designed, illogically interpreted studies claiming that guns are bad and that widely restricting their ownership will solve society’s problems. I get tired of it, like anyone would covering the same fake news over and over. So it is really refreshing to review the rare study that gets it right from start to finish.

“Effect of firearms legislation on suicide and homicide in Canada from 1981 to 2016”  was published June 18 in PLOS One by DRGO member Cailinn Langmann, MD. PLOS One is an open access, but peer reviewed online journal. Dr. Langmann has reviewed a number of others’ work for DRGO, correcting their misattribution and bringing light to the world. Here, he takes them on with his own work.

I encourage you to go to the article itself, but here’s the summary. Canada has “progressively” taken the lead over the U.S. in piling up increasing restrictions on gun ownership, notably in federal laws from 1991, 1994 and 2001. Dr. Langmann looked at homicide and suicide rates from 1981 through 2016, which gave unequivocal before, during and after comparisons.

The results: “No associated benefit from firearms legislation on aggregate rates of . . . suicide” was found for either males or females, though there were increases in rates of hanging suicide and poisoning. “No beneficial association was found between legislation and female or male homicide rates.” On the other hand, “an increased association with suicide rates was found with rates of low income, increased unemployment, and the percentage of aboriginals.”

All his data is public and readily available online, unlike the common problem with other researchers generating data but unwilling to share it in order for others to confirm its validity and appropriateness. There is no researcher-defined case control nonsense here—Langmann analyzes his data as a whole, over time (including sub-sections defined by the three points of new laws), and by age groups and sex. He chooses his topics for regression analysis well, uncovering significant associations with unemployment, poverty, pre-existing high suicide rates, and prevalence of Native Canadians.

The approach is important, too, because its validity underlies the results’ validity. Biased researchers focus only on the rate of use of firearms in suicide and homicide. And (surprise!) “gun deahts” decline with less availability of guns. But they pay no attention to the only changes that matter, overall suicide and homicide rates because of all the ways people can choose to end their lives or others’.

A valuable side-result of work that does, like Langmann’s, is to substantiate the societal reality of means substitution. Yes, the degree of lethality of methods matters a great deal at the decisive moment—it is important to find just ways to separate suicidal individuals from guns (and high places, etc.) when there is an acute risk.

Each life counts, and saving one is a great thing. But on a population basis, there is no difference with or without firearms over time. Rational thinkers know this anyway, because there are other countries with little civilian gun access in which suicide rates dwarf ours.

Add to this finding the fact that violent crime does generally rise in the absence of firearms owned by civilians and their consequent inability to defend themselves.  Just look at the United Kingdom, or any of a number of long-time Democrat-controlled American cities where gun control has resulted in too many (criminal) guns on the street versus none in victims’ hands. Guns owned responsibly are not a cause of suicide, homicide or other violent crime.

Let’s wrap up with Langmann’s own conclusions:

  • It’s true “gun control methods to reduce suicide by firearms may have benefits”—but only in reducing suicide by firearms, not overall.
  • “No associated reductions in homicide with increasing firearms regulations suggests alternative approaches are necessary to reduce homicide by firearm.” These would include:
  • “Steps to reduce youth gang membership and violence through diversion and educational programs”;
  • “[C]ommunity based suicide prevention programs such as training of family physicians in the detection and treatment of depression and [non-judgmental] discussions about firearms, campaigns aimed at increasing awareness about depression, and follow-up of individuals who attempted suicide”; and,
  • “Outreach to groups for which access to care may be a particular issue, such as Aboriginals”.

The truth is out there, for those who have eyes to see it. Just follow the science—the good science, like this.

 

DRGO Editor Robert B. Young, MD is a psychiatrist practicing in Pittsford, NY, an associate clinical professor at the University of Rochester School of Medicine, and a Distinguished Life Fellow of the American Psychiatric Association.

This article was originally published at drgo.us and is reprinted here with permission. 

guns

via The Truth About Guns https://ift.tt/1TozHfp

August 7, 2020 at 03:02PM

Harry Potter with guns

Harry Potter with guns

https://ift.tt/3il9z9q

It was a thing when Steven Spielberg went back and removed the guns from E.T.

Some guy went and did the reverse and added guns to the first Harry Potter movie.

The guy gives some long explanation how this is about the danger of guns and bullshit, “a sobering point about gun violence,” whatever.

He may have wanted it to be an anti-gun thing but in reality it is the most awesome Harry Potter fan fiction ever.

I love that Harry Potter’s gun, the one that fits him best, is a 1911A1.

Hell yeah.

guns

via https://gunfreezone.net

August 7, 2020 at 03:21PM

A “woke” movie that will tick off your Liberal friends

A “woke” movie that will tick off your Liberal friends

https://ift.tt/3fDmUbd

I just watched The Wild Geese again and I realized it is almost the proper woke movie because it checks several important BLM and leftist boxes.

It has good Whites, Blacks, Jews blacks and even an openly gay guy who is the team’s medic. There is a White Rhodesian who is openly racist, yet his heart and mind change by the end of the movie thanks to the spiritual ministrations of a black man. They go up against the Mafia and a fascist Dictator by rescuing a democratic leader falsely imprisoned by another fascist dictator. And they even have an secretive international banker to fund their operation.

It does not get any more woke than that.

guns

via https://gunfreezone.net

August 7, 2020 at 12:44PM

Legacy to Laravel: How to Modernize an Aging PHP Application

Legacy to Laravel: How to Modernize an Aging PHP Application

https://ift.tt/3gte7Kg


Here at Tighten, we love Laravel and get excited about staying up to date with the latest and greatest features our framework of choice has to offer. Who among us doesn’t get excited by typing laravel new, watching Composer wave in the latest packages like a third base coach, and then wading through fields of green as we are prompted to Build something amazing.

But let’s face it—as our industry ages and the number of legacy apps grows, we often find ourselves wrestling with outdated code while hopes of using the latest features demoed at Laracon fade away like a distant dream.

It can be tempting to want to rebuild legacy apps from scratch, but if you’ve ever tried it on an app of significant complexity you know it can be a trap. Apps that have existed in production for a long time generally meet the customers’ needs well enough to keep businesses afloat and are complex for a reason: they’re often the only source of truth about business requirements when the original stakeholders and developers have long since moved on. Complexity grows over time as apps expand to handle more edge cases, and tearing down years of work introduces unnecessary risks while often taking years of its own to complete.

The good news is, you don’t have to completely rewrite your legacy app to start using new Laravel features today! In this post, I’ll present some strategies we use at Tighten to convert legacy apps to Laravel gradually over time, without needing to perform a full rewrite. Whether you’re upgrading from an old framework or moving to a framework for the first time, following these steps will let you start benefitting from all that Laravel has to offer right away.

Install a New Laravel App

First we’ll start with a clean slate by installing a new Laravel app. If you don’t already have the Laravel installer, you can find instructions on how to install it here. Once you have the installer, run the following command in your terminal to install a new Laravel app:

laravel new upgrade-to-laravel

Move the New Laravel App Into the Legacy App

Next we’re going to move the contents of the new Laravel installation into our legacy app, and drop our legacy app down one directory into a legacy folder. Then we’ll set Laravel up to handle all incoming requests and pass any requests that don’t have defined routes through to the legacy app. This will also maintain the legacy app’s version control history.

  1. Create a new legacy directory inside of the legacy app
  2. Move the legacy app’s folders containing PHP files from the top level to the legacy folder
  3. Move all of the files and folders from the Laravel installation into the root folder of the legacy app
  4. Add the following legacy catch-all route to your Laravel app, at the bottom of routes/web.php:
Route::any('{path}', 'LegacyController@index')->where('path', '.*');
  1. Create a legacy controller with the following method:
public function index()
{
    ob_start();
    require app_path('Http') . '/legacy.php';
    $output = ob_get_clean();

    // be sure to import Illuminate\Http\Response
    return new Response($output);
}

Most legacy apps use echo to display their content, so the calls to ob_start() and ob_get_clean() allow us to capture that output into the $output variable using output buffering, so we can wrap it in a Laravel response.

  1. Create a new file at app/Http/legacy.php with the following:
// This is assuming the entry point to the legacy app is at `legacy/index.php`
require __DIR__.'/../../legacy/index.php';
  1. Depending on the configuration of the legacy app, the old entry point may need to be changed to account for being one level lower in the directory tree. For example, in a CodeIgniter 3.0 install, $system_path = 'system'; in index.php will need to be changed to $system_path = '../legacy/system';.

    Depending how the frontend is set up we may also need to move legacy frontend assets to Laravel’s public directory and ensure the legacy files that require them are referencing them with the correct path.

Once all of the files are in place and paths have been updated we should be able to visit our app in the browser and see our legacy app’s home page, which means it is running inside of the Laravel app!

Spring Cleaning

Now that we have our legacy app running through Laravel, it’s a good time to focus on a few important maintenance principles.

First, it is common for older apps to contain commented-out code or code that is unreachable and can’t possibly run. Before any code is moved to Laravel or refactored, it’s a good idea to first ensure that the code is actually in use so no one is wasting any time converting unused code. Any code that is commented out or confirmed to be unreachable should be deleted. As long as the app is under version control, we can always retrieve that code later if we need to.

Second, we may run across configuration settings inside the legacy app that would be better suited for a config file (located in /config) and then referenced with the config helper. Any security keys, or other sensitive settings that should not be committed to version control should be moved to an environment variable in the gitignored .env file and then added (with blank values) to .env.example. Once a setting has been moved to .env, we can also define it in a config file so references to environment variables are limited to the /config directory and Laravel will be able to cache our configs for better performance in production.

Testing the Home Page

Let’s imagine there are no existing tests for the legacy app. You are reasonably confident that everything works but the process of transforming the app introduces risk that things could break. We can use Laravel’s built-in testing features to ensure the app continues to work.

Let’s create a test for the home page by running the following in the terminal:

php artisan make:test HomePageTest

Now lets add a test that ensures the homepage loads successfully:

public function testExample()
{
    // the entry point to the legacy app
    $response = $this->get('/');

    // replace 'welcome' with a string on the home page
    $response->assertStatus(200)
        ->assertSee('Welcome');
}

At this point if all goes well we will see a passing test—but in our experience, there are a number of things that will cause simple tests like this to fail after a conversion.

PHP Superglobals

If the legacy code is referencing superglobals like $_REQUEST or $_SERVER, they should be changed to use Laravel’s request helper instead. References to $_REQUEST['some_param'], $_GET['some_param'], and $_POST['some_param'] can be changed to request('some_param') and references to $_SERVER['some_prop'] can be changed to request()->server('some_prop').

Global Variables

Any tests that run code referencing a global variable will fail if the test doesn’t first run the code where the variable is initialized. This can often be solved by moving the declaration of the global variable to app/Http/legacy.php, but usually the best option is to get rid of the global variable entirely and move it either to a config file (if it’s a simple value) or to Laravel’s Service Container (if it’s an object).

CSRF Tokens

By default, Laravel protects all form submissions with CSRF token verification via the VerifyCsrfToken middleware in the web route group defined in (app/Http/Kernel.php). In order to take advantage of the extra security CSRF tokens offer, we will need to include a CSRF token in each of our form submissions/POST requests. The csrf_field() helper method will generate a hidden input that does this.

However, if the legacy app contains more than a few forms we may want to temporarily disable the VerifyCsrfToken middleware on the legacy routes while we update our forms to include the token. Rather than simply commenting out the VerifyCsrfToken middleware—which would also disable it for any new routes—we can create a new legacy route group that uses the same middleware as the web group, but without VerifyCsrfToken.

To make a new legacy route group that excludes the CSRF middleware, we first need to define the route group in app/Http/Kernel.php as follows:

// within $middlewareGroups below 'web'
'legacy' => [
    \App\Http\Middleware\EncryptCookies::class,
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
    \Illuminate\Session\Middleware\StartSession::class,
    // \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Next, we will move our legacy route to app/routes/legacy.php:

// app/routes/legacy.php
Route::any('{path}', 'LegacyController@index')->where('path', '.*');

Finally, we need to register the legacy route file by editing app/Providers/RouteServiceProvider.php as follows:

public function map()
{
    $this->mapApiRoutes();
    $this->mapWebRoutes();
    // Add this line to the map() method
    $this->mapLegacyRoutes();
}

// Add this method to the end of the class
protected function mapLegacyRoutes()
{
    Route::middleware('legacy')
         ->namespace($this->namespace)
         ->group(base_path('routes/legacy.php'));
}

Now our legacy forms will continue to work as they did before, without Laravel’s CSRF protection, while any new form submission routes can be defined in routes/web.php like normal and take full advantage of the security CSRF tokens provide.

Migrating to Eloquent

If your legacy app has a very complex data access layer, the idea of migrating all of that DB logic to Laravel’s Eloquent ORM may sound daunting. In order to ease this pain and minimize risk, we’ll break this process up into two steps:

Gathering Database Code

Generally, the data access layer will contain code with two responsibilities:

  1. Fetching or modifying data from the database
  2. Acting on data fetched from the database

These responsibilities might be encapsulated in model classes, or they might be scattered throughout the code base—or anywhere in between. We want to resist the urge to refactor this code in-place and instead focus on centralizing it, deferring the refactoring step until later. Separating these two steps helps build a stronger mental model of what the code is responsible for, and reduces duplication upfront. We also don’t want to clutter our brand new Eloquent models with code we know will need to be refactored. Instead, we will gather this database code in classes that sit between the Eloquent models and the rest of the codebase. We will call these classes Eloquent Shims.

Let’s say there is an items table, and code throughout the codebase is responsible for fetching one or more rows and performing operations on each item. Let’s start gathering this database code into an Eloquent Shim.

  1. First we’ll need to create the Eloquent model for the items table.
php artisan make:model Item
  1. Next we’ll create our Eloquent Shim file at app/EloquentShims/ItemShim.php:
<?php

namespace App\EloquentShims;

class ItemShim
{
    protected $item;

    public function __construct($item)
    {
        $this->item = $item;
    }
}

Now we’re ready to gather the database code inside the new shim class. Imagine we have the following code:

// Inside a controller method
$items = OldItemModel::getFutureItems();

// OldItemModel.php
public static function getFutureItems()
{
    // database query
}

First we’ll replace the controller code with the following:

$items = ItemShim::getFutureItems();

Then we’ll move the getFutureItems method from the OldItemModel class to our new ItemShim.

// ItemShim
public static function getFutureItems()
{
    // database query
}

We can continue gathering more database code into the shim classes in a similar manner. For example, when we encounter code that fetches a single record by ID, we can find that item using Eloquent inline and instantiate the shim with it like so:

$item = new ItemShim(Item::find(123));

Any methods called on the $item object can now be moved from OldItemModel to ItemShim.

Refactoring the Shim Code

Once we are ready to move on to the refactoring phase we can focus our efforts on adding enough code to our Eloquent model to eliminate the need for the shim. Back to the earlier example, we have this method now in our shim class:

// ItemShim
public static function getFutureItems()
{
    // database query
}

It might contain any amount of logic, but let’s imagine it contains a raw SQL query that simply fetches the future items from the database. Following Laravel conventions, we will want to implement a future query scope in our Item Eloquent model so we can refactor the body of the getFutureItems method to the following:

// ItemShim
public static function getFutureItems()
{
    return Item::future()->get();
}

At this point our Eloquent model contains enough logic that the shim’s getFutureItems method is no longer needed. We can replace the call to the shim in the controller method with Eloquent directly.

$items = Item::future()->get();

Once all calls to getFutureItems have been replaced with the Eloquent query we can delete the getFutureItems shim method. We can then repeat this process until the shim contains no methods, and then we can delete the shim class entirely.

Stopping Execution Early

Legacy PHP applications often have calls to die or exit that immediately stop execution in place. This will interfere with Laravel’s request/response cycle, break extensions like Laravel Telescope, and prevent LegacyController from returning a response. The app might continue working as intended, but any attempts to write PHPUnit tests covering this code will fail because the PHP process will stop early—none of our assertions will run, and the test suite will come to a halt.

One solution that will preserve existing functionality while allowing PHP to continue execution is to remove these die and exit calls and throw/catch an exception instead. In order to generate an exception that we can consistently catch, we’ll create a new file at app/Exceptions/LegacyExitScript.php with the following:

namespace App\Exceptions;

use Exception;

class LegacyExitScript extends Exception
{

}

Then we’ll update our LegacyController@index method to catch these exceptions and finish the request (don’t forget to import the LegacyExitScript exception!):

public function index()
{
    try {
        ob_start();
        require public_path() . '/legacy.php';
        $output = ob_get_clean();
    } catch (LegacyExitScript $e) {
        $output = ob_get_clean();
    }

    return new Response($output);
}

Now we can replace calls to die and exit with the following:

throw new LegacyExitScript;

If there are too many of these calls to reasonably test while replacing them with the LegacyExitScript exception, it may be a better idea to make these changes over time, while covering them with PHPUnit tests, rather than all at once.

Laravel Views

We want to make sure our application continues to meet our customers’ needs during its transition to a Laravel app, but we are also eager to take advantage of Laravel’s features. Business rules might dictate that we need to render a new page from an existing code path, or perhaps we need to modify an existing page and using a Laravel view would make the task much easier. Migrating an entire route or code path to a Laravel controller might be prohibitively time consuming, but there’s another solution! We can take advantage of the structure we put in place for our LegacyExitScript exception by throwing a view. Let’s create a new file app/Exceptions/LegacyView.php:

namespace App\Exceptions;

use Exception;
use Illuminate\View\View;

class LegacyView extends Exception
{
    protected $view;

    public function __construct(View $view)
    {
        $this->view = $view;
    }

    public function getView()
    {
        return $this->view;
    }
}

We will need to catch this exception in LegacyController@index in order to return the view as a response:

public function index()
{
    try {
        ob_start();
        require public_path() . '/legacy.php';
        $output = ob_get_clean();
    } catch (LegacyExitScript $e) {
        $output = ob_get_clean();
    } catch (LegacyView $e) {
        return $e->getView();
    }

    return new Response($output);
}

We could throw the LegacyView exception inline anywhere we want to call the view, but to make the calls a bit less verbose we can add a global helper method:

function legacy_view($view = null, $data = [], $mergeData = [])
{
    throw new App\Http\LegacyView(
        view($view, $data, $mergeData)
    );
}

Our global function uses the same method signature as Laravel’s view helper, and takes care of throwing the LegacyView exception for us. Now anywhere in the legacy code that we want to stop execution and render a Laravel view we can just call our new helper method:

legacy_view('items.index', ['items' => $items]);
// anything below won't be executed

Throwing a view wrapped in an exception like this may be unconventional but remember, we’re not aiming for perfection on the first pass. Much like our Eloquent shims above, the LegacyView exception is a stepping stone towards a maintainable app. One reason we prepend these functions/classes with legacy is that they are designed to be a temporary solution. Once the app no longer needs them, they should be removed.

Generating Database Migrations

Whether or not the legacy app’s database was generated by migrations, we’re going to want to be able to use Laravel migrations going forward. In order to support running php artisan migrate in a new development environment or on an empty database, we’ll need to generate migration files from the existing database schema. At the time of writing, the oscarafdev/migrations-generator package is one of the easier ways to accomplish this.

Helper Methods

Often when moving pieces of legacy code to Laravel classes, we come across legacy code referencing a helper method that was previously included, but is now undefined when called from the new location. We want to make sure all of our helper methods are available to new code written (or moved to) Laravel, as well as the original legacy app. To do this we can set up a legacy helper file to be autoloaded globally so its methods are made available to the entire app.

Let’s create a new helper file at app/helpers/legacy.php, then autoload it in the "files" key of composer.json:

// Add this to the "autoload" property below "classmap"
"files": [
    "app/helpers/legacy.php"
]

Once we run composer dump-autoload in the terminal, any method we define in app/helpers/legacy.php will be made available globally. Now that we have an easy place to put these methods, each time we run across a helper being called from code we have moved into Laravel we can simply move the referenced method from its legacy location into app/helpers/legacy.php.

Legacy Path Helper

Now that we have a good place to put legacy related helper methods, we can start adding new helper methods for common pieces of code in the legacy app. For example, legacy apps usually contain quite a few include and require statements to import other files. Ideally the paths given will be relative paths so they will continue to work as is, but sometimes full paths are used. In situations like these we might find ourselves needing to reference the new path to the legacy app subfolder. We can make this a bit easier on ourselves by adding a legacy_path helper method to the new app/helpers/legacy.php file:

function legacy_path($path = null)
{
    return base_path('legacy/' . $path);
}

Converting Native PHP Sessions

Most legacy apps make use of native PHP sessions, but the degree to which sessions are relied on may vary widely. Sessions can be used for anything from simply managing user authentication to storing data from every request. Ultimately most people will want to convert their native session data to Laravel sessions—there are a few different strategies that can be used.

Search and Replace

If the app can reliably be tested (either by manual or automated tests), the easiest way to convert the sessions is to perform multiple search and replace calls across the app. Below is an example of using regex to convert setting session values from a native PHP session to a Laravel session.

// find: \$_SESSION\[(.+)] = (.+);
// replace: session([$1 => $2]);

// before
$_SESSION['foo'] = 'bar';

// after
session(['foo' => 'bar']);

Convert by Route

Another strategy is to convert native PHP session usage to Laravel only while moving functionality from the legacy app to newly defined Laravel routes. This strategy would mean fewer session variables need to be converted at once (the native and Laravel sessions will exist simultaneously) but when a session variable is converted, a search should still be performed to convert any other references to that same session variable elsewhere in the legacy app.

In Closing

Legacy apps come in all shapes and sizes, so your specific app might require custom changes or configuration we didn’t cover here. However, we hope these steps can serve as a baseline strategy for transforming a legacy PHP app into a Laravel app without having to undergo a full rewrite—and allow you to start using Laravel features immediately. Laravel is designed to make us happier and more productive developers, so there’s no reason we can’t continue supporting our legacy apps while taking advantage of all that our favorite framework has to offer!

programming

via Laravel News Links https://ift.tt/2dvygAJ

August 6, 2020 at 08:24PM

Spatie Laravel Multi-Tenancy without Sub Domain (customize TenantFinder)

Spatie Laravel Multi-Tenancy without Sub Domain (customize TenantFinder)

https://ift.tt/2PpJt8I


Spatie Laravel Multi-Tenancy without Sub Domain (customize TenantFinder)

Recently Spatie released a brand new package for multi-tenancy called laravel-multitenancy.

It comes with great support to work out of the box with sub-domains like,

https://zluck.infychat.com

https://infyom.infychat.com

https://vasundhara.infychat.com

It identified the tenant based on the sub-domain and sets a database runtime for your tenant-specific models.

Recently, we used it in one of our client for Snow Removal CRM. Here we have two models,

  1. Freemium Model – with no sub-domain (application will work on main domain only)
  2. Premium Model – where the tenant will get its subdomain

And user can convert his account from Freemium to Premium at any point of time by just subscribing to the plan.

So what we want is, on the backend, we want to have a separate database for each tenant, but the application should run on main as well as a sub-domain.

So what we want to have is the ability to extend/customize the tenant detection mechanism. And Spatie does a very good job at there where you can customize the logic.

You can create your own TenantFinder class and configure it in the config file of the package. And there is very good documentation for that here: https://docs.spatie.be/laravel-multitenancy/v1/installation/determining-current-tenant/

To do that, what we did is, we have a field called tenant_id in our users table. All of our users are stored into the main database since we may have user access across the tenant.

And when any user does a login, we listen for the event Illuminate\Auth\Events\Login which is documented in Laravel Docs over here.

When a user does a login, our listener will be called and will create a cookie called tenant on the browser with the tenant id of the user. So our listener will look like,

<?php

namespace App\Listeners;

use App\Models\User;
use Cookie;
use Illuminate\Auth\Events\Login;

class LoginListener
{
    public function handle(Login $event)
    {
        /** @var User $authUser */
        $authUser = $event->user;

        Cookie::forget('tenant');
        Cookie::queue(Cookie::forever('tenant', encrypt($authUser->tenant_id)));
    }
}

Also, we encrypt the cookie on our end, so we do not want Laravel to encrypt it again, so we added tenant cookie into except array of EncryptCookies middleware as per documentation here. so our middleware looks like,

<?php

namespace App\Http\Middleware;

use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;

class EncryptCookies extends Middleware
{
    /**
     * The names of the cookies that should not be encrypted.
     *
     * @var array
     */
    protected $except = [
        'tenant'
    ];
}

Now at the last point, we extended our logic to find a tenant and get it to work on the main domain as well as sub-domain.

We have created our own custom class called InfyChatTenantFinder, which looks like,

<?php

namespace App\TenantFinder;

use App\Models\Account;
use App\Models\SubDomain;
use Illuminate\Http\Request;
use Spatie\Multitenancy\Models\Concerns\UsesTenantModel;
use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\TenantFinder\TenantFinder;

class InfyChatTenantFinder extends TenantFinder
{
    use UsesTenantModel;

    public function findForRequest(Request $request): ?Tenant
    {
        $host = $request->getHost();

        list($subDomain) = explode('.', $host, 2);

        // Get Tenant by subdomain if it's on subdomain
        if (!in_array($subDomain, ["www", "admin", "infychat"])) {
            return $this->getTenantModel()::whereDomain($host)->first();
        }

        // Get Tenant from user's account id if it's main domain
        if (in_array($subDomain, ["www", "infychat"])) {

            if ($request->hasCookie('tenant')) {
                $accountId = $request->cookie('tenant');

                $accountId = decrypt($accountId);

                $account = $this->getTenantModel()::find($accountId);

                if (!empty($account)) {
                    return $account;
                }

                \Cookie::forget('tenant');
            }
        }

        return null;
    }
}

So basically, first we check if the sub-domain is there, then find tenant from the sub-domain.

If the domain is the main domain then get the tenant id from the cookie and return the account (tenant) model.

So this is how you can customize the logic the way you want to have a custom tenant identification system.

programming

via Laravel News Links https://ift.tt/2dvygAJ

August 5, 2020 at 08:48PM

MySQL from a Developers Perspective

MySQL from a Developers Perspective

https://ift.tt/33qZjIk

So this has turned into a small series, explaining how to work with MYSQL
from a developers perspective. This post is intended as a directory for the
individual articles. It will be amended and re-dated as necessary.

The code for the series is also available in
isotopp/mysql-dev-examples
on GitHub.

The Tag #mysqldev will
reference all articles from this series.

  • MySQL Transactions – the physical side.
    Looking at how MySQL InnoDB handles transactions on the physical media, enabling rollback and commit. Introduces a number of important concepts: The Undo Log, the Redo Log, the Doublewrite Buffer, and the corrosponding in memory structures, the Log Buffer and the InnoDB Buffer Pool, as well as the concept of a page.

  • MySQL Commit Size and Speed.
    This article has code in Github, in mysql-commit-size/. We benchmark MySQL write speed as a function of number of rows written per commit.

  • MySQL Connection Scoped State.
    Looking at things that are stateful and attached to a MySQL connection, and are lost on disconnect.

  • MySQL Transactions – the logical view.
    This article introduces the concept of TRANSACTION ISOLATION LEVEL and how pushing things into the Undo Log, while a necessity to implement ROLLBACK for a Writer, enables features for a Reader.

  • MySQL Transactions – writing data.
    This article has code in Github, in mysql-transactions-counter. We increment a counter in the database, with multiple concurrent writers, and see what happens.

  • MySQL: Locks and Deadlocks.
    When changing multiple rows, it is possible to take out locks in transactions one by one. Depending on how that is done, it may come to deadlocks, and server-initiated rollbacks. When that happens, the transaction must be retried.

  • MySQL Deadlocks with INSERT
    When using the obscure transaction isolation level SERIALIZABLE, it may happen that a single INSERT can deadlock. Here is how, and why.

  • MySQL Foreign Keys and Foreign Key Constraints
    When establishing relationships between tables, you are doing this by putting one tables primary keys into another tables columns. Enforcing valid pointers between tables seems like a sexy idea, but is painful, and maybe hurts more than it helps.

  • MySQL Foreign Key Constraints and Locking
    Looking at tables with foreign key constraints, we check what happens to table and row locks, and how this is different from before.

technology

via Planet MySQL https://ift.tt/2iO8Ob8

August 4, 2020 at 11:17AM

How To Import/Export CSV Data Using MySQLi and PHP 7

How To Import/Export CSV Data Using MySQLi and PHP 7

https://ift.tt/3ft9jDk

This tutorial help to import the csv data into MySQL and export data from MySQL to csv file.The CSV file is used to import and export data for moving/exchange data information between web application.You can use rest api or web application to import/export CSV data. The web application data is stored, accessed and exchanged between […]

The post How To Import/Export CSV Data Using MySQLi and PHP 7 appeared first on Phpflow.com.

technology

via Planet MySQL https://ift.tt/2iO8Ob8

August 3, 2020 at 11:47AM

Cool things you can do with Laravel Form Requests

Cool things you can do with Laravel Form Requests

https://ift.tt/3fbjnAF


Form requests are often used for validation purposes only, but they can do a whole lot more. You can manipulate data before and after validation, and you can easily add methods of your own.

In this video I’ll demonstrate all these possiblities.

Want to see more videos like this one? Head over to the Readable Laravel video series on our website.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

programming

via Laravel News Links https://ift.tt/2dvygAJ

August 2, 2020 at 08:15PM