1. Composer is already installed. To update Composer to the latest version, I ran the command, and the result is shown in Figure 1:
composer self-update
Error: Warning: Module ‘mbstring’ already loaded in Unknown on line 0

2. In php.ini, I found that extension=php_mbstring.dll was loaded twice. I commented out line 1007, as shown in Figures 2 and 3:
;extension=php_mbstring.dll


3. I ran the command again. The Warning no longer appeared, but the file at https://getcomposer.org/version could not be downloaded, as shown in Figure 4:
composer self-update

4. The solution was to enable the Packagist/Composer China full mirror. Website: http://pkg.phpcomposer.com/ . I executed the command, as shown in Figure 5:
composer config -g repo.packagist composer https://packagist.phpcomposer.com
Error:
Warning: This development build of composer is over 60 days old. It is recommended to update it by running “C:\ProgramData\ComposerSetup\bin\composer.phar self-update” to get the latest version.
This means:
Warning: This development build of Composer is over 60 days old. It is recommended to update it by running “C:\ProgramData\ComposerSetup\bin\composer.phar self-update” to get the latest version.

5. I executed `composer self-update` again, but it still requested the URL: https://getcomposer.org/version, as shown in Figure 6:

6. I opened C:\Users\Administrator\AppData\Roaming\Composer\config.json, cleared the file contents, and re-executed the command:
composer config -g repo.packagist composer https://packagist.phpcomposer.com
The contents of the config.json file are shown in Figure 7.
{
“repositories”: {
“packagist”: {
“type”: “composer”,
“url”: “https://packagist.phpcomposer.com”
}
}
}

7. I executed `composer self-update` again, and the update was successful, as shown in Figures 8 and 9:
Updating to version a8e9df55dc62d8806360be2f79ad112b8678d397.
Downloading: 100%
Use composer self-update –rollback to return to version a066171dcc023ad6429881a7692e46f10e080f99


8. To install the composer asset plugin for Composer, I executed the command. The result is shown in Figure 10:
composer global require “fxp/composer-asset-plugin:~1.0.0”

9. I executed the command, and the result is shown in Figure 11:
composer global update

10. To install Yii2, I executed the command. The result is shown in Figures 12 and 13:
composer create-project yiisoft/yii2-app-advanced service.ygt.cm


11. I checked the service.ygt.cm directory and found that the installation was successful, as shown in Figure 14:

12. I configured the virtual hosts: frontend.service.ygt.cm and backend.service.ygt.cm. Opening frontend.service.ygt.cm resulted in an error, as shown in Figure 15.

13. The reason is that the index.php file does not exist in the E:\wwwroot\service.ygt.cm\frontend\web directory, as shown in Figure 16.

14. To update the composer asset plugin for Composer, I executed the command. The result is shown in Figure 17:
composer global require “fxp/composer-asset-plugin:~1.1.1”

15. I ran the command to upgrade Yii2, and it produced an error, as shown in Figure 18:
composer update yiisoft/yii2 yiisoft/yii2-composer bower-asset/jquery.inputmask
Error: Composer could not find a composer.json file in E:\wwwroot
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ “Getting Started” section

16. I navigated to the E:\wwwroot\service.ygt.cm directory and executed the command again, as shown in Figure 19:
composer update yiisoft/yii2 yiisoft/yii2-composer bower-asset/jquery.inputmask
Result:
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files

17. To initialize the application, I executed the command, as shown in Figure 20:
init
0
yes

18. Open frontend.service.ygt.cm, as shown in Figure 21.

19. Open backend.service.ygt.cm, as shown in Figure 22.

20. To add the application member.service.ygt.cm, I copied the frontend directory to a directory named member, as shown in Figure 23.

21. Edit the file E:\wwwroot\service.ygt.cm\environments\index.php, as shown in Figure 24.
Copy frontend to member.

22. Under E:\wwwroot\service.ygt.cm\environments, copy the frontend directories in both dev and prod to member as well, as shown in Figure 25.

23. Execute the command, as shown in Figure 26:
init
0
yes
All

24. Search for frontend in the member directory and replace it with member. It is recommended not to replace frontend in the index-test.php file, as shown in Figure 27.

25. Edit E:\wwwroot\service.ygt.cm\common\config\bootstrap.php, as shown in Figure 28.
Yii::setAlias(‘@member’, dirname(dirname(__DIR__)) . ‘/member’);

26. Open member.service.ygt.cm, as shown in Figures 29 and 30.


27. To install Hprose for PHP, I executed the command, as shown in Figures 31 and 32:
composer require “hprose/hprose:dev-master”


28. To publish the remote service, I created E:\wwwroot\service.ygt.cm\member\controllers\HproseController.php, as shown in Figure 33:
<?php
namespace member\controllers;
use yii\base\Controller;
use Hprose\Yii\Server;
/**
* Hprose controller
*/
class HproseController extends Controller
{
public function beforeAction($action)
{
parent::beforeAction($action);
$server = new Server();
$server->setErrorTypes(E_ALL);
$server->setDebugEnabled(true);
$server->addMethod($action->actionMethod, $this, $action->id);
$server->start();
}
}
Alternatively (this approach is recommended):
namespace member\controllers;
use yii\web\Controller;
use Hprose\Yii\Server;
/**
* Hprose controller
*/
class HproseController extends Controller
{
public $enableCsrfValidation = false;
public function beforeAction($action)
{
parent::beforeAction($action);
$server = new Server();
$server->setErrorTypes(E_ALL);
$server->setDebugEnabled(true);
$server->addMethod($action->actionMethod, $this, $action->id);
$server->start();
}
}

29. For the server-side implementation, I created E:\wwwroot\service.ygt.cm\member\controllers\AvatarController.php, as shown in Figure 34:
<?php
namespace member\controllers;
/**
* Avatar controller
*/
class AvatarController extends HproseController
{
public function actionServer()
{
return 10;
}
public function actionHello() {
return “Hello !”;
}
public function actionSum() {
return strval(array_sum(func_get_args()));
}
}

30. Open the URL: http://member.service.ygt.cm/?r=avatar/server , as shown in Figure 35:
The HproseController class in TP3.2.3 publishes all methods of the controller it resides in, whereas the current implementation only publishes the current action method.
Fa1{s6″server”}z

30. For the client-side implementation, I created E:\wwwroot\service.ygt.cm\zhidao\controllers\SiteController.php, as shown in Figure 36:
<?php
namespace zhidao\controllers;
use yii\web\Controller;
use Hprose\Http\Client;
/**
* Site controller
*/
class SiteController extends Controller
{
public function actionClient() {
$client = new Client(‘http://member.service.ygt.cm/?r=avatar/server’);
echo $client->server();
}
}

31. Open the URL: http://zhidao.service.ygt.cm/?r=site/client , as shown in Figure 37:

32. Alternatively, implement the hello action method, as shown in Figures 38 and 39:
Compared to the TP3.2.3 implementation, the drawback is that even for action methods under the same remote controller, the Client needs to be instantiated twice. However, I feel this is not a major issue; generally, one action method is sufficient.


