Php reconstruction optimization example-template method mode Application

Source: Internet
Author: User

I recently optimized the php project, recorded my experience, and worked on it directly...

Php is mainly used for page display in company projects. The front-end has a view, and the service request data of the view back end. The data transmission format is json. The code of the service before optimization is as follows:

[Php]
<? Php
Require_once ('../global. php ');
Require_once (INCLUDE_PATH. '/discache/CacherManager. php ');
Require_once (INCLUDE_PATH. '/oracle_oci.php ');
Require_once (INCLUDE_PATH. '/caihui/cwsd. php ');
Header ('content-type: text/plain; charset = UTF-8 ');
$ Max_age = isset ($ _ GET ['max-age'])? $ _ GET ['max-age'] * 1: 15*60;
If ($ max_age <30 ){
$ Max_age = 30;
}
Header ('cache-Control: max-age = '. $ max_age );
// Use the url hash as the buffer key
$ Url = $ _ SERVER ['HTTP _ host']. $ _ SERVER ['request _ URI '];
$ Url_hash = md5 ($ url );
// Echo "/finance/hs/marketdata/segment/$ {url_hash}. json ";
If (! CacherManager: cachePageStart (CACHER_MONGO, "/finance/hs/marketdata/segment/$ {url_hash}. json", 60*60 )){
 
// Query Conditions
$ Page = isset ($ _ GET ['page'])? $ _ GET ['page'] * 1: 0;
$ Count = isset ($ _ GET ['Count'])? $ _ GET ['Count'] * 1: 30;
$ Type = isset ($ _ GET ['type'])? $ _ GET ['type']: 'query ';
$ Sort = isset ($ _ GET ['sort '])? $ _ GET ['sort ']: 'symbol ';
$ Order = isset ($ _ GET ['order'])? $ _ GET ['order']: 'desc ';
$ Callback = isset ($ _ GET ['callback'])? $ _ GET ['callback']: null;
$ Fieldsstring = isset ($ _ GET ['fields'])? $ _ GET ['fields']: null;
$ Querystring = isset ($ _ GET ['query'])? $ _ GET ['query']: null;
$ Symbol = isset ($ _ GET ['symbol'])? $ _ GET ['sympost']: '';
$ Date = isset ($ _ GET ['date'])? $ _ GET ['date']: '';
 
If ($ type = 'query '){
$ QueryObj = preg_split ('/: |;/', $ querystring,-1 );
For ($ I = 0; $ I <count ($ queryObj); $ I = $ I + 2 ){
If (emptyempty ($ queryObj [$ I]) continue;
If ($ queryObj [$ I] = 'symbol '){
$ Symbol = $ queryObj [$ I + 1];
}
If ($ queryObj [$ I] = 'date '){
$ Date = $ queryObj [$ I + 1];
}
}
}
 
// Query the list
$ Oci = ntes_get_caihui_oci ();
$ Stocklist = array ();
$ Cwsd = new namespace \ dao \ caihui \ Cwsd ($ oci );

$ Stockcurror = $ cwsd-> getCznlList ($ symbol, $ date, $ sort, $ order, $ count * ($ page), $ count );
$ Sumrecords = $ cwsd-> getRecordCount ($ symbol, $ date );
$ I = 0;
// Var_dump ($ symbol, $ date, $ sort, $ order, $ count * ($ page), $ count );
Foreach ($ stockcurror as $ item ){
$ Item ['rsmfratio1422 '] = isset ($ item ['rsmfratio1422'])? Number_format ($ item ['rsmfratio1422 '], 2).' % ':'--';
$ Item ['rsmfratio1822 '] = isset ($ item ['rsmfratio1822'])? Number_format ($ item ['rsmfratio1822 '], 2).' % ':'--';
$ Item ['rsmfratio22 '] = isset ($ item ['rsmfratio22'])? Number_format ($ item ['rsmfratio22 '], 2).' % ':'--';

$ Item ['rsmfratio10'] = isset ($ item ['rsmfratio10'])? Number_format ($ item ['rsmfratio10'], 2 ):'--';
$ Item ['rsmfratio12'] = isset ($ item ['rsmfratio12'])? Number_format ($ item ['rsmfratio12'], 2 ):'--';
$ Item ['rsmfratio4 '] = isset ($ item ['rsmfratio4'])? Number_format ($ item ['rsmfratio4 '], 2 ):'--';
$ Item ['rsmfratio18'] = isset ($ item ['rsmfratio18'])? Number_format ($ item ['rsmfratio18 '], 2 ):'--';
$ Item ['rsmfratio14'] = isset ($ item ['rsmfratio14'])? Number_format ($ item ['rsmfratio14'], 2 ):'--';
 
$ Item ['code'] = $ item ['exchange ']. $ item ['sympost'];
// $ Item ['reportdate'] = isset ($ item ['reportdate'])? $ Item ['reportdate']: '--';
$ Stocklist [$ I] = $ item;
$ I = $ I + 1;
}
 
 
// Output result
$ Result = array ();
// Page number, page count, total number of results, pagecount, and result list
$ Result ['page'] = $ page;
$ Result ['Count'] = $ count;
$ Result ['order'] = $ order;
$ Result ['Total'] = $ I; // $ stockcurror-> count ();
$ Result ['pagecount'] = ceil ($ sumrecords ['sumrecord']/$ count );
$ Result ['time'] = date ('Y-m-d H: I: s ');
$ Result ['LIST'] = $ stocklist;
If (emptyempty ($ callback )){
Echo json_encode ($ result );
} Else {
Echo $ callback. '('. json_encode ($ result ).');';
}
 
CacherManager: cachePageEnd ();
}
?>
The following describes the specific functions of this service:

1. Lines 6-16: Prepare cache parameters and enable cache.
2. Lines 19-41 extract request parameters.
3. Lines 44-49 connect to and query the database.
4. Rows 50-67: add the database query results to the array.
5. lines-84 prepare json data.
6. Line 8-87: Disable the cache.

If you only view this file, the following problems exist:
1. Lines 19-86 with no indentation.
2. Row 44 will reconnect to the database each request.
3. lines-61. Repeated logic can be extracted as a function and completed through iteration.
If most backend services adopt this structure, the problem is that all services must go through the process of enabling caching, obtaining parameters, obtaining data, converting json data, and disabling caching. In all processes, except the logic for obtaining data, other processes are the same. There are a lot of repetitive logic in the code, and even give people a sense of "copy-paste", which seriously violates the DRY principle (Don't Repeat Yourself ). Therefore, we need to use the object-oriented idea to reconstruct it. In the process of restructuring, I always remember a principle-the principle of encapsulation and change. The so-called encapsulation change is to distinguish between the unchanged and variable in the system, and encapsulate the variable, so as to better cope with the change.
Through the above analysis, only the logic for obtaining data changes, while the other logic remains unchanged. Therefore, we need to encapsulate the logic for obtaining data. The specific encapsulation method can be inherited or combined. I use the inheritance method. First, the service processing process is abstracted:
Service (){
StartCache ();
GetParam ();
GetData (); // abstract method, implemented by subclass
ToJson ();
CloseCache ();
}
The ServiceBase class is abstracted and inherited by the subclass to implement the logic for obtaining data. The subclass does not need to process other parameters, cache logic, and other logic. These are all processed by the ServiceBase class.
[Php]
Abstract class ServiceBase {
Public function _ construct ($ cache_path, $ cache_type, $ max_age, $ age_0000e ){
// Obtain Request Parameters
$ This-> page = $ this-> getQueryParamDefault ('page', 0, INT );
// Omitting the logic for obtaining other parameters
......
 
// Generate a response
$ This-> response ();
}
 
/**
*
* Subclass implementation, return data in array format
*/
Abstract protected function data ();
 
/**
*
* Subclass implementation, returns the total number of all data
*/
Abstract protected function total ();
 
Private function cache (){
$ Url = $ _ SERVER ['HTTP _ host']. $ _ SERVER ['request _ URI '];
$ Url_hash = md5 ($ url );
$ Key = $ this-> cache_path. $ url_hash. '. json ';
If (! CacherManager: cachePageStart ($ this-> cache_type, $ key, $ this-> age_cache )){
$ This-> no_cache ();
CacherManager: cachePageEnd ();
}
}
 
Private function no_cache (){
$ Data = $ this-> data ();
$ Total = $ this-> total ();
$ This-> send_data ($ data, $ total );
}
 
Private function send_data ($ data, $ total ){
// Json conversion, omitting the specific code
}
 
Private function response (){
Header ('content-type: text/plain; charset = UTF-8 ');
Header ('cache-Control: max-age = '. $ this-> age_police );
If ($ this-> cache_type = NONE | self: $ enable_cache = false ){
$ This-> no_cache ();
} Else {
$ This-> cache ();
}
}
}
This is the abstract parent class of each service. There are two Abstract METHODS: data and total. data returns data in the array format. tatol is added by page. The specific service only needs to inherit ServiceBase and implement the data and total methods. Other logics are reusable parent classes. In fact, the optimized ServiceBase uses the Template Method. The parent class defines the algorithm processing process (service processing process ), subclass to implement a specific step (the logic for obtaining data from a specific service ). By using the template method, you can ensure that step changes are transparent to the client and reuse the logic in the parent class.

The code for using ServiceBase in php is as follows:

[Php]
Class CWSDService extends ServiceBase {
Function _ construct (){
Parent: :__ construct ();
$ Oci = ntes_get_caihui_oci ();
$ This-> $ cwsd = new namespace \ dao \ caihui \ Cwsd ($ oci );
}
Public function data (){
$ Stocklist = array ();
$ Stockcurror = $ this-> cwsd-> getCznlList ($ this-> query_obj ['symbol'],
$ This-> query_obj ['symbol'], $ sort, $ order, $ count * ($ page), $ count );
$ Filter_list = array ('rsmfratio1422', 'rsmfratio1822', 'rsmfratio22 ',
'Rsmfratio10', 'rsmfratio12', 'rsmfratio4 ', 'rsmfratio18 ',
'Rsmfratio14 ');
$ I = 0;
Foreach ($ stockcurror as $ item ){
Foreach ($ filter_list as $ k)
$ This-> filter ($ item, $ k );
$ Item ['code'] = $ item ['exchange ']. $ item ['sympost'];
$ Stocklist [$ I] = $ item;
$ I = $ I + 1;
}
Return $ stocklist;
}
Public function total (){
Return $ sumrecords = $ this-> cwsd-> getRecordCount ($ this-> query_obj ['symbol'],
$ This-> query_obj ['symbol']);
}
Private function filter ($ item, $ k ){
Isset ($ item [$ k])? Number_format ($ item [$ k], 2). '% ':'--';
}
}
New CWSDService ('/finance/hs/realtimedata/market/AB', MONGO, 30, 30 );
The number of code lines reduced from 87 to 32 because most of the logic is completed by the parent class. The specific service only needs to focus on its own business logic. The code above shows that inheritance can achieve code reuse. The same logic in multiple child classes can be extracted to the parent class for reuse. At the same time, inheritance also adds the coupling between the parent class and the Child class, which means that the combination is due to the inheritance aspect. If this example uses a combination to encapsulate changes, the specific implementation is the policy mode, the logic for getting data is regarded as a policy, and different services are different policies. We will not repeat them for time reasons...

From chosen0ne's column
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.