Skip to content

2.TARS PHP TCP Server & Client Development

PHP Server Side Development

Here we need to use tag php7mysql8 of image tangramor/docker-tars to develop PHP server. Here we assume that you are using Windows:

docker run --name mysql8 -e MYSQL_ROOT_PASSWORD=password -d -p 3306:3306 -v /c/Users/tangramor/mysql8_data:/var/lib/mysql mysql:8 --sql_mode="" --innodb_use_native_aio=0

docker run -d -it --name tars_mysql8 --link mysql8 --env DBIP=mysql8 --env DBPort=3306 --env DBUser=root --env DBPassword=password -p 3000:3000 -p 80:80 -v /c/Users/tangramor/tars_mysql8_data:/data tangramor/docker-tars:php7mysql8

The above 2 commands start 2 containers: a v8.0 mysql and tangramor/docker-tars:php7mysql8 container with name tars_mysql8, and we mount the folder of host machine /c/Users/tangramor/Workspace/tars_mysql8_data as /data folder of container tars_mysql8. It also exposes port 3000 and 80.

Enter /c/Users/tangramor/Workspace/tars_mysql8_data/web and create folders: scriptssrc and tars:

DevPHPTest1

Run docker exec -it tars_mysql8 bash to enter container tars_mysql8 and cd /data/web.

Create file test.tars under tars folder ( Refer: phptars example ):

module testtafserviceservant
{
    struct SimpleStruct {
        0 require long id=0;
        1 require int count=0;
        2 require short page=0;
    };

    struct OutStruct {
        0 require long id=0;
        1 require int count=0;
        2 require short page=0;
        3 optional string str;
    };

    struct ComplicatedStruct {
        0 require vector<SimpleStruct> ss;
        1 require SimpleStruct rs;
        2 require map<string, SimpleStruct> mss;
        3 optional string str;
    }

    struct LotofTags {
        0 require long id=0;
        1 require int count=0;
        2 require short page=0;
        3 optional string str;
        4 require vector<SimpleStruct> ss;
        5 require SimpleStruct rs;
        6 require map<string, SimpleStruct> mss;
    }

    interface TestTafService
    {

        void testTafServer();

        int testLofofTags(LotofTags tags, out LotofTags outtags);

        void sayHelloWorld(string name, out string outGreetings);

        int testBasic(bool a, int b, string c, out bool d, out int e, out string f);

        string testStruct(long a, SimpleStruct b, out OutStruct d);

        string testMap(short a, SimpleStruct b, map<string, string> m1, out OutStruct d, out map<int, SimpleStruct> m2);

        string testVector(int a, vector<string> v1, vector<SimpleStruct> v2, out vector<int> v3, out vector<OutStruct> v4);

        SimpleStruct testReturn();

        map<string,string> testReturn2();

        vector<SimpleStruct> testComplicatedStruct(ComplicatedStruct cs,vector<ComplicatedStruct> vcs, out ComplicatedStruct ocs,out vector<ComplicatedStruct> ovcs);

        map<string,ComplicatedStruct> testComplicatedMap(map<string,ComplicatedStruct> mcs, out map<string,ComplicatedStruct> omcs);

        int testEmpty(short a,out bool b1, out int in2, out OutStruct d, out vector<OutStruct> v3,out vector<int> v4);

        int testSelf();

        int testProperty();

    };

}

Create file tars.proto.php under tars:

<?php

  return array(
      'appName' => 'PHPTest',
      'serverName' => 'PHPServer',
      'objName' => 'obj',
      'withServant' => true, //true to generate server side code, false for client side code
      'tarsFiles' => array(
          './test.tars'
      ),
      'dstPath' => '../src/servant',
      'namespacePrefix' => 'Server\servant',
  );

Create tars2php.sh under scripts and give execution permission chmod u+x tars2php.sh:

cd ../tars/

php /root/phptars/tars2php.php ./tars.proto.php

Create folder src/servant, then run ./scripts/tars2php.sh, you will see there are 3 layers folders generated under src/servant: PHPTest/PHPServer/obj, it includes:

  • classes folder - To store the generated tars structs
  • tars folder - To store the original tars file
  • TestTafServiceServant.php - interface

DevPHPTest2

Enter src folder, we begin to implemente the server side logic. Because we are using the official example, here we copy the source code directly from example project:

wget https://github.com/Tencent/Tars/raw/master/php/examples/tars-tcp-server/src/composer.json
wget https://github.com/Tencent/Tars/raw/master/php/examples/tars-tcp-server/src/index.php
wget https://github.com/Tencent/Tars/raw/master/php/examples/tars-tcp-server/src/services.php
mkdir impl && cd impl && wget https://github.com/Tencent/Tars/raw/master/php/examples/tars-tcp-server/src/impl/PHPServerServantImpl.php && cd ..
mkdir conf && cd conf && wget https://github.com/Tencent/Tars/raw/master/php/examples/tars-tcp-server/src/conf/ENVConf.php && cd ..
  • conf: configurations for implementation, here we just give a demo. If you push config from Tars platform, the file will be written into this folder.
  • impl: implementation code for interface. And the address of the implementation will be written in servcies.php.
  • composer.json: dependencies of the project.
  • index.php: entrance file of the service. You can use another name, and you need to change the deployment template on Tars platform, by adding entrance field under server.
  • services.php: diclare the addresses of interface and implementation, and they will be used for instantiate and annotation parsing.

Change the configuration in conf/ENVConf.php . And execute composer install under src to load required dependencies, then run composer run-script deploy to build the package, and a package name like PHPServer_20180523105340.tar.gz will be generated.

DevPHPTest3

Create a logs folder under /data, because this example will write file under it.

Deploy the generated package to Tars platform. Remember to use tars-php type and use tars.tarsphp.default template (or create a template by yourself):

DeployPHPTest1

DeployPHPTest2

Once the deployment is successfully completed, you will see related processes when run ps -ef.

DeployPHPTest3

PHP Client Side Development

We will develop the client side code in the same container.

Enter /c/Users/tangramor/Workspace/tars_mysql8_data/web and create client folder under it.

Run docker exec -it tars_mysql8 bash to enter container tars_mysql8, and cd /data/web/client.

Copy the test.tars file created in 3. PHP Server Side Development to current folder, and create file tarsclient.proto.php:

<?php

  return array(
      'appName' => 'PHPTest',
      'serverName' => 'PHPServer',
      'objName' => 'obj',
      'withServant' => false, //true to generate server side code, false for client side code
      'tarsFiles' => array(
          './test.tars'
      ),
      'dstPath' => './',
      'namespacePrefix' => 'Client\servant',
  );

Run php /root/phptars/tars2php.php ./tarsclient.proto.php, and you will see there are 3 layers folders generated: PHPTest/PHPServer/obj, it includes:

  • classes folder - To store the generated tars structs
  • tars folder - To store the original tars file
  • TestTafServiceServant.php - client class TestTafServiceServant

Create file composer.json:

{
  "name": "demo",
  "description": "demo",
  "authors": [
    {
      "name": "Tangramor",
      "email": "tangramor@qq.com"
    }
  ],
  "require": {
    "php": ">=5.3",
    "phptars/tars-client" : "0.1.1"
  },
  "autoload": {
    "psr-4": {
      "Client\\servant\\": "./"
    }
  },
  "repositories": {
    "tars": {
      "type": "composer",
      "url": "https://raw.githubusercontent.com/Tencent/Tars/master/php/dist/tarsphp.json"
    }
  }
}

And create index.php file:

<?php
  require_once("./vendor/autoload.php");

  // ip、port
  $config = new \Tars\client\CommunicatorConfig();
  $config->setLocator('tars.tarsregistry.QueryObj@tcp -h 172.17.0.3 -p 17890');
  $config->setModuleName('PHPTest.PHPServer');
  $config->setCharsetName('UTF-8');

  $servant = new Client\servant\PHPTest\PHPServer\obj\TestTafServiceServant($config);

  $name = 'ted';
  $intVal = $servant->sayHelloWorld($name, $greetings);

  echo '<p>'.$greetings.'</p>';

Run composer install to load required dependencies, then execute php index.php to test our client. If everything good, it should output: <p>hello world!</p>. We use a web browser to visit http://192.168.99.100/client/index.php and should see page:

DevPHPTest4

Check ted.log under /data/logs, there should be content written: sayHelloWorld name:ted.