React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

[[email protected] ~]$ whoami
myth
[[email protected] ~]$ pwd
/home/myth

单向数字证书
[[email protected] ~]# openssl genrsa -out ca-app.key 2048    ## 1). 生成一个CA私钥
Generating RSA private key, 2048 bit long modulus
.......................................................................................................................................................+++
..........+++
e is 65537 (0x10001)
[[email protected] ~]# openssl req -x509 -new -nodes -key ca-app.key -days 365 -out ca-app.crt   ## 2).使用ca-app私钥生成客户端的数字证书
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg, city) [Default City]:ShenZhen
Organization Name (eg, company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg, section) []:                    ## 直接按回车键跳过
Common Name (eg, your name or your server's hostname) []:mo.com
Email Address []:[email protected]
[[email protected] ~]# cp ca-app.key  /etc/pki/tls/private/
[[email protected] ~]# cp ca-app.crt  /etc/pki/tls/certs/
私钥文件   ca-app.key
数字证书   ca-app.crt

你学习PHP很久了,还搞不定Apache在PHP开发时项目的执行和读写访问权限问题

直接在httpd.conf配置文件查看apache执行用户和执行组,在以下红色字体标识的66行和67行即是用户和用户组,我们要把第66行和第67行改成如下的样子,其中myth是我登录CentOS 7.2系统的用户名

    66  User myth

    67  Group myth

[[email protected] ~]# cat -n /etc/httpd/conf/httpd.conf
     1  #
     2  # This is the main Apache HTTP server configuration file.  It contains the
     3  # configuration directives that give the server its instructions.
     4  # See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
     5  # In particular, see
     6  # <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
     7  # for a discussion of each configuration directive.
     8  #
     9  # Do NOT simply read the instructions in here without understanding
    10  # what they do.  They're here only as hints or reminders.  If you are unsure
    11  # consult the online docs. You have been warned.  
    12  #
    13  # Configuration and logfile names: If the filenames you specify for many
    14  # of the server's control files begin with "/" (or "drive:/" for Win32), the
    15  # server will use that explicit path.  If the filenames do *not* begin
    16  # with "/", the value of ServerRoot is prepended -- so 'log/access_log'
    17  # with ServerRoot set to '/www' will be interpreted by the
    18  # server as '/www/log/access_log', where as '/log/access_log' will be
    19  # interpreted as '/log/access_log'.
    20
    21  #
    22  # ServerRoot: The top of the directory tree under which the server's
    23  # configuration, error, and log files are kept.
    24  #
    25  # Do not add a slash at the end of the directory path.  If you point
    26  # ServerRoot at a non-local disk, be sure to specify a local disk on the
    27  # Mutex directive, if file-based mutexes are used.  If you wish to share the
    28  # same ServerRoot for multiple httpd daemons, you will need to change at
    29  # least PidFile.
    30  #
    31  ServerRoot "/etc/httpd"
    32
    33  #
    34  # Listen: Allows you to bind Apache to specific IP addresses and/or
    35  # ports, instead of the default. See also the <VirtualHost>
    36  # directive.
    37  #
    38  # Change this to Listen on specific IP addresses as shown below to
    39  # prevent Apache from glomming onto all bound IP addresses.
    40  #
    41  #Listen 12.34.56.78:80
    42  Listen 80
    43
    44  #
    45  # Dynamic Shared Object (DSO) Support
    46  #
    47  # To be able to use the functionality of a module which was built as a DSO you
    48  # have to place corresponding `LoadModule' lines at this location so the
    49  # directives contained in it are actually available _before_ they are used.
    50  # Statically compiled modules (those listed by `httpd -l') do not need
    51  # to be loaded here.
    52  #
    53  # Example:
    54  # LoadModule foo_module modules/mod_foo.so
    55  #
    56  Include conf.modules.d/*.conf
    57
    58  #
    59  # If you wish httpd to run as a different user or group, you must run
    60  # httpd as root initially and it will switch.  
    61  #
    62  # User/Group: The name (or #number) of the user/group to run httpd as.
    63  # It is usually good practice to create a dedicated user and group for
    64  # running httpd, as with most system services.
    65  #
    66  User apache
    67  Group apache

    68
    69  # 'Main' server configuration
    70  #
    71  # The directives in this section set up the values used by the 'main'
    72  # server, which responds to any requests that aren't handled by a
    73  # <VirtualHost> definition.  These values also provide defaults for
    74  # any <VirtualHost> containers you may define later in the file.
    75  #
    76  # All of these directives may appear inside <VirtualHost> containers,
    77  # in which case these default settings will be overridden for the
    78  # virtual host being defined.
    79  #
    80
    81  #
    82  # ServerAdmin: Your address, where problems with the server should be
    83  # e-mailed.  This address appears on some server-generated pages, such
    84  # as error documents.  e.g. [email protected]
    85  #
    86  ServerAdmin [email protected]
    87
    88  #
    89  # ServerName gives the name and port that the server uses to identify itself.
    90  # This can often be determined automatically, but we recommend you specify
    91  # it explicitly to prevent problems during startup.
    92  #
    93  # If your host doesn't have a registered DNS name, enter its IP address here.
    94  #
    95  ServerName corp.contoso.org:80
    96
    97  #
    98  # Deny access to the entirety of your server's filesystem. You must
    99  # explicitly permit access to web content directories in other
   100  # <Directory> blocks below.
   101  #
   102  <Directory />
   103      AllowOverride none
   104      Require all denied
   105  </Directory>
   106
   107  #
   108  # Note that from this point forward you must specifically allow
   109  # particular features to be enabled - so if something's not working as
   110  # you might expect, make sure that you have specifically enabled it
   111  # below.
   112  #
   113
   114  #
   115  # DocumentRoot: The directory out of which you will serve your
   116  # documents. By default, all requests are taken from this directory, but
   117  # symbolic links and aliases may be used to point to other locations.
   118  #
   119  DocumentRoot "/var/www/html"
   120
   121  #
   122  # Relax access to content within /var/www.
   123  #
   124  <Directory "/var/www">
   125      AllowOverride None
   126      # Allow open access:
   127      Require all granted
   128  </Directory>
   129
   130  # Further relax access to the default document root:
   131  <Directory "/var/www/html">
   132      #
   133      # Possible values for the Options directive are "None", "All",
   134      # or any combination of:
   135      #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
   136      #
   137      # Note that "MultiViews" must be named *explicitly* --- "Options All"
   138      # doesn't give it to you.
   139      #
   140      # The Options directive is both complicated and important.  Please see
   141      # http://httpd.apache.org/docs/2.4/mod/core.html#options
   142      # for more information.
   143      #
   144      Options Indexes FollowSymLinks
   145
   146      #
   147      # AllowOverride controls what directives may be placed in .htaccess files.
   148      # It can be "All", "None", or any combination of the keywords:
   149      #   Options FileInfo AuthConfig Limit
   150      #
   151      AllowOverride None
   152
   153      #
   154      # Controls who can get stuff from this server.
   155      #
   156      Require all granted
   157  </Directory>
   158
   159  #
   160  # DirectoryIndex: sets the file that Apache will serve if a directory
   161  # is requested.
   162  #
   163  <IfModule dir_module>
   164      DirectoryIndex index.html
   165  </IfModule>
   166
   167  #
   168  # The following lines prevent .htaccess and .htpasswd files from being
   169  # viewed by Web clients.
   170  #
   171  <Files ".ht*">
   172      Require all denied
   173  </Files>
   174
   175  #
   176  # ErrorLog: The location of the error log file.
   177  # If you do not specify an ErrorLog directive within a <VirtualHost>
   178  # container, error messages relating to that virtual host will be
   179  # logged here.  If you *do* define an error logfile for a <VirtualHost>
   180  # container, that host's errors will be logged there and not here.
   181  #
   182  ErrorLog "logs/error_log"
   183
   184  #
   185  # LogLevel: Control the number of messages logged to the error_log.
   186  # Possible values include: debug, info, notice, warn, error, crit,
   187  # alert, emerg.
   188  #
   189  LogLevel warn
   190
   191  <IfModule log_config_module>
   192      #
   193      # The following directives define some format nicknames for use with
   194      # a CustomLog directive (see below).
   195      #
   196      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
   197      LogFormat "%h %l %u %t \"%r\" %>s %b" common
   198
   199      <IfModule logio_module>
   200        # You need to enable mod_logio.c to use %I and %O
   201        LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
   202      </IfModule>
   203
   204      #
   205      # The location and format of the access logfile (Common Logfile Format).
   206      # If you do not define any access logfiles within a <VirtualHost>
   207      # container, they will be logged here.  Contrariwise, if you *do*
   208      # define per-<VirtualHost> access logfiles, transactions will be
   209      # logged therein and *not* in this file.
   210      #
   211      #CustomLog "logs/access_log" common
   212
   213      #
   214      # If you prefer a logfile with access, agent, and referer information
   215      # (Combined Logfile Format) you can use the following directive.
   216      #
   217      CustomLog "logs/access_log" combined
   218  </IfModule>
   219
   220  <IfModule alias_module>
   221      #
   222      # Redirect: Allows you to tell clients about documents that used to
   223      # exist in your server's namespace, but do not anymore. The client
   224      # will make a new request for the document at its new location.
   225      # Example:
   226      # Redirect permanent /foo http://www.example.com/bar
   227
   228      #
   229      # Alias: Maps web paths into filesystem paths and is used to
   230      # access content that does not live under the DocumentRoot.
   231      # Example:
   232      # Alias /webpath /full/filesystem/path
   233      #
   234      # If you include a trailing / on /webpath then the server will
   235      # require it to be present in the URL.  You will also likely
   236      # need to provide a <Directory> section to allow access to
   237      # the filesystem path.
   238
   239      #
   240      # ScriptAlias: This controls which directories contain server scripts.
   241      # ScriptAliases are essentially the same as Aliases, except that
   242      # documents in the target directory are treated as applications and
   243      # run by the server when requested rather than as documents sent to the
   244      # client.  The same rules about trailing "/" apply to ScriptAlias
   245      # directives as to Alias.
   246      #
   247      ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
   248
   249  </IfModule>
   250
   251  #
   252  # "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
   253  # CGI directory exists, if you have that configured.
   254  #
   255  <Directory "/var/www/cgi-bin">
   256      AllowOverride None
   257      Options None
   258      Require all granted
   259  </Directory>
   260
   261  <IfModule mime_module>
   262      #
   263      # TypesConfig points to the file containing the list of mappings from
   264      # filename extension to MIME-type.
   265      #
   266      TypesConfig /etc/mime.types
   267
   268      #
   269      # AddType allows you to add to or override the MIME configuration
   270      # file specified in TypesConfig for specific file types.
   271      #
   272      #AddType application/x-gzip .tgz
   273      #
   274      # AddEncoding allows you to have certain browsers uncompress
   275      # information on the fly. Note: Not all browsers support this.
   276      #
   277      #AddEncoding x-compress .Z
   278      #AddEncoding x-gzip .gz .tgz
   279      #
   280      # If the AddEncoding directives above are commented-out, then you
   281      # probably should define those extensions to indicate media types:
   282      #
   283      AddType application/x-compress .Z
   284      AddType application/x-gzip .gz .tgz
   285
   286      #
   287      # AddHandler allows you to map certain file extensions to "handlers":
   288      # actions unrelated to filetype. These can be either built into the server
   289      # or added with the Action directive (see below)
   290      #
   291      # To use CGI scripts outside of ScriptAliased directories:
   292      # (You will also need to add "ExecCGI" to the "Options" directive.)
   293      #
   294      #AddHandler cgi-script .cgi
   295
   296      # For type maps (negotiated resources):
   297      #AddHandler type-map var
   298
   299      #
   300      # Filters allow you to process content before it is sent to the client.
   301      #
   302      # To parse .shtml files for server-side includes (SSI):
   303      # (You will also need to add "Includes" to the "Options" directive.)
   304      #
   305      AddType text/html .shtml
   306      AddOutputFilter INCLUDES .shtml
   307  </IfModule>
   308
   309  #
   310  # Specify a default charset for all content served; this enables
   311  # interpretation of all content as UTF-8 by default.  To use the
   312  # default browser choice (ISO-8859-1), or to allow the META tags
   313  # in HTML content to override this choice, comment out this
   314  # directive:
   315  #
   316  AddDefaultCharset UTF-8
   317
   318  <IfModule mime_magic_module>
   319      #
   320      # The mod_mime_magic module allows the server to use various hints from the
   321      # contents of the file itself to determine its type.  The MIMEMagicFile
   322      # directive tells the module where the hint definitions are located.
   323      #
   324      MIMEMagicFile conf/magic
   325  </IfModule>
   326
   327  #
   328  # Customizable error responses come in three flavors:
   329  # 1) plain text 2) local redirects 3) external redirects
   330  #
   331  # Some examples:
   332  #ErrorDocument 500 "The server made a boo boo."
   333  #ErrorDocument 404 /missing.html
   334  #ErrorDocument 404 "/cgi-bin/missing_handler.pl"
   335  #ErrorDocument 402 http://www.example.com/subscription_info.html
   336  #
   337
   338  #
   339  # EnableMMAP and EnableSendfile: On systems that support it,
   340  # memory-mapping or the sendfile syscall may be used to deliver
   341  # files.  This usually improves server performance, but must
   342  # be turned off when serving from networked-mounted
   343  # filesystems or if support for these functions is otherwise
   344  # broken on your system.
   345  # Defaults if commented: EnableMMAP On, EnableSendfile Off
   346  #
   347  #EnableMMAP off
   348  EnableSendfile on
   349
   350  # Supplemental configuration
   351  #
   352  # Load config files in the "/etc/httpd/conf.d" directory, if any.
   353  IncludeOptional conf.d/*.conf


[[email protected] ~]# exit
logout
[[email protected] ~]$

创建基于ThinkPHP 5.1 框架PHP项目 ------ moapp,退出root账户的命令模式环境安装框架并创建moapp项目:

[[email protected] ~]$ cd /home/myth/www && composer create-project topthink/think moapp --prefer-dist

配置操作Users数据表的路由:

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

/home/myth/www/moapp/route/route.php

<?php
// if you use Postman to test PUT method,you must select Body and x-www-form-urlencoded to auto config header

Route::get('users/:id', 'index/User/getUserById');        // GET    http://mo.com/users/2
Route::post('users', 'index/User/addUser');               // POST   http://mo.com/users
Route::delete('users/:id', 'index/User/deleteUserById');  // DELETE http://mo.com/users/2
Route::put('users', 'index/User/updateUserById');         // PUT    http://mo.com/users
Route::get('users', 'index/User/index');                  // GET    http://mo.com/users
return [

];

实现控制器操作数据库Users表的方法:

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

/home/myth/www/moapp/application/index/controller/User.php
<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;

class User extends Controller {

    public function index() {
        $users = Db::table('users')->select();
        return json($users);
    }

    public function getUserById($id) {
        //$user = Db::name('users')->where('id',$id)->find();
        // find() method to query format json:
        // {"id":2,"name":"Jason","email":"[email protected]","mobile":"1380013800"}
        // if you use find() method ,then Andorid&iPhone will throw a TypeError: data.map is not a function
        $user = Db::name('users')->where('id', $id)->select();
        // select() method to query format json:
        // [{"id":2,"name":"Jason","email":"[email protected]","mobile":"1380013800"}]
        return json($user);
    }

    public function addUser(Request $request) {
        $name = $request->param('name');
        $email = $request->param('email');
        $mobile = $request->param('mobile');
        $user = ['name' => $name, 'email' => $email, 'mobile' => $mobile];
        // 启动事务
        Db::startTrans();
        try {
            Db::name('users')->insert($user);
            // 提交事务
            Db::commit();
        } catch (Exception $ex) {
            // 回滚事务
            Db::rollback();
        }
    }

    public function deleteUserById($id) {
        // 启动事务
        Db::startTrans();
        try {
            Db::name('users')->where('id', $id)->delete();
            // 提交事务
            Db::commit();
        } catch (Exception $ex) {
            // 回滚事务
            Db::rollback();
        }
        return json(['rows'=>'successfully']);
    }

    public function updateUserById(Request $request) {
        $id = $request->param('id');
        $name = $request->param('name');
        $email = $request->param('email');
        $mobile = $request->param('mobile');
        $user = ['name' => $name, 'email' => $email, 'mobile' => $mobile];
        // 启动事务
        Db::startTrans();
        try {
            Db::table('users')->where('id', $id)->update($user);
            // 提交事务
            Db::commit();
        } catch (Exception $ex) {
            // 回滚事务
            Db::rollback();
        }
    }

}

配置Apache服务器:

[[email protected] ~]$ cat > /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.123.198   mo.com


[[email protected] ~]$ cat > /etc/httpd/conf.d/httpd-vhosts.conf

<Directory "/home/myth/www/moapp">
        Options +Indexes +FollowSymLinks
        Order allow,deny
        Allow from all
        AllowOverride All
        Require all granted
</Directory>
<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot "/home/myth/www/moapp/public"
    ServerName mo.com
    ServerAlias mo.com
    ErrorLog "/home/myth/log/httpd/mo-com-error_log"
    CustomLog "/home/myth/log/httpd/mo-com-access_log" common
</VirtualHost>
<Directory "/home/myth/www/moapp">
        Options +Indexes +FollowSymLinks
        Order allow,deny
        Allow from all
        AllowOverride All
        Require all granted
</Directory>
<VirtualHost *:443>
    SSLEngine on                
    SSLCertificateFile /etc/pki/tls/certs/ca-app.crt                           
    SSLCertificateKeyFile /etc/pki/tls/private/ca-app.key                        
    # SSLCertificateChainFile /etc/pki/tls/certs/ca-app.pem
    ServerAdmin [email protected]
    DocumentRoot "/home/myth/www/moapp/public"
    ServerName mo.com
    ServerAlias mo.com
    ErrorLog "/home/myth/log/httpd/mo-com-s-error_log"
    CustomLog "/home/myth/log/httpd/mo-com-s-access_log" common
</VirtualHost>

[[email protected] ~]$ su -
Password:
Last login: Mon Apr  2 14:11:31 CST 2018 on pts/1
[[email protected] ~]#  lsof -i:80
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd    1069 root    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1315 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1316 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1317 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1318 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    1319 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd    2860 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd   18468 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
httpd   18688 myth    4u  IPv6  23009      0t0  TCP *:http (LISTEN)
[[email protected] ~]# systemctl restart httpd  && systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-04-03 23:44:21 CST; 13ms ago
     Docs: man:httpd(8)
           man:apachectl(8)
  Process: 47406 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
 Main PID: 47415 (httpd)
   Status: "Processing requests..."
   CGroup: /system.slice/httpd.service
           ├─47415 /usr/sbin/httpd -DFOREGROUND
           ├─47416 /usr/sbin/httpd -DFOREGROUND
           ├─47417 /usr/sbin/httpd -DFOREGROUND
           ├─47419 /usr/sbin/httpd -DFOREGROUND
           ├─47420 /usr/sbin/httpd -DFOREGROUND
           └─47421 /usr/sbin/httpd -DFOREGROUND

Apr 03 23:44:21 contoso.org systemd[1]: Starting The Apache HTTP Server...

Apr 03 23:44:21 contoso.org systemd[1]: Started The Apache HTTP Server.

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

配置macOS系统的hosts文件 ------ macOS这台机器是react-native这台开发机器

myths-Mac:~ myth$ sudo su

Password:
sh-3.2# cat > /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1    localhost
255.255.255.255    broadcasthost
::1             localhost
192.168.123.198  mo.com

创建项目 ------ zigoo

myths-Mac:~ myth$ react-native init zigoo

接下来我们要在macOS系统的命令行终端里通过命令去修改Android手机模拟器它的操作系统对应的hosts文件,修改它就有点特别啦,请按我的顺序执行指令,注意可能你的设备名称显示出来跟我的不一样,你需要开启两个终端窗口,一个用来首先用来启动安卓模拟用的,另外一个用来修改hosts文件用的,请特别注意192.168.123.198这个IP改成你实际的IP地址,本范例是在VMWare workstation pro 12 中实验的 1台PHP部署环境 用的系统是CentOS 7.2 另外一台开发react-native的机器是macOS系统

如果你已经有安卓模拟打开了 就必须关闭它们,那我们先来用命令以可写信息的模式来启动安卓模拟器吧:

电脑macOS系统中的命令终端窗口1,你发现自己emulator命令不是全局目录命令,

请参考我其它篇幅中讲的1条指令搞定配置部分

myths-Mac:~ emulator -list-avds  #列出所有模拟器

Nexus_5X_API_23

myths-Mac:~ emulator -avd Nexus_5X_API_23 -writable-system  #以可写信息的模式来启动安卓模拟器

电脑macOS系统中的命令终端窗口2,开始修改手机的hosts文件

myths-Mac:~ myth$ adb shell cat /etc/hosts

127.0.0.1       localhost
::1             ip6-localhost
myths-Mac:~ myth$ adb root
adbd is already running as root
myths-Mac:~ myth$ adb remount
remount succeeded
myths-Mac:~ myth$ adb pull /system/etc/hosts ~/Desktop/hosts
/system/etc/hosts: 1 file pulled. 0.0 MB/s (56 bytes in 0.003s)
myths-Mac:~ myth$ echo '192.168.123.198  mo.com' >> ~/Desktop/hosts
myths-Mac:~ myth$ cat ~/Desktop/hosts
127.0.0.1       localhost
::1             ip6-localhost

192.168.123.198  mo.com
myths-Mac:~ myth$ adb push ~/Desktop/hosts /system/etc/hosts
/Users/myth/Desktop/hosts: 1 file pushed. 0.0 MB/s (81 bytes in 0.005s)
myths-Mac:~ myth$ adb shell cat /etc/hosts
127.0.0.1       localhost
::1             ip6-localhost

192.168.123.198  mo.com

我们可以用手机模拟器中的浏览器测试一下 http://mo.com/users是否能跨系统访问:

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

最后我把手机端的react-native项目代码贴出来

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  TextInput,
  View,
  ScrollView,
  TouchableHighlight
} from 'react-native';

export default class App extends Component {
  constructor(props){
    super(props)
    this.state = {
        apiData: [],
        naData: []
    }
    this.uid = null;
    this.name = null;
    this.email = null;
    this.mobile = null;
  }

onGetUsers = () => {
   fetch('http://mo.com/users',{
     method: 'GET'
   }).then((response) => {
     return response.json();
   }).then((jsonData) => {
        this.setState({
         apiData: jsonData,
        })
        console.log(this.state.apiData);
      })
      .catch((error) => {
        console.warn(error);
      }).done();
      this.uid = null;
  }

    onPostUser = () => {
     fetch('http://mo.com/users',{
       method: 'POST',
       headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
       },
       body: JSON.stringify({ name: this.name, email: this.email, mobile: this.mobile })
     }).then((response) => {
       return response.json();
     }).then((jsonData) => {
          this.setState({
           naData: jsonData,
          })
          console.log(this.state.naData);
        })
        .catch((error) => {
          console.warn(error);
        }).done();
        this.uid = null;
        this.name = null;
        this.email = null;
        this.mobile = null;
    }

  onGetUser = () => {
   fetch('http://mo.com/users/'+ this.uid,{
     method: 'GET'
   }).then((response) => {
     return response.json();
   }).then((jsonData) => {
        this.setState({
         apiData: jsonData,
        })
        console.log(this.state.apiData);
      })
      .catch((error) => {
        console.warn(error);
      }).done();
      this.uid = null;
  }

    onDeleteUser = () => {
     fetch('http://mo.com/users/'+ this.uid,{
        method: 'DELETE'
     }).then((response) => {
        console.log(response.rows);
     }).catch((error) => {
        console.warn(error);
     }).done();
        this.uid = null;
    }

  onPutUser = () => {
     fetch('http://mo.com/users',{
       method: 'PUT',
       headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
       },
       body: JSON.stringify({ name: this.name, email: this.email, mobile: this.mobile, id: this.uid })
     }).then((response) => {
       return response.json();
     }).catch((error) => {
          console.warn(error);
        }).done();
        this.uid = null;
        this.name = null;
        this.email = null;
        this.mobile = null;
  }

  render() {
  const data = this.state.apiData;
    let dataDisplay = data.map(function(jsonData){
        return (
            <View key={jsonData.id}>
               <View style={{flexDirection: 'row'}}>
                  <Text style={{color: '#000',width: 30}}>{jsonData.id}</Text>
                  <Text style={{color: '#00f',width: 60}}>{jsonData.name}</Text>
                  <Text style={{color: '#000',width: 140}}>{jsonData.email}</Text>
                  <Text style={{color: '#00f',width: 100}}>{jsonData.mobile}</Text>
               </View>
             </View>
        )
    });
    return (
      <View style={styles.container}>
        <Text style={{fontSize: 20, textAlign: 'center',marginTop: 10}}>
          My App Users
        </Text>
        <View style={{height: 2, backgroundColor: '#ccc', marginBottom: 10, width: '90%'}}></View>
        <TextInput style={styles.input}
            placeholder = 'id'
            onChangeText ={(text) => {this.uid = text}}
            value = {this.id}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'name'
            onChangeText ={(text) => {this.name = text}}
            value = {this.name}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'email'
            onChangeText ={(text) => {this.email = text}}
            value = {this.email}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'mobile'
            onChangeText ={(text) => {this.mobile = text}}
            value = {this.mobile}
            underlineColorAndroid = 'transparent'
        />
        <TouchableHighlight style={styles.button} onPress={this.onGetUsers}>
            <Text style={styles.buttonText}>GET All Users</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onPostUser}>
            <Text style={styles.buttonText}>POST a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onGetUser}>
            <Text style={styles.buttonText}>GET a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onDeleteUser}>
            <Text style={styles.buttonText}>DELETE a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onPutUser}>
            <Text style={styles.buttonText}>PUT a User</Text>
        </TouchableHighlight>
        <ScrollView contentContainerStyle={styles.container}>
            {dataDisplay}
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop: 5,
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  input: {
    textAlign: 'left',
    height: 30,
    width: '90%',
    padding: 4,
    marginBottom: 7,
    fontSize: 16,
    fontWeight:'500',
    borderWidth: 1,
  },
  button: {
    paddingTop: 10,
    paddingBottom: 10,
    borderRadius: 25,
    marginTop: 3,
    marginBottom: 3,
    width: '90%',
    backgroundColor: '#00bcd4'
  },
  buttonText: {
    color: '#fff',
    textAlign: 'center',
    fontSize:16,
    fontWeight:'500',
  }

});

如果你想掌握快速调试react-native的技巧,请照我贴的图和上面的文字说明操作吧,会快速调试代码是自己快速解决问题最基本的能力 一定要学会掌握,不然一旦出问题你就傻眼了

React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口React-Native如何调用PHP实现的服务器端接口 ------ Apache + ThinkPHP 5.1 + MySQL 实现的Restful API风格的数据访问接口

如果你不喜欢使用fetch的方式去操作数据库的Restful API接口,我们还可以使用axios插件去操作数据库的Restful API接口

$ cd  /Users/myth/zigoo && yarn add axios    #安装 axios 插件

App.js 完整的代码如下:

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  TextInput,
  View,
  ScrollView,
  TouchableHighlight
} from 'react-native';

import axios from 'axios';

export default class App extends Component {
  constructor(props){
    super(props)
    this.state = {
        apiData: [],
        naData: []
    }
    this.uid = null;
    this.name = null;
    this.email = null;
    this.mobile = null;
  }

onGetUsers = () => {
   axios.get('http://mo.com/users')
      .then(response => {
         this.setState({ apiData: response.data });
      })
       .catch(function (error) {
          console.log(error);
      });
      this.uid = null;
  }

    onPostUser = () => {
      axios({
          method: 'post',
          url: 'http://mo.com/users',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          data: {
            name: this.name,
            email: this.email,
            mobile: this.mobile
          }
     }).then((response) => {
          //接收restful-api新增记录成功还返回一条成功的提示消息
          this.setState({
           naData: response.data,
          })
          console.log(this.state.naData);
        })
        .catch((error) => {
          console.warn(error);
        })
        this.uid = null;
        this.name = null;
        this.email = null;
        this.mobile = null;

    }

  onGetUser = () => {
     axios.get('http://mo.com/users/'+ this.uid)
        .then(response => {
           this.setState({ apiData: response.data });
        })
         .catch(function (error) {
            console.log(error);
        });
      this.uid = null;
  }

    onDeleteUser = () => {
       axios({
           method: 'delete',
           url: 'http://mo.com/users/'+ this.uid
      }).then((response) => {
           //接收restful-api删除记录成功还返回一条成功的提示消息
           this.setState({
            naData: response.data,
           })
           console.log(this.state.naData);
         })
         .catch((error) => {
           console.warn(error);
         })
        this.uid = null;
    }

  onPutUser = () => {
      axios({
          method: 'put',
          url: 'http://mo.com/users',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          data: {
            name: this.name,
            email: this.email,
            mobile: this.mobile,
            id: this.uid
          }
      }).then((response) => {
          //接收restful-api更新记录成功还返回一条成功的提示消息
          this.setState({
           naData: response.data,
          })
          console.log(this.state.naData);
        })
        .catch((error) => {
          console.warn(error);
        })
        this.uid = null;
        this.name = null;
        this.email = null;
        this.mobile = null;
  }

  render() {
  const data = this.state.apiData;
    let dataDisplay = data.map(function(jsonData){
        return (
            <View key={jsonData.id}>
               <View style={{flexDirection: 'row'}}>
                  <Text style={{color: '#000',width: 30}}>{jsonData.id}</Text>
                  <Text style={{color: '#00f',width: 60}}>{jsonData.name}</Text>
                  <Text style={{color: '#000',width: 140}}>{jsonData.email}</Text>
                  <Text style={{color: '#00f',width: 100}}>{jsonData.mobile}</Text>
               </View>
             </View>
        )
    });
    return (
      <View style={styles.container}>
        <Text style={{fontSize: 20, textAlign: 'center',marginTop: 10}}>
          My App Users
        </Text>
        <View style={{height: 2, backgroundColor: '#ccc', marginBottom: 10, width: '90%'}}></View>
        <TextInput style={styles.input}
            placeholder = 'id'
            onChangeText ={(text) => {this.uid = text}}
            value = {this.id}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'name'
            onChangeText ={(text) => {this.name = text}}
            value = {this.name}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'email'
            onChangeText ={(text) => {this.email = text}}
            value = {this.email}
            underlineColorAndroid = 'transparent'
        />
        <TextInput style={styles.input}
            placeholder = 'mobile'
            onChangeText ={(text) => {this.mobile = text}}
            value = {this.mobile}
            underlineColorAndroid = 'transparent'
        />
        <TouchableHighlight style={styles.button} onPress={this.onGetUsers}>
            <Text style={styles.buttonText}>GET All Users</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onPostUser}>
            <Text style={styles.buttonText}>POST a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onGetUser}>
            <Text style={styles.buttonText}>GET a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onDeleteUser}>
            <Text style={styles.buttonText}>DELETE a User</Text>
        </TouchableHighlight>
        <TouchableHighlight style={styles.button} onPress={this.onPutUser}>
            <Text style={styles.buttonText}>PUT a User</Text>
        </TouchableHighlight>
        <ScrollView contentContainerStyle={styles.container}>
            {dataDisplay}
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    marginTop: 5,
    flex: 1,
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  input: {
    textAlign: 'left',
    height: 30,
    width: '90%',
    padding: 4,
    marginBottom: 7,
    fontSize: 16,
    fontWeight:'500',
    borderWidth: 1,
  },
  button: {
    paddingTop: 10,
    paddingBottom: 10,
    borderRadius: 25,
    marginTop: 3,
    marginBottom: 3,
    width: '90%',
    backgroundColor: '#00bcd4'
  },
  buttonText: {
    color: '#fff',
    textAlign: 'center',
    fontSize:16,
    fontWeight:'500',
  }
});