Multitenancy in Laravel: Migrations, Testing, and switching tenants

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone multi-tenancy keeps coming up every couple of weeks and it seems that there is a tremendous amount of confusion around it and in my opinion this is mainly because there are hundreds of definitions to multi-tenancy out there in this video I'm going to give it a definition and I'm going to show you how to achieve multi-tenancy in a lot of application without any packages in my opinion the most common characteristic of a multi-tenant application at that it needs two pieces of information to run so in a typical application you only need to know who the logged in user is in a multi-tenant application you need to know the Lawton user as well as the tenant using the application so for example let's take Laura Casas comm you log onto laRocca's dot-com and the laravel application running Caracas comm knows that you are the logged in user and that's the only piece of information that it needs however imagine that the platform running Laura Kaas comm is also serving view cos comm and live wire cast comm and so on to be able to run this system you need to tell it who the user is as well as who is that Anand and each tenant has its own user base so laRocca's comm has its own users and lucas comm has its own users and to achieve this there are two common ways first to add a tenant ID to all your resources and make sure you query the correct tenant ID each time and the second way is to create a database for each tenant and switch to the correct database before running the application the first approach is the most common one and I personally can't recommend that you go for it as long as you don't have to use the database birth tenant approach if you have to use the database pertinent approach however this video I'm going to show you how to do it in the laravel application we are going to start with the database - HP configuration file we are going to remove all the connections except the my cycle connection next we'll rename this connection to tenant and set it as the default connection we will also create another connection and landlord and this is going to be the connection for the administrator or where we are going to keep information about all tenants and the shared resources between them in this connection all the environment variables start with landlord underscore and finally we are going to set the database in the tenant connection to null because we are going to set it from our code based on the configuration of each tenant now in the configuration file we have the landlord configurations and the main database connection configurations in the landlord configurations we set the database to be called landlord and I have this database already created in my local machine next we'll take a look at the migrations and here we have the tenant migrations and the route of the migrations directory created by laravel these are just the default migrations that were run on the tenant connection I also created a different directory for the landlord related migrations and currently I only have one migration to create the tenants table each tenant is going to have a name a domain and the database I'll explain why in a second why we have the tenant migrations in a separate directory for now let's take a look at the Cedars in the database either class I created a cedar for the landlord connection in this cedar we just create two tenants one called laravel and the other code Bhairava if we take a look at the tenant model we have the connection set to be the landlord connection while tenant related models likely the user model is going to use the default connection which is the tenant connection now let's see how we can run the migrations for the landlord connection we are going to call HP artisan migrate and we are going to use the landlord database connection we will also set a pass for the migration command when running this command we are telling laravel to run the migrations in the database migrations landlord directory on the landlord database connection so let's run this command that take a look at our database and we can see that the migration step will was created and it has the landlord tenant table migration and the tenant table was created as now let's try to run the migrated fresh artisan command on the landlord connection and provide the seed option to see it our database now if we take a look at the database we can see the to test tenants so now we know how to migrate our landlord connection what about the tenant connection what we need to be able to do is to run all the migrations all the tenant migrations for each and every single tenant we have and for that we cannot run each be arts and migrate simply we need to write our own console command that's going to run HP arts and migrate for each tenant I've already created this command on the app console commands tenants migrate command calling HP arts and tenants migrate you can provide an optional talent to run the migration for this specific tenant or you can leave it by default and it's going to run the migrations on all tenants you can use the fresh option to run HP arts and migrate fresh instead of HP arts on migrate and you can also provide a seed option to see the database for you in the handle method of the command we check if we have a tenant argument provided so we run the migration on distant only if not we loop over all tenants in the system and run the migration in the migrate method and before we can run HP arts and migrate or HP arts and migrate fresh on the tenant we need to configure the tenant and use it and I use it I mean telling our application that this is the current tenant so let's take a look at our tenet model and see how we can achieve this I have added two methods one called configure and the other called use the configure method is going to set the configuration for the tenant database connection and set the database attribute to the database of our tenants after that it's going to purge the tenant connection and reconnected and same on the schema connection and we are doing this to make sure that if another tenant was already connected the connection will be reset before connecting to the new tenant and in the use method we are setting a container alias called tenant and we are assigning the current tenant to it now each time we resolve tenant from the container we are going to get this tenant model now if we call our arcs and command tenants migrated it's going to run the migrations on each tenant in our database we can also provide a fresh option to run HP arts and migrate fresh on each tenant now let's see how we can see it our tenant databases here I have the landlord cedar and the user Cedars in our database cedar we need to find a way to tell laravel to only migrate or to only see it the landlord cedar if we are not calling our artisan migrate tenants command we are going to use the server global variable to check if the command being run is the tenants migrated command which is the command we just created and if so we're not going to run the landlord cedar because if you are running tenants migrate that means we need to migrate or we need to see it the tenants connection now if we run the tenants migrate command and provide the seed option it's going to run the migrations and see it our tenant databases now let's take a look on how we can run tests in such setup typically you would use the refresh database straight to refresh the database between each tests but here we have two database connections and we need to refresh both connections before each test so instead of using the trade we are going to configure our own way using the setup method and our tests we can configure the landlord and the tenant database connections to use secure light instead of my sexual and use the in-memory database we are also going to call the my grid command on the landlord connection and on the tenant connection and in our test case here we don't need to call our tenants migrate console command because in our tests we assume that we already have a single tenant that we are testing against in other tests you might need to test against having multiple tenants and in that case you can run the tenants migrate command now that we configure that it abyss connections and our tests manually we can remove this from HP unit dot XML file and if we run our tests they are going to pass if we take a look at the test just run here we are creating a tenant and calling the use method to tell laravel that this is the current tenant and we are going to create four users on that anand will call the users endpoint and assert that we get for users and return as well as the current tenant information in our users endpoint we are simply returning the current tenant by resolving it from the container and all the users in the system in this current tenant and now that we have migrations seeding and tests working let's see how we can configure our application to use the correct tenant I've created a service provider called tenancy provider and registered it in the app beach P configuration file inside this tendency provider inside the boot method I call two methods configure requests and configure to in configure requests we are getting the current host or the domain and use that domain to query the tenant eloquent model find the tenant configure it and use it at the current tenant so now if the request is coming from laravel that web which is the domain of our laravel tenant the application is going to get the laravel tenant and configure it and set it as the current tenant for the rest of the request as for it the queues we are going to use the create a load using method and provide a closure and in this closure we are getting the tenant the current tenant from the container and we are going to set a tenant ID attribute in the drop a load and store the current tenant ID in it now on each and every single queue drop the tenant ID attribute will be added to the baler and that includes queued mail and queued notifications as well we later on lesson to a drop processing event get the tenant ID from the payload and use the tenant model to find the tenant configure it and use it at the current tenant so now every Qwest knows which tenant to use and every cue drop knows which tenant to use as for control commands you need to do the same as we did with the tenants migrate command provide a way to run the command against one tenant or loop over all the tenants and run the business logic on each of them now that I showed you one way of achieving the database pertinent approach I must they say that there are multiple packages out there great packages that provide different approaches that you can use if this approach is not working for you also Tom's leg gave a good talk about multi-tenancy and LaRocca new as 2017 that I highly recommend I will leave a link to the back edges as well as Tom Stoke in the description down below I hope you found this video useful and if you have any questions regarding multi-tenancy please leave them in the comments down below and I'll do my best to answer all the questions thank you and have a great day
Info
Channel: Mohamed Said
Views: 53,740
Rating: undefined out of 5
Keywords:
Id: 592EgykFOz4
Channel Id: undefined
Length: 12min 2sec (722 seconds)
Published: Tue Apr 28 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.