【原文地址:】http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app
第一部分:演示如何开发一个简单的PHP/MySQL的web service
As an iPhone/iPad developer, it can be really useful to be able to write your own simple web services that integrate with your apps.
For example, you may wish to display some news updates that come from your web server, and display it on startup. Or perhaps store some user data “in the cloud”. Your imagination is the only limit!
In this first tutorial in this two-part series, you’ll go step-by-step through the process of creating a simple web service, based on a promo code system I included in my latest app, Wild Fables. In the next part of this series, you’ll write an iOS app that integrates with this web service!
To run through all of the steps on this tutorial, you’ll need a web server with MySQL and PHP. If you do not have a web server already, you have three options:
You don’t necessarily need to know PHP or MySQL to go through this tutorial (although it will be helpful!), as the tutorial includes all of the code you’ll need.
As you might know already if you’ve added In-App Purchases into your app, there is no built-in system provided by Apple to give out promo codes for your in-app purchases.
However, it can be extremely helpful to build your own promo code system for your in-app purchases, for several reasons:
So in this tutorial, we’re going to build a system where you can enter a code into your app, and it will connect to a web service to see if the code is valid or not. If it’s valid, the app will then “unlock” some content.
Don’t worry if you have no plans on adding this particular system into your app – you’ll learn the general technique of developing a web service and integrating it with an iPhone app as well!
The first step of this project is to create the database tables you’ll need. For the purposes of this tutorial, you’ll need three database tables:
Here are the MySQL statements you’ll need to create these tables:
DROP TABLE IF EXISTS rw_promo_code; DROP TABLE IF EXISTS rw_app; DROP TABLE IF EXISTS rw_promo_code_redeemed; CREATE TABLE rw_promo_code ( id mediumint NOT NULL AUTO_INCREMENT PRIMARY KEY, rw_app_id tinyint NOT NULL, code varchar(255) NOT NULL, unlock_code varchar(255) NOT NULL, uses_remaining smallint NOT NULL ); CREATE TABLE rw_app ( id mediumint NOT NULL AUTO_INCREMENT PRIMARY KEY, app_id varchar(255) NOT NULL ); CREATE TABLE rw_promo_code_redeemed ( id mediumint NOT NULL AUTO_INCREMENT PRIMARY KEY, rw_promo_code_id mediumint NOT NULL, device_id varchar(255) NOT NULL, redeemed_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
On your web server, you need to create a MySQL database and create the three tables as specified above. The way you do this varies depending on your web host, but just in case it’s useful I’ll tell you the steps I use on my web host, where I have full command-line access.
I save all of the above SQL statements to a file called create.sql, then I create and populate a new database with the following commands:
rwenderlich@kermit:~$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1286 Server version: 5.1.37-1ubuntu5.1-log (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database promos; Query OK, 1 row affected (0.00 sec) mysql> use promos; Database changed mysql> grant all privileges on promos.* to 'username'@'localhost' identified by 'password'; Query OK, 0 rows affected (0.00 sec) mysql> exit Bye rwenderlich@kermit:~$ mysql -u username -p promos < create.sql Enter password: rwenderlich@kermit:~$ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1417 Server version: 5.1.37-1ubuntu5.1-log (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use promos; Database changed mysql> show tables ; +------------------------+ | Tables_in_promos | +------------------------+ | rw_app | | rw_promo_code | | rw_promo_code_redeemed | +------------------------+ 3 rows in set (0.00 sec)
Now you should have three empty database tables in a new database. Next, go ahead and add a test app and a test code with the following statements:
INSERT INTO rw_app VALUES(1, 'com.razeware.test'); INSERT INTO rw_promo_code VALUES(1, 1, 'test', 'com.razeware.test.unlock.cake', 10000);
OK! Now that the database is connected and populated, on to writing the PHP web service!
Before you start implementing the PHP web service, first run a quick check to make sure PHP is working on your server OK. Create a new directory on your web server called promos, and create a new file inside called index.php with the following:
|
This is a very basic PHP file that create an instance of a class (RedeemAPI) and calls a method on it that just outputs “Hello, PHP!”
You can test this by navigating to the URL on your web server with your browser. Even better, you can test this on the command line with a handy utility called curl similar to the following (but replace the URL with your own):
Ray-Wenderlichs-Mac-mini-2:~ rwenderlich$ curl http://www.wildfables.com/promos/ Hello, PHP!
Next, extend the class to make sure the service can connect to your database OK by replacing the RedeemAPI class with the following:
|
This adds a constructor that connects to your database given a username and password and a destructor that closes the database connection. The redeem loop is modified to run a MySQL statement to select all of the entries in rw_promo_code, and loop through to print a line about each entry.
Once again you can test this with curl to make sure it’s working:
Ray-Wenderlichs-Mac-mini-2:~ rwenderlich$ curl http://www.wildfables.com/promos/ test has 10000 uses remaining!
OK, now that we know things are working, it’s almost time to implement the full behavior. But first, let’s talk about our strategy for the web service.
We know we need to pass some data from the iPhone app to our web service. Specifically, we need to tell the web service the ID of the app, the code to redeem, and the device id that is trying to redeem.
But how can we pass this data? If you aren’t familiar already, there are two ways to pass data to a web service – via GET (the normal way), or via POST (typically used for posting data to a web form).
Depending on which one you choose, the parameters get passed differently:
Either one would work, but usually when you’re trying to “do something” like redeem a code (rather than just passively retrieving data), you would pick the POST method, so that’s what we’re goint to do here.
What does this mean in practice? All it means is if we want to access the passed parameters in PHP, we get them from the built in $_POST array, as follows:
|
And when we’re using ASIHTTPRequest to connect to the web service later, we’ll use the ASIFormDataRequest class, which sends the request as a POST, as follows:
|
For more information on GET vs POST, check out the Wikipedia entry on the HTTP protocol.
Update: Also, check out @smpdawg’s comment in the forum topic for this tutorial some additional must-read tips and info on this!
Next, let’s go over the general algorithm the web service will take:
OK now that we have a strategy in hand, onto the implementation!
First, add two helper methods to the top of your PHP file that you’ll use to easily return HTTP status messages on success and failure:
|
If you’re confused why we need this, since this is a web service that conforms to the HTTP protocol, when you send a response you can give a header that specifies any error code and descripton that occurs. There are standard error codes to use, so these methods help make that a bit easier to work with.
As you can see, I found the function to convert status codes to HTML messages from a great tutorial oncreating a REST API with PHP.
Next, onto the actual implementation! Replace your redeem method with the following:
|
You should be able to understand the general idea of how things work here by looking at the comments inline with the code, and if you’re more curious check out the Mysqli reference. Also, here’s a few things I’d like to point out:
And that’s it – your web service is ready to roll! You can test it with the following curl command:
curl -F "rw_app_id=1" -F "code=test" -F "device_id=test" http://www.wildfables.com/promos/ {"unlock_code":"com.razeware.wildfables.unlock.test"}
Note that if you are trying this on my web service, if you get a “code already used” error, you should change your device_id (since each one can only be used once!)
You may also wish to go into your database and check that there’s an entry in your rw_promo_code_redeemed table, that the uses_remaining has decremented, etc. Play around with it a bit!
Here is the source code for the web service we’ve developed in the above tutorial.
Stay tuned for the next tutorial in the series, where we’ll show how to create an iPhone app that integrates with this web service, and also discuss my experience with using this promo code system in Wild Fables!
If you have any questions about this tutorial, or tips for others making web services for iPhone apps, please join the forum discussion below!