4elements, Amsterdam, Holland

  1. Creating a Dating Application with Sinch: RESTful API

    In this tutorial, we're going to create a dating application for iOS similar to Tinder. For voice and messaging, we will leverage the Sinch platform, making use of its powerful SDK.

    In the first part, we will focus on the development of a RESTful API to store and retrieve user information. In the second part, the iOS client will hook into this API to find nearby users based on the user's current location.

    We will use Laravel 5.0 for the RESTful service and will be covering basic concepts, such as routes and controllers. We are also going to define custom models to support MongoDB integration in an ActiveRecord-like manner. Let's get started.

    1. Basic Setup

    I'm going to assume that you've already installed Composer and the latest Laravel installer. If you haven't, then follow the official Laravel 5.0 documentation. The installation process shouldn't take longer than a couple of minutes.

    From the command line, navigate to the location where you want to create the application for the RESTful service and execute the following command:

    After a couple of seconds, the command will tell you that the mobilesinch application has been successfully created. Navigate to the new folder and execute the following command:

    Any Laravel 5.0 application, by default, ships with some basic scaffolding for user registration and authentication. This command takes care of removing this since we want to start with a clean slate.

    There's one other thing that we have to take care of before writing the actual code for our RESTful service. By default, Laravel 5.0 ships with a middleware for cross-site request forgery (CSRF) protection. However, since we are not building a website but a RESTful API, it makes no sense to have this in place. Also, it can cause some problems along the way.

    For this application, it's best to remove it. In the root of the application folder, navigate to app/Http. Inside that folder, there's a file named Kernel.php. Open it and remove the following line:

    You can also remove WelcomeController.php, located inside app/Http/Controllers, as well as the default welcome.blade.php view inside the resources/views folder. We won't be using them, but you can leave them there if you want. Just make sure that you leave the 503.blade.php view in place as it's useful to debug the application.

    2. Base Model

    The dating application this tutorial is aiming to create has a Tinder-like functionality in which you can find users near your current location. For this to work, the API needs to perform a search based on the user's location, known as a geospatial query. While we could do this with MySQL, the industry standard leans toward MongoDB, and I personally like it much more.

    Instead of using Laravel's DB facade, we will create our own class that the application's models will extend to perform queries in MongoDB.

    This will be a simple class and won't be integrated into Laravel's Eloquent model, even though we could, I'd like to keep it simple for the time being.

    Step 1: MongoDB Configuration

    Before writing the class to perform MongoDB queries, we need to set up the database information, just as we would do for MySQL or PostgreSQL, or any other database server.

    Inside the root config folder, create a new file and name it mongodb.php. Add the following code to it:

    We set the host and port for our MongoDB server, if any, set the user and password for the connection, and define the database that we will be using, mobilesinch.

    Since MongoDB is a document-oriented database and it is schemaless, we need no further configuration, no migrations definition or anything else to structure the tables. It just works.

    Step 2: Database Connection

    We have the configuration file in place and it's now time to create the actual class that will handle the interactions with the database.

    This class will perform queries to MongoDB using ActiveRecord-like syntax. Inside the app/Http folder, create a new one, Models, and add a Base.php file inside it. Append the following code to it:

    These are the bare-bones for our Base model class. It does not extend from anything and only relies on Laravel's Config facade to retrieve the configuration parameters we created earlier.

    Next, we need to create a connection with the database. Add the following code to the private _connect method:

    In this method, we create a connection string and set the username and password if any are given. We then use PHP's MongoDB driver to create a connection and set the database to the one specified in the configuration file.

    If you are familiar with MongoDB syntax from the command line, this method is the equivalent to entering the mongo console and typing use mobilesinch. Refer to the official PHP MongoDB documentation for more information.

    Step 3: Helper Methods

    Before continuing with the database CRUD operations, there are some methods that our Base class must implement. These are used to set filters, select statements, and other query variables that are used to perform database operations. Let's start with adding the necessary member variables. Above the class constructor, add the following code:

    These are holders for the where, select, limit and offset of the database queries. To set these member variables, create the following setter methods:

    The _limit method will be useful for paginating the results of a READ operation. The user can set the limit parameter to specify the number of records to retrieve and optionally an offset parameter to specify the page to read from. Add the following code to the _limit method:

    The _select method will be used to determine which fields of a record a READ query must return. The select statement must be provided as a comma separated string.

    Finally, the _where method will be used to filter the query results and can either be an array or a key/value pair.

    We now have support in place to limit and filter queries, but we have to add some other helper methods. The first one will be used to combine any where statement set before issuing a query with the query's where parameter.

    In a moment, when we write our CRUD methods, this will make more sense. At the bottom of the class, add the following private method:

    It looks a little intimidating, but it's quite simple actually. It first checks if the where parameter is an array. If it is, it combines the given values with the existing ones using the _where helper method.

    This method, however, also supports a string to set what is returned by a READ operation. This string should have the following format:

    This example will run a query and return the fields where the name field is set to John and the last_name field is set to Smith.

    Note, however, that for both an array or a string, we check if an _id field is present. If this is the case and it's a string, we create a new MongoId object from it. Ids are objects in MongoDB and comparing them to a string will return false, which is why this conversion is necessary.

    Another thing we have to do, is reset all the query parameters once an operation has been performed so they won't affect subsequent queries. The _flush method will take care of this.

    Step 4: CRUD Operations

    We now have all the required functionality in place to filter and limit our query results. It's time for the actual database operations, which will rely on PHP's MongoDB driver. If you are uncertain about something, refer to the documentation.

    CREATE Operation

    The first operation that we are going to support is the one to create a record in the system. Add the following code to the Base class:

    Even though the PHP driver expects the inserted data to be an array, our class will support both arrays and objects. We first verify which is passed to us and cast it accordingly. We then attempt to insert the record into the database and return the inserted record as an object, including the _id.

    READ Operation

    We're going to implement two read methods, one will be used to retrieve a single record while the other will be used to fetch a list of records. Let's begin with the former.

    We define the where clause for the query and use PHP's MongoDB driver to perform a findOne operation. We then flush the query parameters and return the record as an object.

    PHP's MongoDB driver returns the result as an array while I personally prefer objects. That's the true reason for the cast.

    Next, we implement the _find method to fetch a list of records.

    In the _find method, we use the driver's find method, setting the query limit and skip parameters to support pagination.

    This method, however, returns a MongoCursor object, which we then iterate over to obtain the actual records. As before, we cast each record as an object, appending it to the result array.

    UPDATE Operation

    We already have support to create and read records from the database. We now need to be able to edit those records and add or modify a record's data. Create a new method _update and implement it as follows:

    As with the CREATE operation, we support both arrays and objects, which means we check and cast accordingly. We combine the where clauses passed to the method using the helper method. The rest is no different than the already created _insert method.

    There is a special thing to note though. When we update a MongoDB document and pass the data to the _update method, the document will be replaced. If we are only updating one field and pass the data for that field, the document will become that field. This is why we need to create an array with the $set key and the added information. The result is that our record won't be replaced with the new information.

    DELETE Operation

    Finally, the driver must support the DELETE operation to remove documents from the database.

    As before, we set the where clause for the delete operation and rely on PHP's MongoDB driver to perform a remove operation on the database.

    And that's it for our Base model. It's a lot of code, but we can now perform operations in MongoDB for the models that inherit from the Base class.

    3. Session Model

    The Session model will be in charge of creating, removing, and finding a session in the database. Create a new file inside the application's Models folder, name it Session.php,  and add the following code to it:

    This model extends from the Base class we created earlier to support MongoDB operations. It also sets the collection to be used to sessions.

    The create method is used to create a user session record. Before attempting to create it, the method verifies if the user already has an active session. If it does, it removes it from the database and creates the new record with the passed in user information.

    The find method is used to retrieve a session record from the database using a session token. Note that it simply sets the where clause for the query and delegates the task of finding the record to the _findOne method of the Base class.

    To end a user session, we implement the remove method. Using the session token, it delegates the heavy lifting to the _remove method of the Base class. Note that the model makes no check for the session token that's passed in. This should be handled by the controller. The only concern for the model is data manipulation.

    4. User Model

    The other model that our REST API needs is one to handle user related interactions. Inside the application's Models folder, create a new User.php file, and add the following code to it:

    The User model is a little more complicated. Let's begin with the methods to retrieve users. The get method will be in charge of retrieving a single record, using the user's id.  Add the following code to the get method:

    We are assuming that in the case the where parameter isn't an array, it's the user's id. The get method then delegates the task of finding the record to the _findOne method of the Base class.

    The get_error method is a helper method that will give the controller more information about failure in the model.

    The last read operation in the User model is the one for the retrieve method. This will fetch a list of users. Add the following code to the retrieve method:

    This method supports pagination and geospatial queries. If the id and distance parameters are passed in, it attempts to search for nearby users based on the user's location.

    If the id does not match any record, it returns false. If the user does exist, it prepares a geospatial query using a MongoDB 2dsphere index.

    Note that we are also setting the query not to return the user matching the _id of the user performing the search. Finally, it sets the query limit and offset parameters, delegating the task to the _find method of the Base class.

    To remove users, we need to implement the remove method. Add the following code to the  remove method:

    We check that the given _id corresponds to an existing user and attempt to remove it using the _remove method of the Base class. If something went wrong, we set the model's _error property and return false.

    Another operation our model should support is the creation of user records. Add the following code to the create method:

    In this method, we make sure there isn't already a user associated with the given email or mobile. If that's true, we return the corresponding user. If it isn't, we delegate the task to create a user to the _insert method of the Base class.

    Before we return the user record, we cast the _id to a string. Why is that? The object that's returned to us defines the _id field as a MongoId object. The client application, however, doesn't need this object.

    The User model also needs to support updating user records. Add the following code to the update method:

    As in the Base class, the update method accepts both arrays and objects as the data for the user. This make the method much more flexible.

    Before we update the user record, we make sure that the user's email and mobile aren't already in use by another user. If that's the case, we set the error to EXISTING_USER and return false. Otherwise, we delegate the update operation to the Base class.

    5. BaseController Class

    Just like the application's models inherit from a Base class, the controllers also inherit from a common parent class, other than Laravel's Controller class. This BaseController class won't be anywhere near the complexity of the Base model though.

    The class will only be used to handle a few simple tasks. To create the class, we use Laravel's artisan command. From the command line, navigate to the root of your application and execute the following command:

    This will create a file named BaseController.php inside the application's Controllers folder in the app/Http folder. Since we are using the --plain flag, the controller will not have any methods, which is what we want.

    This controller won't be using the Request class so you can go ahead and remove the following line:

    Because we need access to the Session model, add the following line to the declaration of the BaseController class:

    We're now ready to implement the methods of the BaseController class. Start by adding the following methods inside the class declaration:

    The _check_session method is used to verify the session token, which is passed as the first argument. Some tasks in the application require the user to be logged in. For instance, when updating a user record, the user corresponding with the active session needs to match the _id of the record that needs to be updated.

    The implementation is pretty straightforward. We fetch the session for the session token and, if the id of the user that corresponds with the session matches the id that is passed in as the second argument, we return the session. Otherwise, we return false.

    The other helper method takes care of sending a result back to the client that consumes the API. At the moment, we only support JSON. If the result to return is an object and has a status parameter, we set it using Laravel's response helper method. Otherwise, we simply return the result.

    6. SessionController Class

    The next controller we'll implement is the one that handles requests for the Sessions resource. From the command line, navigate to the root of your application and execute the following command:

    This will create a new file named SessionController.php inside the application's Controllers folder in the app/Http folder. Before we implement this class, we need to take care of a few things.

    The SessionController class currently inherits from Laravel's Controller class. We need to set this to use our BaseController class. This means we need to replace

    with

    We also need to change the extends clause of the class. Instead of extending from Controller, make sure that your class is extending the BaseController class. We also need to include the models used in the controller. Below the last declaration, add the following lines:

    Normally, we would just use the SessionModel, but you'll see why we are also using the UserModel in just a moment. As for the controller class itself, add the following code:

    We set the controller's model object in the constructor and declare a couple of methods, which are the actions supported by the Sessions resource.

    Step 1: Session Removal

    For the removal of a user session, we simply use the session token, which is given as a parameter in the resource URL. We will declare this later in the application routes. Inside the destroy method, add the following code:

    The method uses the SessionModel's remove method and returns the result using the _response method of the BaseController class. If removing the session is successful, we return an empty object. If an error occurred, we return an error with a 403 status code.

    Step 2: Session Creation

    The method for creating a session is a little more complicated. Note that in the method declaration we are using Laravel's Request object. We use this object to access the POST parameters of the request. Inside the create method, add the following code:

    We haven't created the session object yet, because there's something we need to discuss first. The application is going to be using Facebook Login only. From the Facebook SDK, we obtain the user's information when performing a login operation. In the API's Session resource POST handler, we need to support two things:

    • starting a session for a user
    • creating the user when it doesn't exists and then starting the session

    This is also the reason for including the UserModel in the controller. In the above empty else clause, add the following code:

    We first check for an existing user with the passed in email or mobile. If the user exists, we verify that the given Facebook ID matches the Facebook ID for the user record. If that's the case, we create the session object. If it isn't, the method returns a INVALID_CREDENTIALS error with a 403 status code.

    Starting a session is now complete. Note that this isn't extra secure. However, for the purposes of this tutorial, it will work just fine.

    For the case when there is no user associated with the passed in email or mobile, we want to create a new record. In the above empty if clause, add the following code:

    We first retrieve the rest of the required parameters from the request and then check if the location parameter is given as a JSON object or an encoded JSON object (string). The method is expecting this parameter to be in the following format:

    We then transform this location into a MongoDB 2dSphere location. To execute geospatial queries, this field needs to have the following format:

    We could ask the client to send the location in this format. However, it is better that we don't burden the client with reformatting the user location since this is specific to our implementation.

    After setting the location object, we check that the user required parameters exist and, if that's the case, we create a new user object using the create method of the UserModel class.

    That's it. Even though we could start a session by sending only the email and fbId  parameters or the mobile and fbId parameters, if the rest of the user information is given, our handler will take care of creating a new user when necessary and starting a session.

    7. UserController Class

    The last controller that the application needs is the one in charge of handling the Users resource. Once again, we use Laravel's artisan command. From the command line, navigate to the root of your application and execute the following command:

    This will create a UserController.php file inside the application's Controllers folder in the app/Http folder. As with the SessionController class, make sure that the UserController class inherits from BaseController and that it includes the UserModel class. Inside the class declaration, add the following code:

    As with the SessionController class, we initialize the model object and declare the methods that will be supported by the Users resource. Let's begin with the ones for GET operations. In the get method, add the following code:

    To retrieve a record from the system, we require that the user has an active session. It doesn't have to match the id of the retrieved user. If the user doesn't have a valid session, we return a PERMISSION_DENIED error with a 403 status code. Otherwise we return the user record as a JSON object.

    Next, for a list of users, we need to implement the retrieve method. Add the following code to the retrieve method:

    We start by fetching the request parameters, the user's session token and distance parameters in particular. This method, however, does not requires an active session. If a session is valid, we pass the user id to the retrieve method of the UserModel class.

    If a distance parameter is passed in, a geospatial query is executed. If not, a regular find query is performed. In case of errors, we retrieve the error from the model and return it to the user with a 403 status code. Otherwise, we return an array containing the found users.

    User creation will map to the Users resource POST operation. Add the following code to the create method:

    We first retrieve the necessary information for the user and, as in the session creation handler, we convert the user's location to the appropriate format.

    After this, we check that the required information is passed in. Note that even though both the email and mobile fields are optional, at least one must be present.

    After these checks, we invoke the create method of the UserModel class to insert the new user in the database. Finally, we return the new user or an error.

    To remove a user, we need to implement the remove method. Add the following code to the remove method:

    This is one of those methods in which we want the _id of the user to be removed to match the _id of the user with the active session. This is the first thing we verify. If that's the case, we delegate to the model's remove method. Otherwise, we set the error to  PERMISSION_DENIED and send the result back to the user.

    Finally, let's implement the user's update operation. Inside the update method, add the following code:

    We validate the data that's passed in and set the appropriate object for what to update. In the case of the location parameter, we reformat it first.

    Again, this method should only be accessible by users with an active session that corresponds to their own _id. This means that we first check that's the case.

    We then invoke the update method of the UserModel class and return the result to the client.

    8. Application Router

    With that last piece of code our API is complete. We have our controllers and models in place. The last thing we have to do is map incoming requests to the appropriate endpoints.

    For that, we need to edit our application's routes.php file. It's located inside the app/Http folder. If you open it, you should see something like this:

    When the application receives a GET request without any resource specified, the index method of the WelcomeController class should handle it. However, you probably already removed the WelcomeController at the start of this tutorial. If you try to navigate to this endpoint in a browser, you will get an error. Let's replace that last line with the following code:

    We map API requests to the methods previously added to our controllers. For instance, the following call

    translates to a DELETE request to the given URL. This means that in the SessionController the delete method will be called with a token of abc.

    Conclusion

    That's it for the RESTful API using Laravel 5.0. We have support for user and session management, which is exactly what we need to implement the iOS client.

    In the next part of this tutorial, Jordan will be showing you how to integrate this API in an iOS application. He will also show you how to integrate the Sinch SDK for messaging and voice calls.

     

    0 Comments

    Leave a comment › Posted in: Daily

    1. Creating a Web App From Scratch Using AngularJS and Firebase: Part 5

      In the previous part of the series, we designed and implemented an interface to create a blog post with a title and post. In this part, we'll see how to fetch the blog posts saved in Firebase and render them on our welcome page.

      Getting Started

      Let's start by cloning the previous part of the tutorial from GitHub.

      After cloning the source code, navigate to the project directory and install the required dependencies.

      Once the dependencies are installed, start the server

      Point your browser to http://localhost:8000/app/#/home and you should have the application running.

      Structuring the Data in Firebase

      Earlier when we inserted data into Firebase, we simply pushed the data to the Firebase URL and it was listed randomly in Firebase. But when data grows and everything gets pushed to Firebase it gets difficult to maintain the data. So we'll try to organize our data, which will make querying from Firebase easier.

      Log in to Firebase and go to Manage App. You should see the Firebase URL on the dashboard screen as shown below:

      Firebase Dashboard screen

      Click on the plus icon next to the URL and create a sub node called Articles with a value 0 and click Add. Once a sub node is added, you should have something like:

      Firebase Dashoboard with Articles sub node

      As you can see, we have categorized the Articles data separately, so that it will be easy to query and fetch data. 

      Now, navigate to addPost.js and modify the Firebase URL to https://blistering-heat-2473.firebaseio.com/Articles. Let's also add the email ID of the user related to the blog post. We can get the email ID from the CommonProp service that we wrote earlier. Simply inject the CommonProp service in the AddPostCtrl controller.

      While pushing the data, include the email ID parameter also. Here is the modified AddPost function:

      Save all the changes and restart the server. Try to sign in using a valid email address and password and create a blog post. Now if you have a look at the Firebase dashboard you should see the post details in the Articles sub node as shown:

      Firebase Data structure

      Render Posts on the Welcome Page

      Next, let's add a Bootstrap list group component to show posts created by a user. Navigate to app/welcome/welcome.html and inside the div with class container, after the welcome message, add the list group component as shown:

      Save the changes and restart the server. Try to sign in with a valid email address and password. When on the welcome page you should see something like:

      Welcome page with dummy blog post

      Querying Data From Firebase

      Next, let's query data from Firebase using the URL https://blistering-heat-2473.firebaseio.com/Articles

      Open welcome.js, and inside the WelcomeCtrl controller create a Firebase object using the above URL.

      We'll be using $firebase to get data from Firebase. As per the official docs:

      The $firebase wrapper is used for synchronizing Firebase data with Angular apps. It contains some helper methods for writing data to Firebase, as well as tools for reading data into synchronized collections or objects.

      In order to get data from the Firebase URL as a synchronized array, AngularFire provides a method called $asArray. Let's call the $asArray method on sync object and assign it to another $scope variable. 

      Also add a paragraph element on the welcome page as shown:

      Save all the changes and restart the server. Sign in with a valid email address and password. Once on the welcome page, you should have the query result as JSON data in the $scope.articles binding element.

      Binding the Query Result Using AngularJS

      Since we have the data queried from Firebase in the $scope.articles variable, we can bind the data to our welcome page list element. We'll use the AngularJS directive ngRepeat to repeat the data across the Bootstrap list group. Here is the list group HTML: 

      Add the ngRepeat directive as shown to the main div.

      The ngRepeat directive iterates over the articles variable and creates the HTML inside the list group div for each item. So, modify the HTML code shown:

      Save the changes and restart the server. Sign in using an email address and password, and once on the welcome page you should see the list of articles added from the Add Post page.

      Welcome page with Post from Firebase

      Now navigate to http://localhost:8000/app/#/addPost and add another post. Since we haven't yet added a redirect to the welcome page after creating a post, manually navigate to http://localhost:8000/app/#/welcome and you should see it in the list.

      Fixing a Couple of Minor Issues 

      Redirect After Creating a Post

      Once the post has been added, we need to redirect the user to the welcome page. Open app/addPost/addPost.js and inject $location in the AddPostCtrl controller. On fb.$push success callback, add a redirect to the welcome page.

      Link the Welcome Page to Add Post

      Open up app/welcome/welcome.html and modify the Add Post link href to redirect to the Add Post page as shown:

      Save all the changes and restart the server. Sign in with a valid email address and password and try to create a post, and you should be able to view the post on the welcome page list.

      Conclusion

      In this tutorial, we saw how to query the data stored in Firebase using AngularFire. We created an interface to render the blog post created by a user as a list on the welcome page. We also fixed a couple of small issues.

      In the next part of the series, we'll take this to the next level by implementing a few more features like editing and deleting the blog posts.

      Source code from this tutorial is available on GitHub. Do let us know your thoughts in the comments below!

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. A Glance at the New OpenCart 2.0

      For a while now, OpenCart has been a popular e­-commerce framework for small to medium level online stores. Recently with the release of the 2.0 major version, it has reached a new milestone. In this tutorial, we'll go through some of the exciting new features incorporated in the latest version.

      Built-in Responsive Design

      Responsive design has become a must have feature for any framework in recent times. The latest version of OpenCart is no exception. It looks exceptionally good and embraces the differences between various devices. The result is that you'll see a consistent and user friendly front­-end interface across various devices like mobile, tablets and desktops.

      Let's have a quick look at how it looks like in the mobile display.

      Mobile Front-End

      And believe me, it's not just the front­-end—the back­-end section looks just as beautiful!

      Mobile Back-End

      OCMOD ­Modification System

      If you've worked with the earlier version of OpenCart, you have probably come across the buzzword "vQmod". If you are not familiar with that, it allows you to alter the core files of OpenCart using the XML file based modification system.

      In the newer version of OpenCart, a similar system "OCMOD" is available, which is based upon the "vQmod" system itself. As "OCMOD" is integrated in the core of OpenCart itself, there's no more separate installation of the "vQmod" module required.

      Bootstrap Library Integration

      Although we've already mentioned that the latest version of the OpenCart is fully responsive, it's worth noting that Bootstrap 3 is now integrated into the core itself, which is a huge boost for front­-end developers.

      Font Awesome Support

      If you're a front­-end developer, you are likely to be aware of the "Font Awesome" toolkit. As per the official site, it provides 479+ icons at the moment!

      Font Awesome gives you scalable vector icons that can instantly be customized — size, color, drop shadow, and anything that can be done with the power of CSS.

      It's also integrated as a part of the core in OpenCart 2.0, which enriches the look and feel of the front­-end.

      UI Improvements to the Admin Interface

      The admin section interface is completely replaced with a stunning new responsive interface. The navigation is more intuitive and pleasant. Also, the interface for the catalog and product management has been improved, and the filtering UI is improved.

      UI Improvements in the Back-End

      Extension Installation Made Easy

      A ­built-in "Extension Installer" is a really powerful add­-on in the latest version of OpenCart. It eliminates the hassle of manual uploading of files to the server using FTP or something similar. Apart from this, it has made the process of installation far easier, specifically for newbies or back­-end editors who don't feel very comfortable with the manual extension installation process.

      Extension Installer

      Event Observer Pattern Integration

      "Events (script notifications)" is the killer feature of OpenCart 2.0, which really improves the extensibility of the OpenCart core framework. If it looks like an alien feature to you, let me tell you it's one of the most powerful patterns followed in the world of object oriented programming called the "Event Observer Pattern".

      The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

      In the core of the OpenCart framework, there are numerous events available to which you can listen. As an example, lets say whenever an order is placed in your store you would like to submit the order-related information to the third party reporting tool. In that case you could register your module with the post.order.add event. So every time a new order is placed, it'll call a certain piece of code in your module where you can use the order object to do the necessary stuff.

      Dashboard Notifications

      Dashboard Notifications

      As an editor or back-­end admin, you would like to have hands-on statistics of your front-end store. In the new version, a notification section is visible once you're logged into the back-­end of the OpenCart. It highlights the quick and useful summarized statistics of the store. 

      As an example, you'll see pending approvals for customers, affiliates and orders. It also provides figures regarding out of stock products and the status of sales orders.

      Addition of Payment Gateways

      Although the earlier version of OpenCart provided more than 20 payment methods in the core itself, the recent version adds a few more payment processors to the kitty. Here's the list of new payment methods available in OpenCart 2.0.

      • Secure Trading Payment Pages
      • Secure Trading Web Service
      • First Data EMEA Connect (3DSecure enabled)
      • First Data EMEA Web Service API
      • Realex Redirect
      • Realex Remote
      • BluePay Hosted Form
      • BluePay Redirect (Requires SSL)

      Custom Fields

      Custom Fields

      Ever wanted to add more input fields to the default registration form of the OpenCart front-end to collect more customer-specific information? The "Custom Fields" feature is now available in the core of the newer version itself. It'll help you to add new custom fields to the user registration and profile pages.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. One Class per Rails Controller Action With Aldous

      Controllers are often the eyesore of a Rails application. Controller actions are bloated despite our attempts to keep them skinny, and even when they look skinny, it is often an illusion. We move the complexity to various before_actions, without reducing said complexity. In fact, it often requires significant digging around and mental compilation to get a feel for the control flow of a particular action. 

      After using service objects for a while in the Tuts+ dev team, it became apparent that we may be able to apply some of the same principles to controller actions. We eventually came up with a pattern that worked well and pushed it into Aldous. Today I will look at Aldous controller actions and the benefits they can bring to your Rails application.

      The Case for Breaking Out Every Controller Action Into a Class

      Breaking out each action into a separate class was the first thing we thought of. Some of the newer frameworks such as Lotus do this out of the box, and with a little bit of work Rails could also take advantage of this.

      Controller actions that are a single if..else statement are a straw man. Even modest-sized apps have a lot more stuff than that, creeping into the controller domain. There is authentication, authorization, and various controller-level business rules (e.g. if a person goes here and they are not logged in, take them to the sign in page). Some controller actions can get quite complex, and all the complexity is firmly in the realm of the controller layer.

      Given how much a controller action can be responsible for, it seems only natural that we encapsulate all of that into a class. We can then test the logic much more easily, as we would hopefully have more control of the lifecycle of that class. It would also allow us to make these controller action classes much more cohesive (complex RESTful controllers with a full complement of actions tend to lose cohesion quite rapidly). 

      There are other problems with Rails controllers, such as the proliferation of state on controller objects via instance variables, the tendency for complex inheritance hierarchies to form, etc. Pushing controller actions into their own classes can help us address some of those as well.

      What to Do With the Actual Rails Controller

      Controller
      Image by Mack Male

      Without a lot of complex hacking on the Rails code, we can't really get rid of controllers in their current form. What we can do is turn them into boilerplate with a tiny amount of code to delegate to the controller action classes. In Aldous, controllers look like this:

      We include a module so that we have access to the controller_actions method, and we then state which actions the controller should have. Internally, Aldous will map these actions to correspondingly named classes in the controller_actions/todos_controller folder. This is not configurable just yet, but can easily be made so, and it is a sensible default.

      A Basic Aldous Controller Action

      The first thing we need to do is to tell Rails where to find our controller action (as I've mentioned above), so we modify our app/config/application.rb like so:

      We're now ready to write Aldous controller actions. A simple one might look like this:

      As you can see it looks somewhat similar to a service object, which is by design. Conceptually an action is basically a service, so it makes sense for them to have a similar interface.

      There are, however, two things that are immediately non-obvious:

      • where BaseAction comes from and what's in it
      • what build_view is

      We will cover BaseAction shortly. But this action is also using Aldous view objects, which is where build_view comes from. We're not covering Aldous view objects here and you don't have to use them (although you should seriously consider it). Your action can easily look like this instead:

      This is more familiar and we'll stick to this from now on, so as not to muddy the waters with view-related stuff. But where does the controller variable come from?

      What the Constructor for an Action Looks Like

      Let's talk about the BaseAction that we saw above. It is the Aldous equivalent of ApplicationController, so it is strongly recommended you have one. A bare-bones BaseAction is:

      It inherits from ::Aldous::ControllerAction and one of the things that it inherits is a constructor. All Aldous controller actions have the same constructor signature:

      What Data is Directly Available From the Controller Instance

      Being what they are, we've tightly coupled Aldous actions to a controller and so they can do just about everything a Rails controller can do. Obviously you have access to the controller instance and can pull whatever data you want from there. But you don't want to be calling everything on the controller instance—that would be a drag for common things like params, headers, etc. So, via a little bit of Aldous magic, the following things are available on the action directly:

      • params
      • headers
      • request
      • response
      • cookies

      And you can also make more things available in the same way via an initializer config/initializers/aldous.rb:

      More on Aldous Views or Not

      Aldous controller actions are designed to work well with Aldous view objects, but you can opt not to use the view objects if you follow a few simple rules.

      Aldous controller actions are not controllers, so you have to always provide the full path to a view. You can't do:

      Instead you have to do:

      Also, since Aldous actions are not controllers, you won't be able to have instance variables from these actions automatically be available in the view templates, so you have to provide all data as locals, e.g.:

      Not sharing state via instance variables can only improve your view code, and more explicit rendering won't hurt too much either.

      A More Complex Aldous Controller Action

      Complex
      Image by Howard Lake

      Let's look at a more complex Aldous controller action and talk about some of the other things Aldous gives us, as well as some of the best practices to writing Aldous controller actions.

      The key here is for the perform method to contain all or most of the relevant controller-level logic. First we have a few lines to handle the local preconditions (i.e. things that need to be true in order for the action to even have a chance of succeeding). These should all be one-liners similar to what you see above. The only unsightly thing is the 'and return' which we have to keep adding. This would not be an issue if we were to use Aldous views, but for now we're stuck with it. 

      If the conditional logic for the local precondition gets too complex, it should be extracted into another object, which I call a predicate object—this way the complex logic can easily be shared and tested. Predicate objects may become a concept within Aldous at some point.

      After the local preconditions are handled, we need to perform the core logic of the action. There are two ways to go about this. If your logic is simple, as it is above, just execute it right there. If it is more complex, push it into a service object and then execute the service. 

      Most of the time our action's perform method should be similar to the one above, or even less complex depending on how many local preconditions you have and the possibility of failure.

      Handling Strong Params

      Another thing you see in the above action class is:

      This is another object that inherits from an Aldous base class, and these are here in order for multiple actions to be able to share strong params logic. It looks like so:

      You supply your params logic in one method and an error message in another. You then simply instantiate the object and call fetch on it to get the permitted params. It will return nil in the event of error.

      Passing Data to Views

      Another interesting method in the action class above is:

      When you use Aldous view objects there is some magic that uses this method, but we're not using them, so we need to simply pass it as a locals hash to any view that we render. The base action also overrides this method:

      This is why we need to make sure to use super when we override it again in child actions.

      Handling Before Actions via Precondition Objects

      All of the above stuff is great, but sometimes you have global preconditions, which need to affect all or most of the actions in the system (e.g. we want to do something with the session before executing any action, etc.). How do we handle that?

      This is a good part of the reason for having a BaseAction. Aldous has a concept of precondition objects—these are basically controller actions in everything but name. You configure which action classes should be executed before every action in a method on the BaseAction, and Aldous will automatically do this for you. Let's have a look:

      We override the preconditions method and supply the class of our precondition object. This object might be:

      The above precondition inherits from BasePrecondition, which is simply:

      You don't really need this unless all your preconditions will need to share some code. We simply create it because writing BasePrecondition is easier than ::Aldous::Controller::Action::Precondition.

      The above precondition terminates the execution of the action since it renders a view—Aldous will do this for you. If your precondition doesn't render or redirect anything (e.g. you simply set a variable in the session) then the action code will execute after all the preconditions are done. 

      If you want a particular action to be unaffected by a particular precondition, we use basic Ruby to accomplish this. Override the precondition method in your action and reject whichever preconditions you like:

      Not that dissimilar to regular Rails before_actions, but wrapped in a nice 'objecty' shell.

      Error-Free Actions

      Error
      Image by Duncan Hull

      The last thing to be aware of is that controller actions are error-free, just like service objects. You never need to rescue any code in the controller action perform method—Aldous will handle this for you. If an error occurs, Aldous will rescue it and utilise the default_error_handler to handle the situation.

      The default_error_handler is a method you can override on your BaseAction. When using Aldous view objects it looks like this:

      But since we're not, you can do this instead:

      So you handle the non-fatal errors for your action as local preconditions, and let Aldous worry about the unexpected errors.

      Conclusion

      Using Aldous you can replace your Rails controllers with smaller, more cohesive objects which are a lot less of a black box and are much easier to test. As a side-effect you can reduce coupling throughout your whole application, improve how you work with views, and promote reuse of logic in your controller layer via composition.

      Better yet, Aldous controller actions can co-exist with vanilla Rails controllers without too much code duplication, so you can start using them in any existing app you are working with. You can also use Aldous controller actions without committing to using either view objects or services unless you want to. 

      Aldous has allowed us to decouple our development speed from the size of the application we're working on, while giving us a better, more organised codebase in the long run. Hopefully it can do the same for you.

       

      0 Comments

      Leave a comment › Posted in: Daily

    1. Why You Shouldn’t Code URLs in Themes or Plugins—and the WordPress Functions to Use Instead

      When you're developing a theme or a plugin, you'll often find that you have to include a URL in your code. For example, in a plugin you might need a link to a stylesheet bundled with the plugin, while in a theme you'll probably want to code the site's URL in your header.

      It might be tempting to simply code the URL in the same way as you might in a static site, but it's a bad idea. In this tutorial I'll explain why you shouldn't do this—and show you the functions you can use to create URLs dynamically.

      Why You Shouldn't Code URLs in Your Themes and Plugins

      Let's start with themes. If you're developing a theme for use on a specific site, it may not seem too harmful to add that site's domain in the theme files somewhere, but there are some definite risks and downsides:

      • If you ever decide to change the site's domain name, you'll have to edit all the URLs you've hard-coded.
      • If you're working on a development site which you'll be moving to a live server on launch, you'll have to change all the URLs you've hard-coded.
      • If you decide to use the theme on another site, you'll have to edit all those URLs.
      • If you decide to release the theme to the public or let other developers use it, it will break.
      • If you use the theme as the basis for another theme you develop for another site, you'll have to edit all the URLs.
      • If your site is in a subdirectory of your domain's root directory but you've told WordPress to use the root directory for the URL, your hard-coded URLs may point to the wrong place.
      • If you ever forget to do any of the above, your site will get 404 errors, and links to resources such as images and stylesheets won't work.

      So don't do it!

      But what about plugins? Well, this is even more risky. It's not uncommon to develop a theme just for one site, but most plugins will be used on multiple sites. It's unlikely that you'd ever hard-code a full URL into a plugin, but you might be tempted to use a function to fetch the site's URL and then code the path to the plugin directory. Again, this is risky:

      • If your plugin is moved to a different directory (such as the must use directory) then any links will break.
      • If your plugin is installed in a Multisite network running an older version of WordPress, your links could break.
      • If your plugin is installed in a site using a different directory structure to the one you've used for your URLs, again your links will break.

      This could result in your plugin simply not working at all.

      So, what do you do to avoid hard-coding URLs in WordPress?

      Functions to Use Instead of Hard-Coded URLs

      There are a variety of functions that you use to avoid hard-coding URLs in WordPress. I'm going to split them into five categories:

      • functions to retrieve the site's home page
      • functions to retrieve other front-end links (including posts, pages, attachments and archives)
      • functions to retrieve URLs for the admin screens
      • functions to retrieve URLs for files in your plugin and theme's directories
      • functions to retrieve stylesheets and scripts

      Let's start with the functions to retrieve and output a link to the home page.

      Fetching the Home Page URL

      The following template tags will fetch or output the home page URL for your site:

      • bloginfo( 'url' ): displays the home URL as specified in your Reading settings in the admin.
      • get_bloginfo( 'url' ): fetches the site URL without displaying it.
      • home_url(): fetches the home page URL without displaying it: use echo esc_url( home_url( '/' ) ); to display the home URL with a trailing slash. This takes two optional parameters: $path if you want to add a path to a specific page or add a trailing slash, and $scheme to specify the scheme for the URL, such as http, https and relative.
      • get_home_url() retrieves the URL for the home page, and supports Multisite: you can include the blog ID as a parameter.
      • site_url(): the URL where WordPress is stored, so if your WordPress installation is in the wordpress subdirectory, this will retrieve the URL http://mysite.com/wordpress
      • get_site_url(): retrieves the site URL without outputting it. Can also be used with parameters to output the URL for a site in a Multisite network, add a path, and use a specific scheme.
      • network_home_url(): the home URL for the main site in a Multisite network, useful if you want to include a link to the main site in the footer of each site on the network, for example.
      • network_site_url(): the site URL for the main site in a Multisite Network.

      As you can see, there a few different tags you can use to display the URL. Which you use will depend on a number of actors:

      • Do you want to just fetch the URL or display it?
      • Do you want to add a path after the home URL? (You can avoid this in some cases using the functions in the next section.)
      • Do you want to specify the scheme?
      • Do you want to fetch the home page URL or the site URL, if these are different?
      • Do you want to fetch the URL for a site in a Multisite network?

      You should use one of these in your theme template files where you want to insert a link to the home page, for example if a logo in your site's head links to the home page. There might also be cases where a plugin will need to fetch or display the home page URL.

      Fetching Other Front-End URLs

      As well as the home page URL, there may be times when you want to code links to other pages in your site. This will include pages, posts, attachments, and custom post types. Here are the functions you should use:

      • post_permalink() outputs a link to a post, with the post ID as its parameter.
      • get_page_link() fetches (but does not output) the link to a page, with the page ID as a parameter.
      • get_permalink() fetches (but does not output) the permalink for a post or page, with the post or page ID as its parameter.
      • get_category_link() fetches the link to a category archive, with the category ID as its parameter.
      • get_tag_link() fetches the link to a tag's archive page, with the tag ID as its parameter.
      • get_post_type_archive_link() fetches the link to a post type's archive, with the post type as its parameter.
      • get_term_link() fetches the link to a taxonomy term, with the term and the taxonomy as its parameters.
      • the_attachment_link() outputs the link to an attachment, with the attachment ID as its first parameter. Use other parameters to define the image size and whether the link will lead to the file itself or its attachment page.
      • get_attachment_link() fetches the link for an attachment, with the attachment ID as the parameter.
      • wp_get_attachment_link() also fetches the link to an attachment, but additionally lets you display the image if the attachment is an image, at a size you specify.
      • get_search_link() retrieves the link to the search page. You can define a query as its parameter, or leave it blank, in which case it will use the current query.

      Fetching Admin URLs

      If you're creating a plugin or theme with settings screens in the WordPress admin, or you're customising the admin screens, you may want to add links to admin screens. Again, you shouldn't hard-code your URLs, but use one of these tags:

      • admin_url() fetches (but doesn't output) a URL in the admin. You need to include the path to the URL as a parameter and can also include the scheme if needed. So, for example, to output the URL for the screen to create a new post, you would use echo admin_url( 'post-new.php' );.
      • get_admin_url() is similar to admin_url() but supports Multisite networks: you can include the blog ID as a parameter.
      • edit_post_link() displays a link to the editing page for a post. It can be used in the loop or outside the loop with the post ID as a parameter.
      • get_edit_post_link() fetches the link to a post's editing screen, with the post ID as its parameter.

      Retrieving Files in Your Plugin and Theme Folders

      Just as when you're coding URLs in the front-end or admin screens, you should also code URLs and paths correctly when referring to files in your plugin or theme folders. 

      First, here are the functions you should use in theme files:

      • get_stylesheet_directory() retrieves the full server path (not the URL) for the currently activated theme's directory. Use this to call include files rather than to output links.
      • get_stylesheet_directory_uri() retrieves the URL for the currently activated theme, without a trailing slash. Use it in template files to fetch resources stored in your theme folder: for example, to display an image stored in your theme's images folder, use <img src="<?php echo get_stylesheet_directory_uri(); ?>/images/logo.jpg">.
      • get_bloginfo( 'stylesheet_directory' ) retrieves the URL for the currently activated theme: using get_stylesheet_directory_uri() is neater.
      • get_template_directory_uri() is similar to get_stylesheet_directory_uri() but if you're using a child theme, it fetches the URL for the parent theme. Similarly, get_template_directory() works in the same way as get_stylesheet_directory() but for the parent theme.

      There are also functions for use in plugin files:

      • plugins_url() fetches the absolute URL to the plugins directory (without a trailing slash). It takes two optional parameters: the path to add after the URL, and the plugin which you want the URL to be relative to.
      • plugin_dir_url() retrieves the URL for the directory a file is in (with a trailing slash), with that file as its parameter. Normally you would use __FILE__ as its parameter to denote the current file.

      Here's an example of each of the above. Firstly, to retrieve the URL for a file in the current plugin's includes directory:

      And to retrieve the same URL using plugin_dir_url():

      Note that with the second example you have to echo out the path after the function: I prefer the first as it's neater. Don't forget that the second returns a trailing slash and the first doesn't.

      Retrieving Stylesheets and Scripts

      You should never hard-code links to stylesheets and scripts in your template files or plugins: instead use a function and attach it to the correct hook. This avoids problems with files being moved, ensures you're using the correct scripts without duplication, and is also more efficient.

      To call a stylesheet, use wp_register_style() and wp_enqueue_style() in a function and hook it to the wp_enqueue_scripts hook. The function below would do this in a plugin:

      Note that I've used __FILE__ above, which tells WordPress that the path to the stylesheet is relative to the current file.

      Calling a script is similar, but uses wp_register_script() and wp_enqueue_script() in your function, and attaches those to the wp_enqueue_scripts hook. The example below registers a new script and calls it:

      If your script uses a script bundled with WordPress, such as jQuery, you don't need to register it; just enqueue it as follows:

      Read more about the wp_enqueue_scripts hook in this tutorial on including JavaScript and CSS in your themes and plugins.

      Summary

      Hopefully I've convinced you that hard-coding URLs in WordPress is a bad idea: it can lead to all sorts of problems in the future, and is less efficient. Depending on where you need to link to, WordPress provides a function to replace any hard-coded URL, in either your themes or plugins. You can use functions and template tags to link to pages in your site's front end, including the home page, to screens on the WordPress admin, and to files in your templates or plugins.

       

      0 Comments

      Leave a comment › Posted in: Daily

  • Page 1 of 59 pages  1 2 3 >  Last ›
  • Browse the Blog

    Syndicate

    Most recent entries

    governing-bruise