From: Mark Slee Date: Sat, 17 Nov 2007 00:32:36 +0000 (+0000) Subject: Add __autoload() support to Thrift-generated PHP code X-Git-Tag: 0.2.0~1123 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=09f69e052452e973949bc143d0f34c28c51ff15e;p=common%2Fthrift.git Add __autoload() support to Thrift-generated PHP code Summary: Include thrift/autoload.php and use -phpa flag to generated code that works with autoload. Good for services with lots of methods that are typically not all invoked. Reviewed By: dreiss Test Plan: Falcon, baby, falcon. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665349 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc index c0fdd25c..8a3bdb7c 100644 --- a/compiler/cpp/src/generate/t_php_generator.cc +++ b/compiler/cpp/src/generate/t_php_generator.cc @@ -359,6 +359,28 @@ void t_php_generator::generate_php_struct_spec(ofstream& out, } +void t_php_generator::generate_php_struct_definition(ofstream& out, + t_struct* tstruct, + bool is_exception) { + if (autoload_) { + // Make output file + ofstream autoload_out; + string f_struct = program_name_+"."+(tstruct->get_name())+".php"; + string f_struct_name = get_out_dir()+f_struct; + autoload_out.open(f_struct_name.c_str()); + autoload_out << "" << endl; + autoload_out.close(); + + f_types_ << + "$GLOBALS['THRIFT_AUTOLOAD']['" << php_namespace(tstruct->get_program()) << tstruct->get_name() << "'] = '" << program_name_ << "/" << f_struct << "';" << endl; + + } else { + _generate_php_struct_definition(out, tstruct, is_exception); + } +} + /** * Generates a struct definition for a thrift data type. This is nothing in PHP * where the objects are all just associative arrays (unless of course we @@ -366,7 +388,7 @@ void t_php_generator::generate_php_struct_spec(ofstream& out, * * @param tstruct The struct definition */ -void t_php_generator::generate_php_struct_definition(ofstream& out, +void t_php_generator::_generate_php_struct_definition(ofstream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); @@ -1032,12 +1054,32 @@ void t_php_generator::generate_service_rest(t_service* tservice) { "}" << endl << endl; } +void t_php_generator::generate_service_client(t_service* tservice) { + if (autoload_) { + // Make output file + ofstream autoload_out; + string f_struct = program_name_+"."+(tservice->get_name())+".client.php"; + string f_struct_name = get_out_dir()+f_struct; + autoload_out.open(f_struct_name.c_str()); + autoload_out << "" << endl; + autoload_out.close(); + + f_service_ << + "$GLOBALS['THRIFT_AUTOLOAD']['" << service_name_ << "Client" << "'] = '" << program_name_ << "/" << f_struct << "';" << endl; + + } else { + _generate_service_client(f_service_, tservice); + } +} + /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ -void t_php_generator::generate_service_client(t_service* tservice) { +void t_php_generator::_generate_service_client(ofstream& out, t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != NULL) { @@ -1045,33 +1087,33 @@ void t_php_generator::generate_service_client(t_service* tservice) { extends_client = " extends " + extends + "Client"; } - f_service_ << + out << "class " << service_name_ << "Client" << extends_client << " implements " << service_name_ << "If {" << endl; indent_up(); // Private members if (extends.empty()) { - f_service_ << + out << indent() << "protected $input_ = null;" << endl << indent() << "protected $output_ = null;" << endl << endl; - f_service_ << + out << indent() << "protected $seqid_ = 0;" << endl << endl; } // Constructor function - f_service_ << + out << indent() << "public function __construct($input, $output=null) {" << endl; if (!extends.empty()) { - f_service_ << + out << indent() << " parent::__construct($input, $output);" << endl; } else { - f_service_ << + out << indent() << " $this->input_ = $input;" << endl << indent() << " $this->output_ = $output ? $output : $input;" << endl; } - f_service_ << + out << indent() << "}" << endl << endl; // Generate client method implementations @@ -1084,10 +1126,10 @@ void t_php_generator::generate_service_client(t_service* tservice) { string funname = (*f_iter)->get_name(); // Open function - indent(f_service_) << + indent(out) << "public function " << function_signature(*f_iter) << endl; - scope_up(f_service_); - indent(f_service_) << + scope_up(out); + indent(out) << "$this->send_" << funname << "("; bool first = true; @@ -1095,63 +1137,63 @@ void t_php_generator::generate_service_client(t_service* tservice) { if (first) { first = false; } else { - f_service_ << ", "; + out << ", "; } - f_service_ << "$" << (*fld_iter)->get_name(); + out << "$" << (*fld_iter)->get_name(); } - f_service_ << ");" << endl; + out << ");" << endl; if (!(*f_iter)->is_async()) { - f_service_ << indent(); + out << indent(); if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << "return "; + out << "return "; } - f_service_ << + out << "$this->recv_" << funname << "();" << endl; } - scope_down(f_service_); - f_service_ << endl; + scope_down(out); + out << endl; - indent(f_service_) << + indent(out) << "public function send_" << function_signature(*f_iter) << endl; - scope_up(f_service_); + scope_up(out); std::string argsname = php_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_args"; // Serialize the request header if (binary_inline_) { - f_service_ << + out << indent() << "$buff = pack('N', (0x80010000 | TMessageType::CALL));" << endl << indent() << "$buff .= pack('N', strlen('" << funname << "'));" << endl << indent() << "$buff .= '" << funname << "';" << endl << indent() << "$buff .= pack('N', $this->seqid_);" << endl; } else { - f_service_ << + out << indent() << "$this->output_->writeMessageBegin('" << (*f_iter)->get_name() << "', TMessageType::CALL, $this->seqid_);" << endl; } - f_service_ << + out << indent() << "$args = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - f_service_ << + out << indent() << "$args->" << (*fld_iter)->get_name() << " = $" << (*fld_iter)->get_name() << ";" << endl; } // Write to the stream if (binary_inline_) { - f_service_ << + out << indent() << "$args->write($buff);" << endl << indent() << "$this->output_->write($buff);" << endl << indent() << "$this->output_->flush();" << endl; } else { - f_service_ << + out << indent() << "$args->write($this->output_);" << endl << indent() << "$this->output_->writeMessageEnd();" << endl << indent() << "$this->output_->getTransport()->flush();" << endl; } - scope_down(f_service_); + scope_down(out); if (!(*f_iter)->is_async()) { @@ -1162,12 +1204,12 @@ void t_php_generator::generate_service_client(t_service* tservice) { string("recv_") + (*f_iter)->get_name(), &noargs); // Open function - f_service_ << + out << endl << indent() << "public function " << function_signature(&recv_function) << endl; - scope_up(f_service_); + scope_up(out); - f_service_ << + out << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl << indent() << "$mtype = 0;" << endl << @@ -1176,16 +1218,16 @@ void t_php_generator::generate_service_client(t_service* tservice) { if (binary_inline_) { t_field ffname(g_type_string, "fname"); t_field fseqid(g_type_i32, "rseqid"); - f_service_ << + out << indent() << "$ver = unpack('N', $this->input_->readAll(4));" << endl << indent() << "$ver = $ver[1];" << endl << indent() << "$mtype = $ver & 0xff;" << endl << indent() << "$ver = $ver & 0xffff0000;" << endl << indent() << "if ($ver != 0x80010000) throw new TProtocolException('Bad version identifier: '.$ver, TProtocolException::BAD_VERSION);" << endl; - generate_deserialize_field(f_service_, &ffname, "", true); - generate_deserialize_field(f_service_, &fseqid, "", true); + generate_deserialize_field(out, &ffname, "", true); + generate_deserialize_field(out, &fseqid, "", true); } else { - f_service_ << + out << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);" << endl << indent() << "if ($mtype == TMessageType::EXCEPTION) {" << endl << indent() << " $x = new TApplicationException();" << endl << @@ -1195,19 +1237,19 @@ void t_php_generator::generate_service_client(t_service* tservice) { indent() << "}" << endl; } - f_service_ << + out << indent() << "$result = new " << resultname << "();" << endl << indent() << "$result->read($this->input_);" << endl; if (!binary_inline_) { - f_service_ << + out << indent() << "$this->input_->readMessageEnd();" << endl << endl; } // Careful, only return result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << + out << indent() << "if ($result->success !== null) {" << endl << indent() << " return $result->success;" << endl << indent() << "}" << endl; @@ -1217,7 +1259,7 @@ void t_php_generator::generate_service_client(t_service* tservice) { const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - f_service_ << + out << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl << indent() << " throw $result->" << (*x_iter)->get_name() << ";" << endl << indent() << "}" << endl; @@ -1225,22 +1267,22 @@ void t_php_generator::generate_service_client(t_service* tservice) { // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << + indent(out) << "return;" << endl; } else { - f_service_ << + out << indent() << "throw new Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } // Close function - scope_down(f_service_); - f_service_ << endl; + scope_down(out); + out << endl; } } indent_down(); - f_service_ << + out << "}" << endl << endl; } diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h index 57427474..3f85feaa 100644 --- a/compiler/cpp/src/generate/t_php_generator.h +++ b/compiler/cpp/src/generate/t_php_generator.h @@ -21,11 +21,16 @@ */ class t_php_generator : public t_oop_generator { public: - t_php_generator(t_program* program, bool binary_inline=false, bool rest=false, bool phps=false) : + t_php_generator(t_program* program, + bool binary_inline=false, + bool rest=false, + bool phps=false, + bool autoload=false) : t_oop_generator(program), binary_inline_(binary_inline), rest_(rest), - phps_(phps) { + phps_(phps), + autoload_(autoload) { out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php"); } @@ -55,6 +60,7 @@ class t_php_generator : public t_oop_generator { void generate_php_struct(t_struct* tstruct, bool is_exception); void generate_php_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false); + void _generate_php_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false); void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct); void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct); void generate_php_function_helpers(t_function* tfunction); @@ -70,6 +76,7 @@ class t_php_generator : public t_oop_generator { void generate_service_interface (t_service* tservice); void generate_service_rest (t_service* tservice); void generate_service_client (t_service* tservice); + void _generate_service_client (std::ofstream &out, t_service* tservice); void generate_service_processor (t_service* tservice); void generate_process_function (t_service* tservice, t_function* tfunction); @@ -168,6 +175,11 @@ class t_php_generator : public t_oop_generator { */ bool phps_; + /** + * Generate PHP code that uses autoload + */ + bool autoload_; + }; #endif diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index c633facb..0b904ea4 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -140,6 +140,7 @@ bool gen_xsd = false; bool gen_php = false; bool gen_phpi = false; bool gen_phps = true; +bool gen_phpa = false; bool gen_rest = false; bool gen_perl = false; bool gen_erl = false; @@ -562,6 +563,7 @@ void usage() { fprintf(stderr, " -phpi Generate PHP inlined files\n"); fprintf(stderr, " -phps Generate PHP server stubs (with -php)\n"); fprintf(stderr, " -phpl Generate PHP-lite (with -php)\n"); + fprintf(stderr, " -phpa Generate PHP with autoload (with -php)\n"); fprintf(stderr, " -py Generate Python output files\n"); fprintf(stderr, " -rb Generate Ruby output files\n"); fprintf(stderr, " -xsd Generate XSD output files\n"); @@ -813,7 +815,7 @@ void generate(t_program* program) { if (gen_php) { pverbose("Generating PHP\n"); - t_php_generator* php = new t_php_generator(program, false, gen_rest, gen_phps); + t_php_generator* php = new t_php_generator(program, false, gen_rest, gen_phps, gen_phpa); php->generate_program(); delete php; } @@ -953,6 +955,12 @@ int main(int argc, char** argv) { gen_php = true; } gen_phps = false; + } else if (strcmp(arg, "-phpa") == 0) { + if (!gen_php) { + gen_php = true; + gen_phps = false; + } + gen_phpa = true; } else if (strcmp(arg, "-rest") == 0) { gen_rest = true; } else if (strcmp(arg, "-py") == 0) { diff --git a/lib/php/src/autoload.php b/lib/php/src/autoload.php new file mode 100644 index 00000000..b5886c5e --- /dev/null +++ b/lib/php/src/autoload.php @@ -0,0 +1,34 @@ + + */ + +/** + * Include this file if you wish to use autoload with your PHP generated Thrift + * code. The generated code will *not* include any defined Thrift classes by + * default, except for the service interfaces. The generated code will populate + * values into $GLOBALS['THRIFT_AUTOLOAD'] which can be used by the autoload + * method below. If you have your own autoload system already in place, you + * should merge the following functionality into your autoload system. + * + * Generate this code using the -phpa Thrift generator flag. + */ + +$GLOBALS['THRIFT_AUTOLOAD'] = array(); + +if (!function_exists('__autoload')) { + function __autoload($class) { + global $THRIFT_AUTOLOAD; + if (isset($THRIFT_AUTOLOAD[$class])) { + include_once $GLOBALS['THRIFT_ROOT'].'/lib/packages/'.$THRIFT_AUTOLOAD[$class]; + } + } +}