#SocialMedia #code #webdev #webdevelopment Low cost SEO services that help you rank higher on Google!
— Web Devel0pment (@webimprovenew4u) July 30, 2016
Find out mo… http://pic.twitter.com/OqQ0Dm49wU
from Twitter https://twitter.com/webimprovenew4u
methods and new tools for people to develop effective web . ruby css html code webdev webdevelopment
#SocialMedia #code #webdev #webdevelopment Low cost SEO services that help you rank higher on Google!
— Web Devel0pment (@webimprovenew4u) July 30, 2016
Find out mo… http://pic.twitter.com/OqQ0Dm49wU
#SocialMedia #code #webdev #webdevelopment 40+ Awesome Tips That Will Help You Do #Twitter Like a Boss:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/cKNOavPpnE
#webdesign 6 Best Landing Page Conversion Trends of 2016 So Far https://t.co/kUe5Jbos7k
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 6 Essential Components of a Successful Online #Marketing Strategy:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/tYaskXYq8B
#SocialMedia #code #webdev #webdevelopment Got No #SEO Budget? Here's 20+ Tips to Increase Google Traffic for FREE… http://pic.twitter.com/Fd4IiFFM1J
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#webdesign Dio: Lightweight virtual DOM framework https://t.co/FyrDtP497C
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 36 Rules of Social Media EVERY #Business Should Live By:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/oylsCQsWXu
#webdesign In conversation with architects: 9 video interviews from the Venice Architecture Biennale https://t.co/3Pk3cWALPb
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 6 Steps to Building a Loyal Online Audience:https://t.co/7swD95vqF2
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/HzO4UiZmuR
#SocialMedia #code #webdev #webdevelopment Conversion Rate Optimisation: How to Test and Improve Your Website:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/Fksa5n1ZOi
#SocialMedia #code #webdev #webdevelopment Just for Fun: 20 of the Craziest Questions People Ask Google:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/00tgovIvg5
#webdesign Marimekko illustrator Aino-Maija Metsola creates covers for six Virginia Woolf books https://t.co/Uhh4sInaPf via itsnicethat
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 8 Really Easy Ways to Keep Visitors on Your Website for Longer:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/jcyMMyt6to
#SocialMedia #code #webdev #webdevelopment 4 Mistakes That Will Lead To The FAILURE Of Your #Marketing Strategy:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/zMJjgYUCea
#SocialMedia #code #webdev #webdevelopment Low cost Ecommerce website design for small business.
— Web Devel0pment (@webimprovenew4u) July 30, 2016
Find out more - … http://pic.twitter.com/zmSpFAlDDY
#webdesign The Complete iOS 9 Developer Course (6 weeks) - https://t.co/joNHPhgri9 #deal
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 10 Ways Infographics Can Help You BOSS Your #Marketing Strategy:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/3SGUvBSv4K
#SocialMedia #code #webdev #webdevelopment SEO Basics: How to Structure a Perfectly Optimised Web Page:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/SStFYFzUOc
#webdesign Creative industries booming across the UK, according to new report https://t.co/I6owu9F4cl via Dezeen
— Web Devel0pment (@webimprovenew4u) July 30, 2016
#SocialMedia #code #webdev #webdevelopment 15+ Shocking Stats That Will Make You Start Using #Instagram TODAY:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/sjkXI5PATU
#SocialMedia #code #webdev #webdevelopment Cold Calling is for AMATEURS! This Is What You Should Do Instead:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/KJtMRyaJrN
#SocialMedia #code #webdev #webdevelopment Social Media Hashtags: How Many You Should Use on Each Network:
— Web Devel0pment (@webimprovenew4u) July 30, 2016
… http://pic.twitter.com/bdat161SaL
#SocialMedia #code #webdev #webdevelopment Create a #Marketing Strategy That STANDS OUT With These 9 Design Trends… http://pic.twitter.com/cdabKLylsB
— Web Devel0pment (@webimprovenew4u) July 29, 2016
#SocialMedia #code #webdev #webdevelopment Just for Fun: 20 of the Craziest Questions People Ask Google:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/tQe2y77SwS
#SocialMedia #code #webdev #webdevelopment SEO Tips: 7 Rules for Creating Content That Generates LOADS of Links:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/qelaqfvHcF
#SocialMedia #code #webdev #webdevelopment Does Your #SEO Suck? Here's 9 Reasons Why You Don't Show Up On Google:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/1xKvHSdiyc
#SocialMedia #code #webdev #webdevelopment Simple and affordable websites that help your business grow!
— Web Devel0pment (@webimprovenew4u) July 29, 2016
Find out … http://pic.twitter.com/jeNeTpsiKy
#webdesign nadiacosta we were using Polar polls, sadly they went out of business. We’re now using a custom script based on their original s…
— Web Devel0pment (@webimprovenew4u) July 29, 2016
#SocialMedia #code #webdev #webdevelopment Email #Marketing: 15 Creative Ideas to MASSIVELY Increase Subscribers:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/GHwY1npCt3
#SocialMedia #code #webdev #webdevelopment How To Be AWESOME at Social Media #Marketing Without Even Trying:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/7wOVCGefTu
#SocialMedia #code #webdev #webdevelopment SEO FAQ: What is Google Panda & Penguin and How Does It Affect My Site?… http://pic.twitter.com/ADT5lbeLK0
— Web Devel0pment (@webimprovenew4u) July 29, 2016
#SocialMedia #code #webdev #webdevelopment Got Bloggers Block? Here's How To Break Out Of A Creative Rut:
— Web Devel0pment (@webimprovenew4u) July 29, 2016
… http://pic.twitter.com/FkaGHkDFeU
If you dream of creating the next big thing in Android apps, then I'm not going to lie: you’ve got your work cut out for you!
You only need to take a quick peek at the Google Play store to see that pretty much every app you can think of has already been created—usually, multiple times and with varying degrees of success.
In such a competitive market, your app has to offer the full package—simply having a great set of features isn’t going to cut it! Your app also has to be responsive, easy to use, completely free of bugs, and (as shallow as it may seem) it has to look nice, too.
So when you jolt awake in the middle of the night with a brilliant idea for an Android app, resist the temptation to leap out of bed, boot up Android Studio and start bringing your vision to life. If you’re going to do your idea justice, then you need to put some thought into your application’s design.
In this two-part series, I’m going to show you how to turn a great idea into a great app. You’ll learn how to plan, test and perfect every part of your app’s design, and how to iron out as many issues as possible before you even write a single line of code.
In this first installment, we’re going to look at how to answer all of those big, burning questions every developer has to tackle whenever they start a new Android project. Then, we’ll create a list of all the screens we need to build, plus a screen map that shows exactly how all these screens fit together.
In part 2, you’ll master some powerful, designed-minded techniques, including wireframing and prototyping. By the end of part 2 you’ll have created a digital prototype that you can install and test on your Android smartphone, tablet, or emulator.
To help you see exactly how you’d take an idea from ‘spark of inspiration’ to working digital prototype, I’m going to imagine I’ve come up with an idea for an Android app that I want to create, and then develop this idea throughout the series.
Since we're (supposedly) heading into summer, I’m going to design an app that’ll help people plan and book the ultimate summer holiday with all their friends.
So we have our idea—what’s the first thing we need to do?
Your typical app has lots of nice-to-have added extras, but it also has a clearly defined primary task. For example, our finished travel app might include social media functionality so users can share a snap of that awesome cocktail they had on the beach, or the cat they petted outside their hotel, but these features aren’t the app’s primary task.
A good trick for getting to the core of what your app is really about is to write a product statement. This is a single sentence that communicates what your app is, what it does, and why it’s imperative that the user boots up Google Play and downloads your app right now. It might help to imagine you’re pitching your app to a potential user, and you only have a single sentence to get your message across.
After much deliberation, I’ve decided on the following product statement:
An app that takes the stress out of planning and booking the ultimate summer vacation.
It’s crucial that you never lose sight of this product statement, so you may want to scribble it on a post-it note and stick it above your desk.
The next big question you need to tackle is: who exactly am I building this thing for?
Hopefully you already have a rough idea of the kind of person who might want to use your app, but for the best results you need to design your app with a very specific target audience in mind. The old saying is true: try to please everyone, and you’ll end up pleasing no one.
Who you’re trying to appeal to should influence every part of your app—from the features you include to the look and feel of your UI, right through to the tone of your application’s text. That’s why it’s crucial you identify your target audience as early in the design process as possible.
I already have a rough idea of who I’m targeting: young adults aged 18-25 who are either on summer break from college or university, taking a full-blown gap year, or are planning one final adventure before it’s time to start looking for that first full-time job. This is a good start, but we can get more specific than that!
One simple but effective trick for zeroing in on your audience is to create a user persona.
A user persona is a single user who epitomizes the kind of person you’re targeting. What characteristics would this person have? Although the exact characteristics will vary depending on the kind of app you have in mind, you can start by answering the following questions:
Let’s create a user persona for our travel app. For the best results, it helps to think of your persona as a real person. You might even want to give your user persona a name, which is exactly what I'm going to do: meet Sasha!
Since my app is all about organising a holiday, I also need to define Sasha’s experiences surrounding travel. Is my “typical” user likely to be well-travelled? Have they been responsible for planning their own holidays before, or is this all new to them?
I’m going to add the following characteristics to my user persona:
So now we have the who, but what about the when? Under what circumstances might Sasha feel compelled to whip out her phone and boot up our app?
Here are a few that spring to my mind:
It’s time to have some fun: let your imagination run wild and write down every feature you would include in your app if you had infinite time, money and a whole army of developers ready and raring to help you out. For now, don’t worry about whether these features are practical—think of this as your ultimate features list.
If you're struggling for inspiration, then head over to the Google Play store and download a few examples of Android applications that cover similar content, or have the same target audience as your application.
Here are a few of the features I’ve jotted down:
Now it’s time for a reality check: there’s no way anyone can cram all their ideas into a single app. Even if all your ideas are sensible, well thought out and would appeal to your target audience, throwing everything but the kitchen sink into an app would be a nightmare for you as a developer, and would likely lead to a terrible user experience.
Imagine launching an app for the first time and instantly being confronted by a huge, complicated menu packed with a tonne of options. Choice is a good thing, but too much choice just becomes confusing! Since the last thing you want to do is confuse your users, we need to whittle our ultimate features list down to the bare essentials.
So how do we decide which features live, and which features die?
For the initial release, you should concentrate on features that are essential for delivering your app’s core functionality. And remember that just because a feature doesn’t make it into Version 1.0, doesn’t mean it won’t find its way into a subsequent update. If you come across a feature in your list that has potential, but isn’t essential for fulfilling your app’s primary task, then make a note of it as something that’s worth revisiting once you’ve got your app’s fundamentals down.
Your user persona and use cases should also play a role in determining what features you include in Version 1.0 (and in subsequent releases). What features are most likely to appeal to Sasha?
After re-reading the user persona, use cases and product statement, I’ve settled on the following features:
Our list contains other features that would appeal to Sasha, such as being able to post photos from her trip, as we already know that Sasha is a fan of all things social media. However, for this initial release I’m going to keep things simple and remain focused on the app’s primary goal. Once you’ve delivered your app’s core functionality and fulfilled your product statement, you can turn your attention to all those nice-to-have added extras.
You next task is to start thinking about the screens that you’ll need to create, in order to deliver this list of features, so grab a piece of paper and a pen or pencil. Sketch some rough flowcharts of the routes your users might take through your app, in order to accomplish core tasks.
For my travel app, the core tasks are:
You’ll typically represent screens with shapes, and express navigation using lines or arrows.
This exercise is mainly intended to get you thinking about the different screens you’ll need to create, in order to deliver the features you cherry-picked from your ultimate features list. Don’t spend too much time on your flowchart, as you’ll refine this flow when you come to create your screen map.
Next, come up with a list of all the screens you’ll need to create, based on your flowchart.
Here’s my screen list, plus a brief overview of what I plan to include in each screen:
Now it’s time to combine our flowchart and screen list into a screen map that expresses the navigational relationship between all of these screens.
Start with the first screen the user sees when they launch your app, and work outwards.
It’s never too early to start looking for ways to improve the user experience, so once you’ve created your screen map, take a moment to look at it with a critical eye. One factor that has a huge impact on the user experience is the number of screens the user needs to navigate in order to complete the app’s core tasks.
Generally speaking, the fewer steps, the better the user experience. This map is the perfect opportunity to identify places where you can reduce the number of screens the user needs to navigate. This may involve removing screens, combining screens, reordering screens, or identifying places where it would make sense to add a navigational ‘shortcut’ so the user can jump straight from screen A to screen E.
So far, we've made some big decisions about the app we’re going to create, including who our target audience is, and what features we’re going to include in Version 1.0 (with some features left over for subsequent releases). We’ve also made a list of all the screens we need to design, and sketched out how these screens are going to be arranged in our finished app.
At this point we have our app all planned out, albeit at a very high level. In part 2 I’m going to dig deeper and design the individual screens that make up this screen map, before putting these screens to the test by building a digital prototype.
Loopj is an Android library for making asynchronous HTTP requests. I like it for its ease of use and simplicity. Created by James Smith, it's also known as "Android Asynchronous HTTP Client", and it's used by companies like Instagram, Pinterest, and many others. It's a good entry point to the world of HTTP libraries, and will help you understand important concepts very easily.
To learn to use this library, we are going to create MovieTrivia, a simple app that connects to a web service to retrieve information about movies or TV shows and displays this information to the user.
To start, create a new Android Studio project, with an empty activity. To include Loopj, copy the dependency from the official website. You can find the dependency under the "Installation and basic usage" section of the website (or just copy the string below).
compile 'com.loopj.android:android-async-http:1.4.9'
The message "Sync Now" will pop up in the upper right-hand corner. Click it so Gradle will download the library and make it available to your project.
Because the app will connect to the internet, we must declare the appropriate permission for the user to authorise. Open your AndroidManifest.xml file and, just before the application tag, write:
<uses-permission android:name="android.permission.INTERNET"/>
Now you are ready to start using Loopj in your app.
We are going to create the simplest possible user interface: just a TextField to enter a search term, a Button to do the search, and a TextView to show the results. Open activity_mail.xml and add the required UI components as shown below.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://ift.tt/nIICcg"
xmlns:tools="http://ift.tt/LrGmb4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/activity_vertical_margin"
tools:context="com.pdrogfer.movietrivia.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/etSearchTerms"
android:layout_width="0dp"
android:layout_weight="3"
android:layout_height="wrap_content"
android:hint="movie or tv show" />
<Button
android:id="@+id/btnSearch"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Search" />
</LinearLayout>
<TextView
android:id="@+id/tvSearchResults"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:hint="search results"/>
</LinearLayout>
Now, as usual, wire up these components in your MainActivity.java.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
EditText etSearchTerms;
Button btnSearch;
TextView tvSearchResults;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etSearchTerms = (EditText) findViewById(R.id.etSearchTerms);
btnSearch = (Button) findViewById(R.id.btnSearch);
tvSearchResults = (TextView) findViewById(R.id.tvSearchResults);
btnSearch.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String searchTerm = etSearchTerms.getText().toString();
etSearchTerms.setText("");
// make Loopj HTTP call
}
}
To keep your code clean and organized, create a separate java class, MyLoopjTask.java, to contain all the Loopj-specific code and operations. You will need two instance variables, one of type RequestParams to build the search details into the URL, and another of type AsyncHttpClient to actually make the HTTP requests. Before going further, check that Android Studio added these necessary imports.
import org.json.JSONObject; import cz.msebera.android.httpclient.Header;
Also create a method that takes the user query as an argument—this is where the actual work will be done.
public class MyLoopjTask {
private static final String TAG = "MOVIE_TRIVIA";
AsyncHttpClient asyncHttpClient;
RequestParams requestParams;
String BASE_URL = "http://www.omdbapi.com/?";
String jsonResponse;
public MyLoopjTask() {
asyncHttpClient = new AsyncHttpClient();
requestParams = new RequestParams();
}
public void executeLoopjCall(String queryTerm) {
requestParams.put("s", queryTerm);
asyncHttpClient.get(BASE_URL, requestParams, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
super.onSuccess(statusCode, headers, response);
jsonResponse = response.toString();
Log.i(TAG, "onSuccess: " + jsonResponse);
}
@Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
super.onFailure(statusCode, headers, throwable, errorResponse);
Log.e(TAG, "onFailure: " + errorResponse);
}
});
}
}
As you see, you can add all the necessary API request parameters keys with the RequestParams instance (in this case, just the query entered by the user). This version of the get() method returns a JSON object to onSuccess, but there are other variations available to fit your needs. (Use Ctrl+O to see the other versions of this method.)
This is all you need to do to implement a Loopj client to make HTTP calls to a web service. In our case, we want to send our request when the user clicks the "Search" button. So, back in MainActivity, create an instance of MyLoopjTask and inside onClick call executeLoopjCall with the term entered by the user. MainActivity will look as follows.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
EditText etSearchTerms;
Button btnSearch;
TextView tvSearchResults;
MyLoopjTask myLoopjTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etSearchTerms = (EditText) findViewById(R.id.etSearchTerms);
btnSearch = (Button) findViewById(R.id.btnSearch);
tvSearchResults = (TextView) findViewById(R.id.tvSearchResults);
btnSearch.setOnClickListener(this);
myLoopjTask = new MyLoopjTask();
}
@Override
public void onClick(View v) {
String searchTerm = etSearchTerms.getText().toString();
etSearchTerms.setText("");
// make loopj http call
myLoopjTask.executeLoopjCall(searchTerm);
}
}
Now, if you run the app, you should see the results of your request in the log window.
Separating asynchronous operations into dedicated classes helps keep our code clean, but it means we don't have access to UI elements directly. To show the results of these requests, I recommend creating a listener interface. This is a common strategy, discussed for example in this Stack Overflow question. It has three easy steps.
First, create an interface with a single method that will be called when the results of the HTTP request are obtained from Loopj.
public interface OnLoopjCompleted {
public void taskCompleted(String results);
}
In MyLoopjTask, modify the constructor so it takes a Context and an OnLoopjCompleted instance as parameters.
public MyLoopjTask(Context context, OnLoopjCompleted listener) {
asyncHttpClient = new AsyncHttpClient();
requestParams = new RequestParams();
this.context = context;
this.loopjListener = listener;
}
Now, when the request results are available in MyLoopjTask, pass them to the listener interface's method.
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
super.onSuccess(statusCode, headers, response);
jsonResponse = response.toString();
loopjListener.taskCompleted(jsonResponse);
Log.i(TAG, "onSuccess: " + jsonResponse);
}
Finally, make the activity you want to update—in this case MainActivity—implement OnLoopjCompleted. Update the initialization of myLoopjTask to myLoopjTask = new MyLoopjTask(this, this);.
Since your activity now implements OnLoopjCompleted, Android Studio will force you to implement the method taskCompleted. There, you can update the UI with the new data.
@Override
public void taskCompleted(String results) {
tvSearchResults.setText(results);
}
There you have it. When you run the app, all the data from your asynchronous HTTP request will be displayed to the user. Naturally, you will want to parse the received JSON data to extract just the parts you need. For example, you could display the movie poster by passing the poster image URL to Picasso.
In this tutorial, you've seen how to use Loopj, a library to perform asynchronous HTTP requests in Android. Loopj is easy to use with just a few lines of code. Now you don't have any excuse for not keeping your app up to date with content from your favourite web service!
As a module developer, more often than not you’ll need to create a custom schema in your day-to-day OpenCart custom module development. It’s already provisioned, as with the other frameworks, in the form of different hooks in the module architecture of OpenCart.
Before we go ahead and explore the aforementioned hooks, let’s explore the concept of extensions in OpenCart. Looking from the top, it’s an extension in OpenCart that allows you to enrich the core functionality of OpenCart. By installing it, you add features to the front-end store, be it a simple image gallery or some fancy-looking drag-and-drop functionality.
Further, the extensions, depending on the functionality they provide, are categorized into logical groups. As a quick example, the payment extension adds new payment methods in the front-end checkout, while it’s an anti-fraud extension that allows you to detect spam activities in your store. Head over to the back-end and have a look at the list under the Extensions menu that shows the different kinds of extensions supported in OpenCart.
You’ll be surprised to know that a module is also just an another kind of extension in OpenCart. Each extension is built around the common workflow of how things should work in the OpenCart ecosystem. And hooks allow you to perform certain actions based on specific events, whether it’s running an install hook during the module activation or cleaning up the garbage during uninstallation.
It’ll be those install and uninstall hooks that will be discussed throughout the course of this article. Although they’ll be discussed in the context of modules, I don’t see anything that stops you applying the same method to other kinds of extensions as well, so feel free to explore those files on your own.
It’s the latest version of OpenCart that provides the snippets spread over this tutorial. As of writing this, it’s the 2.1.0.2 stable version.
In this section, we’ll explore what exactly the install hook is used for. Go ahead and open admin/controller/extension/module.php in your favorite text editor, and find the install method. It should look something like this:
<?php
...
public function install() {
$this->load->language('extension/module');
$this->document->setTitle($this->language->get('heading_title'));
$this->load->model('extension/extension');
$this->load->model('extension/module');
if ($this->validate()) {
$this->model_extension_extension->install('module', $this->request->get['extension']);
$this->load->model('user/user_group');
$this->model_user_user_group->addPermission($this->user->getGroupId(), 'access', 'module/' . $this->request->get['extension']);
$this->model_user_user_group->addPermission($this->user->getGroupId(), 'modify', 'module/' . $this->request->get['extension']);
// Call install method if it exists
$this->load->controller('module/' . $this->request->get['extension'] . '/install');
$this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));
}
$this->getList();
}
...
?>
It’s the generic install hook for the module that will be called whenever you try to install any module from the back-end. Let’s go through the important parts of this method.
First, it loads the model files that are required for the subsequent activities. The $this->model_extension_extension->install method call makes sure that an entry is added to the database for this particular module.
Following that, there’s some ACL stuff, and it’s accomplished by calling the addPermission method. It makes sure that the current user, admin, should be able to access the module-specific settings and alter them.
Finally, it calls the install method of the module that’s being installed. Don’t get confused with the install method we’re already in—it’ll call the module specific install method if it exists.
For example, if you’re trying to install the Log In with PayPal module, it’ll call an install method defined in the file admin/controller/module/pp_login.php as shown below.
<?php
...
public function install() {
$this->load->model('extension/event');
$this->model_extension_event->addEvent('pp_login', 'post.customer.logout', 'module/pp_login/logout');
}
...
?>
Since the introduction of OpenCart 2.x, there are a few exciting features included, and event-observer is one of them. It allows you to add module-specific events, and other modules could set up observers for this event so that they could run some arbitrary code when that particular event is fired. And that’s exactly what's demonstrated in the above install method, which adds the post.customer.logout custom event!
In the case of the Log In with PayPal module, it was pretty simple stuff, but sometimes you’ll need more should you wish to inject a custom schema or something similar. Let’s pull in our install method from the PayPal Express Checkout payment extension. Go ahead and open admin/controller/payment/pp_express.php.
<?php
...
public function install() {
$this->load->model('payment/pp_express');
$this->model_payment_pp_express->install();
}
...
?>
First, it loads the corresponding model file, and using that it calls the install method of the model. As a rule of thumb, whenever you want to manipulate a schema, you should implement that code in the model's install method, rather than directly putting it in the controller's install method.
Now, let’s quickly pull in the install method defined in the model file admin/model/payment/pp_express.php.
<?php
...
public function install() {
$this->db->query("
CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order` (
`paypal_order_id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`date_added` DATETIME NOT NULL,
`date_modified` DATETIME NOT NULL,
`capture_status` ENUM('Complete','NotComplete') DEFAULT NULL,
`currency_code` CHAR(3) NOT NULL,
`authorization_id` VARCHAR(30) NOT NULL,
`total` DECIMAL( 10, 2 ) NOT NULL,
PRIMARY KEY (`paypal_order_id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
$this->db->query("
CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "paypal_order_transaction` (
`paypal_order_transaction_id` int(11) NOT NULL AUTO_INCREMENT,
`paypal_order_id` int(11) NOT NULL,
`transaction_id` CHAR(20) NOT NULL,
`parent_transaction_id` CHAR(20) NOT NULL,
`date_added` DATETIME NOT NULL,
`note` VARCHAR(255) NOT NULL,
`msgsubid` CHAR(38) NOT NULL,
`receipt_id` CHAR(20) NOT NULL,
`payment_type` ENUM('none','echeck','instant', 'refund', 'void') DEFAULT NULL,
`payment_status` CHAR(20) NOT NULL,
`pending_reason` CHAR(50) NOT NULL,
`transaction_entity` CHAR(50) NOT NULL,
`amount` DECIMAL( 10, 2 ) NOT NULL,
`debug_data` TEXT NOT NULL,
`call_data` TEXT NOT NULL,
PRIMARY KEY (`paypal_order_transaction_id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
}
...
?>
Finally, there's something to cheer about! As you can see, a couple of custom MySQL tables are created using the database API of OpenCart. So, this is the way to apply database-related changes using the install method of the model.
So, that's it as far as the install hook is concerned. I hope it's not as complicated as it seems to be at first glance. Let's put it this way. The process is commenced by triggering an extension-specific install method that in turn calls the install method of the extension being installed if it exists. Finally, the install method of the model is called from the controller's install method in case any database manipulation is needed by that extension.
This section, the counterpart of the previous section, highlights the happenings in the uninstall hook. We'll proceed in the same way as we did for the install method in the previous section, so let's straight away grab the code of the uninstall hook from the file admin/controller/extension/module.php.
<?php
...
public function uninstall() {
$this->load->language('extension/module');
$this->document->setTitle($this->language->get('heading_title'));
$this->load->model('extension/extension');
$this->load->model('extension/module');
if ($this->validate()) {
$this->model_extension_extension->uninstall('module', $this->request->get['extension']);
$this->model_extension_module->deleteModulesByCode($this->request->get['extension']);
$this->load->model('setting/setting');
$this->model_setting_setting->deleteSetting($this->request->get['extension']);
// Call uninstall method if it exists
$this->load->controller('module/' . $this->request->get['extension'] . '/uninstall');
$this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));
}
$this->getList();
}
...
?>
Again, it should look a bit familiar as most of it is the boilerplate code. The important snippet to start with is the call to the uninstall method that deletes the entry of the current extension being uninstalled from the extension MySQL table.
Next, it calls deleteModulesByCode, which deletes the modules associated with the extension. It's a special method that's only found in this module kind of extension—you won't find it in the other extensions like payment, shipping, fraud, etc.
The reason is that you could replicate every module to create multiple instances. For example, you could show different banner modules on different pages. On the other hand, it doesn't make any sense to replicate the other kind of extensions. Again as an example, there's only one instance required for the PayPal payment extension in the front-end.
Next, it deletes the configuration variables related to the module by calling the deleteSetting method. Finally, it calls the uninstall method of the module that’s being uninstalled.
Let's open admin/controller/module/pp_login.php to see how the uninstall method looks.
<?php
...
public function uninstall() {
$this->load->model('extension/event');
$this->model_extension_event->deleteEvent('pp_login');
}
...
?>
Pretty simple, huh? It's just undoing the stuff that was injected into the install method of the Log In with PayPal module. Recall that we created a new event post.customer.logout during the installation, so it's obvious that we need to delete it during uninstallation to make sure we don't leave any module-specific garbage.
Also, let's have a quick look at the uninstall method of the PayPal Express Checkout payment extension as we went through the install method of it in the earlier section. Grab the following snippet of admin/controller/payment/pp_express.php.
<?php
...
public function uninstall() {
$this->load->model('payment/pp_express');
$this->model_payment_pp_express->uninstall();
}
...
?>
Fairly expected stuff—it loads the model and calls the uninstall method. That also gives us a strong reason to open the model file admin/model/payment/pp_express.php and explore the uninstall method as well.
<?php
...
public function uninstall() {
$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order_transaction`;");
$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "paypal_order`;");
}
...
?>
We're just dropping the MySQL tables that were created earlier, as we don't want someone to ask us, "How could you leave this garbage?"
So, that was the story, hopefully nice, of install and uninstall hooks in OpenCart. The next and last section quickly wraps up the concepts learned so far in a simple, yet working, custom module, as that's something nice to have in your kitty post theory session.
In this section, we'll create an admin module demo that won't do much except to create a new schema during installation and drop it during uninstallation.
First, let's create a language file so that the module is picked up in the back-end. Go ahead and create a file admin/language/english/module/demo.php with the following contents.
<?php // Heading $_['heading_title'] = 'Demo Module';
Next, we need to create a model file that holds the actual and interesting code of our custom module. The model file should be placed at admin/model/module/demo.php. It creates a demo MySQL table in the install method and drops it in the uninstall method.
<?php
class ModelModuleDemo extends Model {
public function install() {
$this->db->query("
CREATE TABLE IF NOT EXISTS `" . DB_PREFIX . "demo` (
`demo_id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`demo_id`)
) ENGINE=MyISAM DEFAULT COLLATE=utf8_general_ci;");
}
public function uninstall() {
$this->db->query("DROP TABLE IF EXISTS `" . DB_PREFIX . "demo`;");
}
}
Finally, go ahead and create a controller file admin/controller/module/demo.php with the following contents.
<?php
class ControllerModuleDemo extends Controller {
public function install() {
$this->load->model('module/demo');
$this->model_module_demo->install();
}
public function uninstall() {
$this->load->model('module/demo');
$this->model_module_demo->uninstall();
}
}
It's straightforward, as it should be—it loads the model and calls the corresponding methods depending on the actions being performed.
Go ahead and give it a try. It should be listed as a Demo Module under Extensions > Modules. Install it and you should see the demo MySQL table created in the back-end, and of course don't forget to uninstall it to drop the table.
Today, we've discussed an important aspect of the OpenCart installation process, the install and uninstall hooks. We went through the details of those hooks, and in the later part of the article we built a simple module as a proof of concept.
Of course, queries and comments are always welcome!
#designs #HTML5 RT analyticbridge: RT KirkDBorne: 4 Skills You'll Need to Become a #DataScientist: … http://pic.twitter.com/1v3YoaCEgZ
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT KirkDBorne: Human Capital #Analytics > Are Pre-hire Talent Assessments part of a Predictive Talent Ac…
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT KirkDBorne: #BigData #Analytics Certs >> Important Certifications in #DataSc… http://pic.twitter.com/9DXLELIIlK
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT KirkDBorne: 1.#Python
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
2. R
3. SQL
4.#Hadoop
5. Java
Top 5 Tools & Languages for #DataScience: …
#designs #HTML5 RT analyticbridge: RT KirkDBorne: #DataScience is greater than the sum of its parts: … http://pic.twitter.com/3L8WO4ulSR
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT innova_scape: RT 12 #algorithms all #DataScientist Should Know … http://pic.twitter.com/bTWvgldGt5
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: The "Island of Games" Data Puzzle https://t.co/GDFvn6vt2z
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#softwareengine… Learn how to create a modern flat metro-style menu with flip effect using #CSS3https://t.co/An5mC84l3F
— Software Engineering (@DesignS0ftware) July 24, 2016
---#CSS #webdev …
#softwareengine… 3 excellent programming tips to write faster, more efficient #codehttps://t.co/hLXO3iCH1X
— Software Engineering (@DesignS0ftware) July 24, 2016
---#dev #coding #development …
#SocialMedia #code #webdev #webdevelopment 10 Rules for Creating a Cool, Effective and Viral #Infographic:
— Web Devel0pment (@webimprovenew4u) July 24, 2016
… http://pic.twitter.com/fwykiG66Rh
#designs #HTML5 RT techjunkiejh:#aspnet MVC 5 From Scratch : Create an https://t.co/zDXYcnQe3K MVC 5 Empty Projec… http://pic.twitter.com/R7K7wN1Nfr
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT techjunkiejh:Art Spotlight: Fantasy Game Environments https://t.co/2r126SVw5n #gamedev #gaming http://pic.twitter.com/SjMPEuYhFy
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT anitayorker: Google + open-source = TensorFlow - Data Science Central … https://t.co/WZVABaLXp1
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT autoDataSci: "Feature Engineering: Data scientist's Secret Sauce !" on Data … https://t.co/DHKIp1KL1J
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT DataScienceCtrl: Limitations of Deep Learning and strategic observations https://t.co/Zr1uS7roF0
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT simonlporter: How is Big Data Changing the World? – Data Science Central … http://pic.twitter.com/cvQX9jQPlE
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT analyticbridge: Origin of Techniques used in Data Science https://t.co/4FoNJJDrHh
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: RT analyticbridge: Invitation to join Data Science Central … http://pic.twitter.com/98RXxxPtyB
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#designs #HTML5 RT analyticbridge: Storytelling in Social Media Analytics: Beyond the Bar Chart II https://t.co/4fRriX6pYr
— Tool CSS Develop (@ToolCSSDevelop) July 24, 2016
#webdesign LIFETIME ACCESS: 500,000+ Stock Vectors, Illustrations and Icons https://t.co/10cgqmivKP #deal
— Web Devel0pment (@webimprovenew4u) July 24, 2016
#softwareengine… Prevent Delay on the Focus Event in #HTML5 #Apps for #Mobile Devices with #jQuery Mobilehttps://t.co/gF0i6k8sjh
— Software Engineering (@DesignS0ftware) July 24, 2016
---#UX …
#softwareengine… Perfect #CSS3 hexagons in any size using transform and calc()https://t.co/u3hlKNWVyo
— Software Engineering (@DesignS0ftware) July 24, 2016
---#webdev #CSS #webdesign #UX #UI…
#softwareengine… Making animated #CSS3 social buttonshttps://t.co/xqRg3x4D8x
— Software Engineering (@DesignS0ftware) July 24, 2016
---#UX #webdev #webdesign #UI
#SocialMedia #code #webdev #webdevelopment How Colour Can Impact the Kind of Customers Your #Business Attracts:
— Web Devel0pment (@webimprovenew4u) July 24, 2016
… http://pic.twitter.com/kFSIzJvLKs
#softwareengine… Make an animated image gallery percentage preloader with #CSS and #jQueryhttps://t.co/vGdtSy7u0a
— Software Engineering (@DesignS0ftware) July 24, 2016
---#webdev #UX #webdes…
#softwareengine… Creating a full-screen #responsive gallery with #CSS and the #Masonry #JavaScript libraryhttps://t.co/l3L8iYrsR7
— Software Engineering (@DesignS0ftware) July 24, 2016
---#U…
#SocialMedia #code #webdev #webdevelopment 13 #Twitter Stats You Need to Know to Maximise the Effect of Your Tweet… http://pic.twitter.com/hbjvlOhYgo
— Web Devel0pment (@webimprovenew4u) July 24, 2016
#softwareengine… Resizing, displaying and serving images on-the-fly with #Laravelhttps://t.co/RcQfmdqSbU
— Software Engineering (@DesignS0ftware) July 24, 2016
---#PHP #webdev
#softwareengine… How to use #AngularJS and #Laravel #Blade togetherhttps://t.co/p3A8SsIDjs
— Software Engineering (@DesignS0ftware) July 24, 2016
---#webdev #JavaScript #PHP
#SocialMedia #code #webdev #webdevelopment The 10 Most Effective Social Media Automation Tools for #Business:
— Web Devel0pment (@webimprovenew4u) July 24, 2016
… http://pic.twitter.com/Ye4ycYxj2v
#SocialMedia #code #webdev #webdevelopment How to Decide What Type of Logo is Right for Your #Business:
— Web Devel0pment (@webimprovenew4u) July 24, 2016
… http://pic.twitter.com/SzDtUN9fgg
#webdesign What’s new for designers, July 2016 https://t.co/HT0qi99bBH
— Web Devel0pment (@webimprovenew4u) July 24, 2016
#SocialMedia #code #webdev #webdevelopment 20 Rules Every Business Needs to Know Before Posting on #Instagram and … http://pic.twitter.com/PfTyFZFK2Y
— Web Devel0pment (@webimprovenew4u) July 24, 2016