Masonite Documentation
v2.2 LTS
v2.2 LTS
  • Introduction and Installation
  • Creating a Blog
  • Prologue
    • Contributing Guide
    • How To Contribute
    • Release Cycle
    • Known Installation Issues
    • Deprecation
  • What's New
    • Masonite 1.3
    • Masonite 1.4
    • Masonite 1.5
    • Masonite 1.6
    • Masonite 2.0
    • Masonite 2.1
    • Masonite 2.2
  • Upgrade Guide
    • Masonite 1.3 to 1.4
    • Masonite 1.4 to 1.5
    • Masonite 1.5 to 1.6
    • Masonite 1.6 to 2.0
    • Masonite 2.0 to 2.1
    • Masonite 2.1 to 2.2
  • The Basics
    • Controllers
    • Helper Functions
    • Requests
    • Routing
    • Static Files
    • Views
  • The Craft Command
    • Introduction
    • Creating Commands
  • Architectural Concepts
    • Request Lifecycle
    • Service Container
    • Service Providers
  • Advanced
    • Autoloading
    • Creating a Mail Driver
    • Creating Packages
    • Database Seeding
    • Extending Classes
    • Middleware
    • Responses
    • Sessions
    • Status Codes
    • Validation
  • Useful Features
    • Broadcasting
    • Caching
    • Compiling Assets
    • Environments
    • Events
    • Framework Hooks
    • Mail
    • Queues and Jobs
    • Task Scheduling
    • Testing
    • Selenium Testing
    • Template Caching
    • Uploading
    • View Composers, Sharing and Filters
  • Security
    • Authentication
    • CSRF Protection
    • Encryption
    • Headers
    • Releases
  • Orator ORM
    • Database Migrations
    • Basic Usage
    • Collections
    • ORM
    • Pagination
    • Query Builder
    • Schema Builder
  • Managers and Drivers
    • About Drivers
    • About Managers
    • Contracts
  • Official Packages
    • Masonite API
    • Masonite Billing
    • Masonite Logging
    • Masonite Notifications
  • Masonite Essentials
    • Hash ID's
  • Tutorials
    • Creating a Blog
  • How-to Guides
    • Build Email Verification from Scratch With Masonite Framework and JSON Web Tokens
    • Deploying a Masonite Application to Heroku
    • How To Deploy Masonite to PythonAnywhere
    • How-To: Use RabbitMQ with Masonite 2.0 queues
    • How To Use The Repository Pattern with Masonite
    • Making Masonite and Laravel Mix work together
  • Deployment
    • Drivers
    • Optimization
Powered by GitBook
On this page
  • Introduction
  • Creating a Driver
  • Contracts
  • Coding Our Driver
  • Using Our Driver
Edit on Git
Export as PDF
  1. Managers and Drivers

About Drivers

Introduction

Drivers are simply extensions to features that are managed by the Manager Pattern. If we have a UploadManager then we might also create a UploadDiskDriver and a UploadS3Driver which will be able to upload to both the file system (disk) and Amazon S3. In the future if we have to upload to Microsoft Azure or Google Cloud Storage then we simply create new drivers like UploadAzureDriver and UploadGoogleDriver which are very simple to create. Drivers can be as small as a single method or have dozens of methods. The Manager Pattern makes it dead simple to expand the functionality of a Manager and add capabilities to Masonite's features.

Creating a Driver

Let's go ahead and create a simple driver which is already in the framework called the UploadDiskDriver.

If you are creating a driver it can live wherever you like but if you are creating it for Masonite core then it should live inside masonite/drivers. For our UploadDiskDriver we will create the file: masonite/drivers/UploadDiskDriver.py.

We should make a class that looks something like:

from masonite.contracts import UploadContract

class UploadDiskDriver(UploadContract):
    pass

Contracts

In order to ensure that all drivers follow the same structure, we can use Contracts. Contracts are essentially interfaces if you are coming from other programming languages. They make sure that the classes they inherit into have the minimum methods necessary in order to be accepted as a driver. If it does not meet the minumum methods necessary then you will keep hitting exceptions every time you tried to run your code.

For our specific driver we should inherit from the UploadContract:

from masonite.contracts import UploadContract

class UploadDiskDriver(UploadContract):
    pass

Coding Our Driver

Simple enough, now we can start coding what our API looks like. In the endgame, we want developers to do something like this from their controllers:

from masonite import Upload

def show(self, upload: Upload):
    upload.store(request().input('file'))

So we can go ahead and make a store method.

from masonite.contracts import UploadContract

class UploadDiskDriver(UploadContract):

    def store(self, fileitem, location=None):
        pass

Ok great. Now here is the important part. Our Manager for this driver (which is the UploadManager) will resolve the constructor of this driver. This basically means that anything we put in our constructor will be automatically injected into this driver. So for our purposes of this driver, we will need the storage and the application configuration.

from masonite.contracts import UploadContract
from config import storage, application

class UploadDiskDriver(UploadContract):

    def __init__(self, cls: SomeClass):
        self.cls = cls
        self.config = storage
        self.appconfig = application

    def store(self, fileitem, location=None):
        pass

Now that we have our configuration we need injected into our class, we can go ahead and build out the store() method:

from masonite.contracts import UploadContract
from config import storage, application

class UploadDiskDriver(UploadContract):

    def __init__(self):
        self.config = storage
        self.appconfig = application

    def store(self, fileitem, location=None):
        filename = os.path.basename(fileitem.filename)

        if not location:
            location = self.config.DRIVERS['disk']['location']

        location += '/'

        open(location + filename, 'wb').write(fileitem.file.read())

        return location + filename

Ok great! You can see that our store() method simply takes the file and write the contents of the fileitem to the disk.

Using Our Driver

from masonite.provider import ServiceProvider
from masonite.managers import UploadManager
from masonite.drivers import UploadDiskDriver
from config import storage


class UploadProvider(ServiceProvider):

    wsgi = False

    def register(self):
        self.app.bind('StorageConfig', storage)
        self.app.bind('UploadDiskDriver', UploadDiskDriver)
        self.app.bind('UploadManager', UploadManager(self.app))

    def boot(self, manager: UploadManager):
        self.app.bind('Upload', manager.driver(storage.DRIVER))

That's it! Drivers are extremely simple and most drivers you create will be a simple class with a single method or two.

PreviousDatabase MigrationsNextAbout Managers

Last updated 6 years ago

Great. If you're confused about how the dependency injection Service Container works then read the documentation.

So now that our driver is created, we can tell our Manager about it. Learn how to create managers under the documentation. Our manager will know of all drivers that are inside the Service Container. We can create a new service provider which we can use to register classes into our container. Here is an example of what the UploadProvider will look like:

Notice how we set our storage configuration in the container, binded our drivers and then binded our Manager. Again, our manager will be able to find all our UploadXDrivers that are loaded into the container. So if we set the DRIVER inside our configuration file to google, our manager will look for a UploadGoogleDriver inside our container. Read more about Managers in the documentation.

Service Container
About Managers
About Managers