整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          ThinkPHP5.0.23源碼分析系列(一):生命

          ThinkPHP5.0.23婧愮爜鍒嗘瀽緋誨垪錛堜竴錛夛細鐢熷懡鍛ㄦ湡

          銆佺敓鍛藉懆鏈燂細

          浜屻€佸叆鍙f枃浠?/strong>

          thinkphp浣跨敤鍗曚竴鍏ュ彛錛屾墍鏈夌殑璇鋒眰閮戒粠榛樿鐨刬ndex.php鏂囦歡榪涘叆銆備綘榪樺彲浠ュ垱寤哄涓簲鐢紝涓€涓簲鐢ㄥ搴斾竴涓叆鍙f枃浠訛紝鎵€鏈夌殑鍏ュ彛鏂囦歡閮藉紩鐢ㄤ竴濂梩hinkphp綾誨簱銆?/p>

          // 瀹氫箟搴旂敤鐩綍
          define('APP_PATH', __DIR__ . '/../application/');
          // 鍔犺澆妗嗘灦寮曞鏂囦歡
          require __DIR__ . '/../thinkphp/start.php';
          

          絎竴琛屼唬鐮?瀹氫箟浜嗗簲鐢ㄧ殑榛樿鐩綍錛?/p>

          絎簩琛屼唬鐮佹槸鎴戜滑涓嬮潰瑕佺湅鐨勫紩瀵兼枃浠?/p>

          娉ㄦ剰錛氬畼鏂逛笉寤鴻鍦ㄥ簲鐢ㄥ叆鍙f枃浠朵腑鍔犲叆榪囧鐨勪唬鐮侊紝灝ゅ叾鏄拰涓氬姟閫昏緫鐩稿叧鐨勪唬鐮併€?/p>

          涓夈€佸紩瀵兼枃浠?/strong>

          start.php鏂囦歡灝辨槸緋葷粺榛樿鐨勪竴涓紩瀵兼枃浠躲€傚湪寮曞鏂囦歡涓紝浼氫緷嬈℃墽琛屼笅闈㈡搷浣滐細

          鍔犺澆緋葷粺甯擱噺瀹氫箟-->鍔犺澆鐜鍙橀噺瀹氫箟鏂囦歡-->娉ㄥ唽鑷姩鍔犺澆鏈哄埗-->娉ㄥ唽閿欒鍜屽紓甯稿鐞嗘満鍒?->鍔犺澆鎯緥閰嶇疆鏂囦歡-->鎵ц搴旂敤

          // ThinkPHP 寮曞鏂囦歡
          // 1. 鍔犺澆鍩虹鏂囦歡
          require __DIR__ . '/base.php';
          // 2. 鎵ц搴旂敤
          App::run()->send();
          

          start.php寮曞鏂囦歡棣栧厛浼氳皟鐢╞ase.php鍩虹寮曞鏂囦歡錛屾煇浜涚壒孌婇渶姹備笅闈㈠彲鑳界洿鎺ュ湪鍏ュ彛鏂囦歡涓紩鍏ュ熀紜€寮曞鏂囦歡銆?/p>

          鏂囩簿閫?NET Swagger 浣跨敤

          鉂?/span>

          鍦ㄥ悗绔紑鍙戜腑,甯哥敤 Web API 妯″紡,瀵瑰鎻愪緵 RESTful API 璁╁墠绔皟鐢?鑰屽叾涓渶钁楀悕鐨勫氨鏄嬌鐢?Swagger(淇楃О:涓濊鍝?,Swagger 涓嶄絾鎻愪緵浜嗛潪甯哥洿瑙傜殑欏甸潰渚涘紑鍙戣€呮煡鐪?榪樿兘閰嶇疆娉ㄩ噴璇存槑,鍒嗙粍絳?榪樺彲浠ョ洿鎺ュ湪嫻忚鍣ㄤ笂嫻嬭瘯鎺ュ彛,鍙互璇存槸,鐜板湪涓嶇敤 Swagger 鐨勫悗绔紑鍙戣€呬笉鏄釜濂藉紑鍙戣€?鏈枃灝嗛拡瀵規垜鍦ㄦ棩甯稿伐浣滀腑浣跨敤 Swagger 鐨勪竴浜涙€葷粨鍜屼緥瀛?鍩烘湰涓婂睘浜庡鍒朵唬鐮佸氨鑳界敤.

          鉂?/span>
          • 鏈枃榛樿澶у閮芥湁鐐瑰熀紜€,鑷沖皯浣跨敤 VS 鍒涘緩欏圭洰榪欎簺涓嶇敤鎴戝啀澶氳.
          • 鏈枃鐨勪緥瀛愪嬌鐢ㄥ井杞粯璁ょ殑 Web API 妯℃澘榪涜鏋勫緩,浼氳緇嗙殑璁茶В姣忎竴姝?騫朵笖浼氬皢浠g爜涓婁紶鍒?GitHub.
          • 鏈枃浼氫粙緇?Swagger 鐨勬敞閲?鎺ュ彛鍒嗙粍,闅愯棌鎺ュ彛,浠ュ強緇欓渶瑕佹巿鏉冪殑鎺ュ彛娣誨姞鏍囪瘑.浠ュ強鍙楁敮鎸佺殑鏁版嵁綾誨瀷鐨勯粯璁ゅ€兼樉紺?
            • 娉ㄩ噴涓嶇敤璇?灝辨槸灝嗕唬鐮佹敞閲婃樉紺哄埌欏甸潰涓?
            • 鎺ュ彛鍒嗙粍鍙互瀹炵幇灝嗕笉鍚屽姛鑳界殑鎺у埗鍣ㄥ垎鍒頒笉鍚岀殑緇勪腑,渚夸簬鏌ョ湅.
            • 闅愯棌鎺ュ彛鍒欐槸灝嗕笉甯屾湜瀵瑰鍏紑鐨勬帴鍙d笉鏄劇ず,閴存潈鎺ュ彛鏍囪瘑鍒欐槸鍦?API 鐨勫悗杈規樉紺轟竴涓?馃敀 閿佸浘鏍?
            • 鏄劇ず榛樿鍊煎垯鏄湪鏌愪簺鏁版嵁涓?姣斿鐢ㄦ埛騫撮緞,榛樿鏄劇ず 20,鍓嶇涓€鐪嬪氨鐭ラ亾榪欐槸涓粈涔堟暟鎹被鍨?褰撶劧榪欓噷鐨勪緥瀛愪笉澶伆褰?鍙嶆鎰忔€濆樊涓嶅.
          • 鏈€緇堝憟鐜扮殑鏁堟灉澶ф灝辨槸濡備笅,鎺ヤ笅鏉ュ氨寮€濮嬩嬌鐢ㄤ唬鐮佽鏄庤繖涓€鍒?

          • 棣栧厛浣跨敤 VS 鍒涘緩涓€涓?Web API 欏圭洰,榪欓噷鎴戝彨浠?Swagger.Sample,浣犱篃鍙互鍙粬鍏朵粬鍚嶅瓧,闅忎綘鑷繁.
          • 榛樿鐨?AddSwaggerGen 閰嶇疆浠g爜閲屼粈涔堥兘娌℃湁,鎵€浠ユ病鏈変粈涔堢壒孌婄殑鏁堟灉.浠呬粎鍙兘鏌ョ湅鎺ュ彛鍜岃皟璇曡€屽凡.
          var builder=WebApplication.CreateBuilder(args);

          // Add services to the container.
          builder.Services.AddControllers();
          // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
          builder.Services.AddEndpointsApiExplorer();
          // 閰嶇疆Swagger
          builder.Services.AddSwaggerGen();
          var app=builder.Build();

          // Configure the HTTP request pipeline.
          if (app.Environment.IsDevelopment())
          {
          app.UseSwagger();
          app.UseSwaggerUI();
          }
          app.UseAuthorization();
          app.MapControllers();
          app.Run();
          • 鐢變簬榛樿浠g爜閲屾湁涓ぉ姘旀暟鎹帴鍙?鎴戜滑騫朵笉闇€瑕?鎵€浠ュ垹鎺変粬浠?騫舵坊鍔犲嚑涓?POST,PUT,GET,DELETE 絳夋帴鍙f潵鍋氫緥瀛?鎵€鏈夌殑鎺ュ彛鍧囪繑鍥炰竴涓瓧絎︿覆.鍙傛暟鏍規嵁涓嶅悓鐨勬帴鍙g被鍨?浼氬0鏄庝笉鍚岀殑鍙傛暟.浣嗘槸閮戒笉浼氬お澶嶆潅,澶у鑲畾閮借兘鎳?
          • 灝嗛粯璁ょ殑鎺у埗鍣ㄦ敼鎴愬涓嬭繖涓牱瀛?
          using Microsoft.AspNetCore.Mvc;

          // ReSharper disable ClassNeverInstantiated.Global

          namespace Swagger.Sample.Controllers;

          /// <summary>
          /// 絎竴涓帶鍒跺櫒
          /// </summary>
          [ApiController, Route("[controller]/[action]")]
          public class FirstController : ControllerBase
          {
          /// <summary>
          /// Hello {name}
          /// </summary>
          /// <param name="name"></param>
          /// <returns></returns>
          [HttpGet]
          public string Hello(string name)=> $"Hello {name}";

          /// <summary>
          /// Hello World
          /// </summary>
          /// <returns></returns>
          [HttpGet]
          public string HelloWorld()=> "Hello World";

          /// <summary>
          /// PostOne
          /// </summary>
          /// <param name="parameter"></param>
          /// <returns></returns>
          [HttpPost]
          public PostParameter PostOne(PostParameter parameter)=> parameter;

          /// <summary>
          /// PutOne
          /// </summary>
          /// <param name="id"></param>
          /// <param name="put"></param>
          /// <returns></returns>
          [HttpPut("{id}")]
          public string PutOne(string id, PutParameter put)=> $"update:{id},{put.Gender}";

          /// <summary>
          /// DeleteOne
          /// </summary>
          /// <param name="id"></param>
          /// <returns></returns>
          [HttpDelete("{id}")]
          public string DeleteOne(string id)=> $"delete {id}";
          }

          /// <summary>
          /// Put鍙傛暟妯℃嫙
          /// </summary>
          public class PutParameter
          {
          /// <summary>
          /// Gender
          /// </summary>
          public EGender Gender { get; set; }
          }

          /// <summary>
          /// POST鍙傛暟妯℃嫙
          /// </summary>
          public class PostParameter : PutParameter
          {
          /// <summary>
          /// Name
          /// </summary>
          public string Name { get; set; }=string.Empty;

          /// <summary>
          /// Age
          /// </summary>
          public int Age { get; set; }
          }

          /// <summary>
          /// 鎬у埆鏋氫婦
          /// </summary>
          public enum EGender
          {
          /// <summary>
          /// 鐢?/span>
          /// </summary>
          鐢?

          /// <summary>
          /// 濂?/span>
          /// </summary>
          濂?br>}
          • 涓婅竟鎼炰簡鍑犱釜渚嬪瓙.鍚姩鍚庝細鍙戠幇鎸夌収棰勬湡鏄劇ず欏甸潰.浣嗘槸娌℃湁娉ㄩ噴涔熸病鏈変笂榪板埆鐨勫姛鑳?

          娣誨姞鏂囨。娉ㄩ噴

          • 瑕佽 Swagger 鏄劇ず鏂囨。娉ㄩ噴,棣栧厛瑕佸欏圭洰娣誨姞 XML 鏂囨。鐢熸垚.
          • 鎵撳紑欏圭洰鐨?xxx.csproj 鎴戣繖閲屾槸 Swagger.Sample.csproj,鍦?PropertyGroup 鑺傜偣涓嬫坊鍔?GenerateDocumentationFile 涓?Trune 濡備笅鍐呭:
           <PropertyGroup>
          <GenerateDocumentationFile>True</GenerateDocumentationFile>
          </PropertyGroup>
          • 榪欐椂鍊欏惎鍔ㄩ」鐩?铏界劧浼氱敓鎴愮浉搴旂殑鏂囦歡,浣嗘槸 Swagger 榪樻槸鏃犳硶姝e父鏄劇ず娉ㄩ噴,鍏跺師鍥犲氨鏄皻鏈 Swaager 榪涜閰嶇疆,榪欓噷鎴戜滑鍏堟潵娣誨姞鏂囨。娉ㄩ噴鏄劇ず.
          • 鎵撳紑 Program.cs 鏂囦歡.鑻ユ槸榪涜榪囧皝瑁?鍙兘浼氭槸鍏朵粬鏂囦歡,榪欓噷涓嶅仛鎺㈣,鎴戜滑鍏ㄩ儴閮藉湪 Program.cs 涓繘琛?
          • 鎴戜滑灝嗕唬鐮佹敼鎴愬涓嬪艦寮?/section>
          var builder=WebApplication.CreateBuilder(args);

          // Add services to the container.
          builder.Services.AddControllers();
          // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
          builder.Services.AddEndpointsApiExplorer();
          // 閰嶇疆Swagger
          builder.Services.AddSwaggerGen(c=>
          {
          // 濉啓鏂囨。鐨勪竴浜涘睘鎬?鍚嶇О,鐗堟湰鍜屾弿榪頒俊鎭?/span>
          c.SwaggerDoc("Swagger.Sample", new()
          {
          Title="Swagger.Sample",
          Version="v1",
          Description="Console.WriteLine(\"馃悅馃嵑\")"
          });
          // 鎵懼埌紼嬪簭榪愯鐩綍涓嬬殑鎵€鏈墄ml鏂囦歡
          var files=Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
          foreach (var file in files)
          {
          // 閰嶇疆娉ㄩ噴鏂囨。
          c.IncludeXmlComments(file, true);
          }
          });
          var app=builder.Build();

          // Configure the HTTP request pipeline.
          if (app.Environment.IsDevelopment())
          {
          app.UseSwagger();
          app.UseSwaggerUI(c=> c.SwaggerEndpoint("/swagger/Swagger.Sample/swagger.json", "Swagger.Sample v1"));
          }
          app.UseAuthorization();
          app.MapControllers();
          app.Run();
          • 鍙鎴戜滑鍦?AddSwaggerGen 鍜?UseSwaggerUI 涓兘娣誨姞浜嗕竴浜涢厤緗?璁?Swagger 鍙互鎵懼埌瀵瑰簲鐨?XML 娉ㄩ噴鏂囦歡,榪欐椂鍊欏啀閲嶆柊榪愯紼嬪簭,鍗沖彲鐪嬪埌娉ㄩ噴浜?
          • 榪欓噷鐨勯厤緗垜浠彲浠ョ湅鍒?涓嶇鏄枃?。鐨勫悕绉皹q樻槸 swagger.json 鏂囦歡璺緞鍧囨槸紜紪鐮佺殑,榪欐柟闈㈠悗杈圭殑璋冩暣涓細閫愭璋冩暣,榪欓噷鍏堜笉鐢ㄥ湪鎰?

          • 鍒拌繖閲屾敞閲婂氨鍩烘湰娣誨姞瀹屾垚,鍘熺悊涔熸噦浜?

          鏂囨。鍒嗙粍

          • 鎺ュ彛鏂囨。鍒嗙粍鎴戣繖閲屼嬌鐢ㄤ簡涓€浜涚壒鎬?閰嶅悎鍙嶅皠鏉ヨ幏鍙栧垎緇勪俊鎭?鎵€浠ユ垜浠渶瑕佸厛鍒涘緩涓€涓伐鍏風被鏉ュ府鍔╂垜浠柟渚夸嬌鐢ㄥ弽灝?
          • 鍒涘緩涓€涓?Tool 鏂囦歡澶?鐢ㄦ潵鏀句竴浜涙墿灞曠被.騫舵柊寤烘垜浠殑絎竴涓?榪欎釜渚嬪瓙閲屽簲璇ヤ篃鏄渶鍚庝竴涓?鎵╁睍綾?AssemblyHelper.cs,騫舵坊鍔犲涓嬩唬鐮?
          using Microsoft.Extensions.DependencyModel;
          using System.Reflection;
          using System.Runtime.Loader;

          namespace Swagger.Sample.Tools;

          /// <summary>
          /// 紼嬪簭闆嗗府鍔╃被
          /// </summary>
          // ReSharper disable once UnusedType.Global
          public static class AssemblyHelper
          {
          private static readonly string[] Filters={ "dotnet-", "Microsoft.", "mscorlib", "netstandard", "System", "Windows" };
          private static readonly IEnumerable<Assembly>? _allAssemblies;
          private static readonly IEnumerable<Type>? _allTypes;

          /// <summary>
          /// 闇€瑕佹帓闄ょ殑欏圭洰
          /// </summary>
          private static readonly List<string> FilterLibs=new();

          /// <summary>
          /// 鏋勯€犲嚱鏁?/span>
          /// </summary>
          static AssemblyHelper()
          {
          _allAssemblies=DependencyContext.Default?.GetDefaultAssemblyNames().Where(c=> c.Name is not && !Filters.Any(c.Name.StartsWith) && !FilterLibs.Any(c.Name.StartsWith)).Select(Assembly.Load);
          _allTypes=_allAssemblies?.SelectMany(c=> c.GetTypes());
          }

          /// <summary>
          /// 娣誨姞鎺掗櫎欏圭洰,璇ユ帓闄ら」鐩彲鑳戒細褰卞搷AutoDependenceInjection鑷姩娉ㄥ叆,璇蜂嬌鐢ㄧ殑鏃跺€欒嚜琛屾祴璇?
          /// </summary>
          /// <param name="names"></param>
          public static void AddExcludeLibs(params string[] names)=> FilterLibs.AddRangeIfNotContains(names);

          /// <summary>
          /// 鏍規嵁紼嬪簭闆嗗悕瀛楀緱鍒扮▼搴忛泦
          /// </summary>
          /// <param name="assemblyNames"></param>
          /// <returns></returns>
          public static IEnumerable<Assembly> GetAssembliesByName(params string[] assemblyNames)=> assemblyNames.Select(o=> AssemblyLoadContext.Default.LoadFromAssemblyPath(Path.Combine(AppContext.BaseDirectory, $"{o}.dll")));

          /// <summary>
          /// 鏌ユ壘鎸囧畾鏉′歡鐨勭被鍨?/span>
          /// </summary>
          public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate)=> _allTypes!.Where(predicate).ToArray();

          /// <summary>
          /// 鏌ユ壘鎵€鏈夋寚瀹氱壒鎬ф爣璁扮殑綾誨瀷
          /// </summary>
          /// <typeparam name="TAttribute"></typeparam>
          /// <returns></returns>
          public static IEnumerable<Type> FindTypesByAttribute<TAttribute>() where TAttribute : Attribute=> FindTypesByAttribute(typeof(TAttribute));

          /// <summary>
          /// 鏌ユ壘鎵€鏈夋寚瀹氱壒鎬ф爣璁扮殑綾誨瀷
          /// </summary>
          /// <param name="type"></param>
          /// <returns></returns>
          public static IEnumerable<Type> FindTypesByAttribute(Type type)=> _allTypes!.Where(a=> a.IsDefined(type, true)).Distinct().ToArray();

          /// <summary>
          /// 鏌ユ壘鎸囧畾鏉′歡鐨勭被鍨?/span>
          /// </summary>
          public static IEnumerable<Assembly> FindAllItems(Func<Assembly, bool> predicate)=> _allAssemblies!.Where(predicate).ToArray();

          /// <summary>
          /// 娣誨姞涓嶉噸澶嶇殑鍏冪礌
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="this"></param>
          /// <param name="values"></param>
          private static void AddRangeIfNotContains<T>(this ICollection<T> @this, params T[] values)
          {
          foreach (var obj in values)
          {
          if (@this.Contains(obj)) continue;
          @this.Add(obj);
          }
          }
          }
          • 鍐欏ソ甯姪綾誨悗,鍗沖彲鏂板緩涓€涓壒鎬х敤鏉ユ壙杞芥垜浠殑鍒嗙粍淇℃伅.
          • 鏂板緩涓€涓枃浠跺す Attributes 騫舵坊鍔?ApiGroupAttribute.cs,騫跺啓鍏ュ涓嬩唬鐮?
          namespace Swagger.Sample.Attributes;

          /// <summary>
          /// 琚鐗規€ф爣璁扮殑鎺у埗鍣ㄥ彲鍦⊿wagger鏂囨。鍒嗙粍涓彂鎸ヤ綔鐢?
          /// </summary>
          [AttributeUsage(AttributeTargets.Class)]
          // ReSharper disable once UnusedMember.Global
          // ReSharper disable once UnusedType.Global
          // ReSharper disable once ClassNeverInstantiated.Global
          public sealed class ApiGroupAttribute : Attribute
          {
          /// <summary>
          /// 鏋勯€犲嚱鏁?/span>
          /// </summary>
          /// <param name="title"></param>
          /// <param name="version"></param>
          /// <param name="description"></param>
          public ApiGroupAttribute(string title, string version, string description="")
          {
          Title=title;
          Version=version;
          Description=description;
          Name=$"{title}-{version}";
          }

          /// <summary>
          /// Doc鍚嶇О,$"{Title}-{Version}"鏍煎紡
          /// </summary>
          public string Name { get; }

          /// <summary>
          /// 鏍囬
          /// </summary>
          public string Title { get; }

          /// <summary>
          /// 鐗堟湰
          /// </summary>
          public string Version { get; }

          /// <summary>
          /// 鎻忚堪
          /// </summary>
          public string Description { get; }
          }
          • 鍏朵腑鍚勪釜瀛楁鐨勫惈涔?鍧囨湁娉ㄩ噴.鏂逛究鐞嗚В.榪欎釜鏃跺€欐垜浠噯澶囧伐浣滃氨鍋氬ソ浜?鍙互寮€濮嬫敼閫?Programe.cs 涓殑閰嶇疆浜?
          • 棣栧厛鍒涘緩鍑犱釜灞€閮ㄥ彉閲?鐢ㄦ潵瀛樺偍涓€浜涗俊鎭?
          // 鏂囨。鏍囬
          const string Title="Test"; // 鏂囨。鏍囬
          const string Version="v1"; // 鐗堟湰
          const string Name=$"{Title}-{Version}"; // 鏂囨。鍚嶇О
          Dictionary<string, string> docsDic=new(); // 鐢ㄦ潵瀛樺偍鏂囨。鍒嗙粍鐨勪俊鎭?/span>
          Dictionary<string, string> endPointDic=new(); // 瀛樺偍鏂囨。緇堢粨鐐筳son淇℃伅
          • 鐒跺悗淇敼 AddSwaggerGen 鍜?UseSwaggerUI 涓哄涓嬪唴瀹?
          • 涓轟簡鏂逛究,鍚庢湡鍧囦細灞曠ず瀹屾暣鐨?Programe.cs 浠g爜
          using Swagger.Sample.Attributes;
          using Swagger.Sample.Tools;
          using System.Reflection;

          var builder=WebApplication.CreateBuilder(args);

          // Add services to the container.
          builder.Services.AddControllers();
          // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
          builder.Services.AddEndpointsApiExplorer();

          // 閰嶇疆Swagger
          const string Title="Test"; // 鏂囨。鏍囬
          const string Version="v1"; // 鐗堟湰
          const string Name=$"{Title}-{Version}"; // 鏂囨。鍚嶇О
          Dictionary<string, string> docsDic=new(); // 鐢ㄦ潵瀛樺偍鏂囨。鍒嗙粍鐨勪俊鎭?/span>
          Dictionary<string, string> endPointDic=new(); // 瀛樺偍鏂囨。緇堢粨鐐筳son淇℃伅
          builder.Services.AddSwaggerGen(c=>
          {
          // 閰嶇疆榛樿鍒嗙粍
          c.SwaggerDoc(Name, new()
          {
          Title=Title,
          Version=Version,
          Description="Console.WriteLine(\"馃悅馃嵑\")"
          });
          // 閰嶇疆鏂囨。娉ㄩ噴
          var files=Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
          foreach (var file in files)
          {
          c.IncludeXmlComments(file, true);
          }
          // 鑾峰彇鎺у埗鍣ㄥ垎緇勪俊鎭拰閰嶇疆鍒嗙粍
          var controllers=AssemblyHelper.FindTypesByAttribute<ApiGroupAttribute>();
          foreach (var ctrl in controllers)
          {
          var attr=ctrl.GetCustomAttribute<ApiGroupAttribute>();
          if (attr is ) continue;
          if (docsDic.ContainsKey(attr.Name)) continue;
          _=docsDic.TryAdd(attr.Name, attr.Description);
          c.SwaggerDoc(attr.Name, new()
          {
          Title=attr.Title,
          Version=attr.Version,
          Description=attr.Description
          });
          }
          c.DocInclusionPredicate((docName, apiDescription)=>
          {
          //鍙嶅皠鎷垮埌鍊?/span>
          var actionList=apiDescription.ActionDescriptor.EndpointMetadata.Where(x=> x is ApiGroupAttribute).ToList();
          if (actionList.Count !=0)
          {
          return actionList.FirstOrDefault() is ApiGroupAttribute attr && attr.Name==docName;
          }
          //鍒ゆ柇鏄惁鍖呭惈榪欎釜鍒嗙粍
          var not=apiDescription.ActionDescriptor.EndpointMetadata.Where(x=> x is not ApiGroupAttribute).ToList();
          return not.Count !=0 && docName==Name;
          });
          });
          var app=builder.Build();

          // Configure the HTTP request pipeline.
          if (app.Environment.IsDevelopment())
          {
          app.UseSwagger();
          app.UseSwaggerUI(c=>
          {
          // 榛樿鍒嗙粍
          c.SwaggerEndpoint($"/swagger/{Name}/swagger.json", $"{Title} {Version}");
          // 閰嶇疆浣跨敤ApiGroupAttribute鐨勫垎緇?/span>
          var controllers=AssemblyHelper.FindTypesByAttribute<ApiGroupAttribute>();
          foreach (var ctrl in controllers)
          {
          var attr=ctrl.GetCustomAttribute<ApiGroupAttribute>();
          if (attr is ) continue;
          if (endPointDic.ContainsKey(attr.Name)) continue;
          _=endPointDic.TryAdd(attr.Name, attr.Description);
          c.SwaggerEndpoint($"/swagger/{attr.Name}/swagger.json", $"{attr.Title} {attr.Version}");
          }
          });
          }
          app.UseAuthorization();
          app.MapControllers();
          app.Run();
          • 榪欓噷鍒嗙粍鐨勯€昏緫浠g爜灝卞凡緇忓畬鎴愪簡,鎴戜滑鍐嶆柊寤?TwoController 鍜?ThreeController 鎺у埗鍣ㄦ潵婕旂ず鍒嗙粍.
          /// <summary>
          /// TwoController
          /// </summary>
          [Route("api/[controller]/[action]"), ApiController, ApiGroup("GroupOne", "v1", "絎竴涓垎緇?)]
          public class TwoController : ControllerBase
          {
          /// <summary>
          /// TwoHello
          /// </summary>
          /// <returns></returns>
          [HttpGet]
          public string TwoHello()=> "Hello GroupOne";
          }

          /// <summary>
          /// ThreeController
          /// </summary>
          [Route("api/[controller]/[action]"), ApiController, ApiGroup("GroupOne", "v1", "絎竴涓垎緇?)]
          public class ThreeController : ControllerBase
          {
          /// <summary>
          /// ThreeHello
          /// </summary>
          /// <returns></returns>
          [HttpGet]
          public string ThreeHello()=> "Hello GroupOne";
          }
          • 鍙互鐪嬪埌鎴戜滑鍒嗙粍鎴愬姛鍚?閫夋嫨 GroupOne 鍒嗙粍鍗沖彲鐪嬪埌 Two 鍜?Three 鎺у埗鍣ㄧ殑 API 浜?

          涓烘坊鍔犱簡 Authorize 鐗規€х殑鎺ュ彛娣誨姞閿佸浘鏍?/span>

          • Authorize 涓?NET 妗嗘灦鑷甫鐨勪竴涓壒鎬?琚粬鏍囪鐨勬帴鍙?鍙互琛ㄧず璇ユ帴鍙i渶瑕乀oken鏍¢獙閫氳繃鎵嶈兘璁塊棶.鎴戜滑鍙互浣跨敤 OpenApiSecurityScheme 鏉ヤ負鎺ュ彛娣誨姞閿?涓嶈繃榪欎釜鏂規鏈変釜緙虹偣,浼氭妸鎵€鏈夌殑鎺ュ彛鍧囧姞涓婇攣,鍏跺疄鎴戜滑瀹為檯寮€鍙戜腑鏈変簺鎺ュ彛鏄笉闇€瑕佺殑,铏界劧璁塊棶鍙兘娌℃湁浠€涔堥棶棰?浣嗘槸榪欎細緇欏墠绔€犳垚涓€浜涜瑙?姣斿鐧誨綍鎺ュ彛鏈変釜閿?灝變細璁╀漢寰堟嚨 馃樀.涓轟簡閬垮厤榪欎簺涓嶅繀瑕佺殑璇В.鎵€浠ュ氨鏈変簡榪欎釜闇€姹?涓哄彧鏍囪浜?Authorize 鐗規€х殑 API 娣誨姞閿佸浘鏍?
          • 鍦ㄩ」鐩噷鏂板緩涓€涓枃浠跺す SwaggerFilters,瀛樻斁鎴戜滑鐨勮嚜瀹氫箟鐨勪竴浜涢拡瀵?Swagger 鐨?Filters.榪欓噷鎴戜滑鍏堝垱寤虹涓€涓?SwaggerAuthorizeFilter.cs,騫舵坊鍔犲涓嬩唬鐮?
          /// <summary>
          /// 鍦⊿wagger鏂囨。涓粰闇€瑕丄uthorize鐨勬帴鍙f坊鍔狆煍?/span>
          /// </summary>
          // ReSharper disable once UnusedMember.Global
          // ReSharper disable once ClassNeverInstantiated.Global
          public sealed class SwaggerAuthorizeFilter : IOperationFilter
          {
          /// <summary>
          /// Apply
          /// </summary>
          /// <param name="operation"></param>
          /// <param name="context"></param>
          public void Apply(OpenApiOperation operation, OperationFilterContext context)
          {
          // 鍏堢瓫閫夊嚭鍖呭惈Authorize鐗規€х殑鎺ュ彛
          var authAttributes=context.MethodInfo.DeclaringType?.GetCustomAttributes(true)
          .Union(context.MethodInfo.GetCustomAttributes(true))
          .OfType<AuthorizeAttribute>();
          if (!authAttributes!.Any()) return;
          // 鐒跺悗涓哄叾娣誨姞SecurityScheme
          // 鐢變簬欏圭洰涓ぇ閮ㄥ垎浣跨敤鐨勯兘鏄痮auth2 Bearer Token璁よ瘉鎵€浠ヨ繖閲岄粯璁や互榪欑鏂瑰紡瀹炵幇.鍒殑鏂規璇瘋嚜琛岃皟鏁?
          operation.Security=new List<OpenApiSecurityRequirement>
          {
          new()
          {
          {
          new()
          {
          Reference=new()
          {
          Type=ReferenceType.SecurityScheme,
          Id="Bearer"
          },
          Scheme="oauth2",
          Name="Bearer",
          In=ParameterLocation.Header
          },
          new List<string>()
          }
          }
          };
          operation.Responses.Add("401", new() { Description="Unauthorized" });
          }
          }
          • 鍐欏ソ Fillter 鍚庝簨鎯呭氨綆€鍗曚簡.鍦?AddSwaggerGen 鏂規硶涓坊鍔犱竴琛屼唬鐮佸嵆鍙?
          builder.Services.AddSwaggerGen(c=>
          {
          ...
          c.DocInclusionPredicate((docName, apiDescription)=>
          {
          ...
          });
          c.OperationFilter<SwaggerAuthorizeFilter>(); // 涓烘帴鍙f坊鍔犻攣鍥炬爣
          });
          • 鎺ヤ笅鏉ュ湪 ThreeController 涓柊澧炰竴涓帴鍙f潵鍋氶獙璇?
          /// <summary>
          /// ThreeAuthorize
          /// </summary>
          /// <returns></returns>
          [HttpGet, Authorize]
          public string ThreeAuthorize()=> "Hello Authorize";
          • 閲嶆柊鍚姩紼嬪簭,鍗沖彲鍙戠幇娣誨姞浜?Authorize 鐗規€х殑鎺ュ彛宸茬粡鍔犱笂浜嗛攣.

          闅愯棌鎺ュ彛

          • 鏈変簺鍦烘櫙涓?鎴戜滑甯屾湜鏌愪簺鎺ュ彛鏄唴閮ㄤ嬌鐢?涓嶅澶栧叕寮€.鐢氳嚦涓嶉渶瑕佽鍓嶇鐭ラ亾.榪欎釜鏃跺€欐垜浠氨鍙互鍦?Swagger 閲岄殣钘忚繖縐嶆帴鍙f垨鑰呮帶鍒跺櫒.榪欐牱鍋氱殑鐩殑鏄負浜嗛檷浣庡墠绔伐紼嬪笀浜х敓鐨勮瑙?鍚屾椂涔熷彲浠ュ皢榪囨椂鐨勬帴鍙i殣钘忚搗鏉?閬垮厤鍓嶇浣跨敤閿欒,铏界劧榪囨椂鎺ュ彛鍙互浣跨敤 Obsolete 鐗規€ф潵鏍囪,浣嗘槸浠栬繕鏄兘鍦?Swagger 涓婄湅瑙?
          • 涓轟簡闅愯棌鎺ュ彛,鎴戜滑闇€瑕佹柊寤轟竴涓壒鎬х敤鏉ユ爣璁伴渶瑕侀殣钘忕殑鎺ュ彛鎴栬€呮帶鍒跺櫒.
          • 鍦?Attributes 鏂囦歡澶逛腑娣誨姞 HiddenApiAttribute.cs 騫舵坊鍔犲涓嬩唬鐮?
          /// <summary>
          /// 琚鐗規€ф爣璁扮殑Action鎴栬€呮帶鍒跺櫒鍙湪Swagger鏂囨。涓殣钘?
          /// </summary>
          [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
          public sealed class HiddenApiAttribute : Attribute { }
          • 鍚屾椂榪橀渶瑕佸湪 SwaggerFilters 鏂囦歡澶逛腑娣誨姞 SwaggerHiddenApiFilter.cs 鏉ュ疄鐜拌鏍囪鎺ュ彛闅愯棌.
          • 鍏跺師鐞嗗氨鏄皢琚?HiddenApiAttribute 鏍囪鐨勬帴鍙d粠 SwaggerDoc 涓Щ闄ゆ潵杈懼埌涓嶆樉紺虹殑鐩殑.
          /// <summary>
          /// 鍦⊿wagger鏂囨。涓殣钘忔帴鍙?/span>
          /// </summary>
          // ReSharper disable once UnusedMember.Global
          // ReSharper disable once ClassNeverInstantiated.Global
          public sealed class SwaggerHiddenApiFilter : IDocumentFilter
          {
          /// <summary>
          /// Apply
          /// </summary>
          /// <param name="swaggerDoc"></param>
          /// <param name="context"></param>
          public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
          {
          foreach (var apiDescription in context.ApiDescriptions)
          {
          #pragma warning disable IDE0048
          if (!apiDescription.TryGetMethodInfo(out var method) || !method.ReflectedType!.IsDefined(typeof(HiddenApiAttribute)) && !method.IsDefined(typeof(HiddenApiAttribute)))
          #pragma warning restore IDE0048
          continue;
          var key=$"/{apiDescription.RelativePath}";
          if (key.Contains('?'))
          {
          var index=key.IndexOf("?", StringComparison.Ordinal);
          key=key[..index];
          }
          _=swaggerDoc.Paths.Remove(key);
          }
          }
          }
          • 璇ヨ繃婊ゅ櫒鐨勪嬌鐢ㄦ柟娉曞拰鍓嶈竟鐨?SwaggerAuthorizeFilter 涓€鏍?鍙渶瑕佷竴琛屼唬鐮?
          builder.Services.AddSwaggerGen(c=>
          {
          ...
          c.OperationFilter<SwaggerAuthorizeFilter>(); // 涓烘帴鍙f坊鍔犻攣鍥炬爣
          c.DocumentFilter<SwaggerHiddenApiFilter>(); // 娣誨姞闅愯棌鎺ュ彛榪囨護
          });
          • 鎴戜滑鍐嶅湪 ThreeController 涓垱寤轟竴涓帴鍙f潵楠岃瘉璇ョ壒鎬ф槸鍚︾敓鏁?
          /// <summary>
          /// ThreeHidden
          /// </summary>
          /// <returns></returns>
          [HttpGet, HiddenApi]
          public string ThreeHidden()=> "Hello Hidden";
          • 閲嶆柊鍚姩紼嬪簭鍚?鎴戜滑浼氬彂鐜?ThreeHidden 騫舵湭鏄劇ず鍦?Swagger 涓鏄庢垜浠垚鍔熶簡.榪欓噷灝變笉鍐嶆埅鍥句簡.鍙互涓嬭澆婧愮爜鏌ョ湅鏁堟灉.
          • 鍚屾牱璇ョ壒鎬у彲浠ヤ綔鐢ㄤ簬鎺у埗鍣?榪欐牱鏁翠釜鎺у埗鍣ㄤ腑鐨勬帴鍙e潎涓嶄細鏄劇ず.

          涓哄弬鏁版坊鍔犻粯璁ゅ€兼樉紺?/span>

          • 鐩墠鎰熻榪欎釜鍔熻兘 Swagger 鏀寔榪樹笉澶熷畬緹?鏈変竴浜涚被鍨嬬殑鏁版嵁鏃犳硶姝e父閰嶇疆,涓嶈繃鍚庢湡浼氳秺鏉ヨ秺瀹屽杽鐨?
          • 榪欓噷鎴戜滑涔熸槸鍒╃敤涓€涓?NET 妗嗘灦鑷甫鐨勭壒鎬?DefaultValue 鏉ュ疄鐜?涓嶈繃鍚屾牱闇€瑕佽嚜宸卞啓涓€涓?Filter 鎵嶈兘瀹炵幇榪欑鍔熻兘.
          • 棣栧厛鎴戜滑鍦?SwaggerFilters 鏂囦歡澶逛腑鏂板緩涓€涓?Filter,鍚嶅瓧鍙?SwaggerSchemaFilter.cs 騫舵坊鍔犲涓嬩唬鐮?
          /// <summary>
          /// 娣誨姞榛樿鍊兼樉紺?/span>
          /// </summary>
          // ReSharper disable once UnusedMember.Global
          // ReSharper disable once ClassNeverInstantiated.Global
          public sealed class SwaggerSchemaFilter : ISchemaFilter
          {
          /// <summary>
          /// Apply
          /// </summary>
          /// <param name="schema"></param>
          /// <param name="context"></param>
          public void Apply(OpenApiSchema schema, SchemaFilterContext context)
          {
          if (schema.Properties is ) return;
          foreach (var info in context.Type.GetProperties())
          {
          // Look for class attributes that have been decorated with "[DefaultAttribute(...)]".
          var defaultAttribute=info.GetCustomAttribute<DefaultValueAttribute>();
          if (defaultAttribute is ) continue;
          foreach (var property in schema.Properties)
          {
          // Only assign default value to the proper element.
          if (ToCamelCase(info.Name) !=property.Key) continue;
          property.Value.Example=defaultAttribute.Value as IOpenApiAny;
          break;
          }
          }
          }

          /// <summary>
          /// 杞垚椹煎嘲褰㈠紡,榪欓噷闇€瑕佹敞鎰忎竴涓?鍙兘闇€瑕佹寜鐓т綘鑷繁鐨勫瓧孌佃鑼冭繘琛岃嚜瀹氫箟杞崲,涓嶇劧瀵逛笉涓?
          /// </summary>
          /// <param name="name"></param>
          /// <returns></returns>
          private static string ToCamelCase(string name)=> char.ToLowerInvariant(name[0]) + name[1..];
          }
          • 鍏朵腑 ToCamelCase 鏂規硶闇€瑕佹敞鎰忎竴涓?鎴戜滑浣跨敤榛樿鐨勯┘宄板艦寮忔潵琛ㄧず JSON 瀛楁,鎵€浠ヨ繖閲岃嫢鏄笉涓€鏍?闇€瑕佽嚜宸卞鐞嗕竴涓?
          • 鎺ヤ笅鏉ュ湪 Program.cs 涓厤緗?SwaggerSchemaFilter.
          builder.Services.AddSwaggerGen(c=>
          {
          ...
          c.DocumentFilter<SwaggerHiddenApiFilter>(); // 娣誨姞闅愯棌鎺ュ彛榪囨護
          c.SchemaFilter<SwaggerSchemaFilter>(); // 娣誨姞榛樿鍊兼樉紺?/span>
          });
          • 榪欎竴鍒囬兘鍋氬ソ浜嗗悗,鐜板湪鍥炲埌 FirstController.cs 涓?灝?PostParameter 綾昏皟鏁翠笅,涓轟簡鐩磋鐐?鎴戝姞浜嗕竴涓柊鐨勫璞?騫惰皟鏁存垚濡備笅浠g爜:
          /// <summary>
          /// POST鍙傛暟妯℃嫙
          /// </summary>
          public class PostParameter : PutParameter
          {
          /// <summary>
          /// Name
          /// </summary>
          [DefaultValue("寮犱笁")]
          public string Name { get; set; }=string.Empty;

          /// <summary>
          /// Age
          /// </summary>
          [DefaultValue(20)]
          public int Age { get; set; }

          /// <summary>
          /// 鐢熸棩
          /// </summary>
          [DefaultValue(typeof(DateTime), "2023-04-01")]
          public DateTime Birthday { get; set; }=DateTime.Now;
          }
          • 鍦ㄤ笂榪頒緥瀛愪腑,鎴戠粰 Name 瀛楁娣誨姞浜嗛粯璁ゅ€?寮犱笁,Age 娣誨姞浜嗛粯璁ゅ€?20,鏂板 Birthday 瀛楁騫惰緗粯璁ゅ€間負 23 騫存剼浜鴻妭.
          • DefaultValue 鐗規€х涓€涓弬鏁頒負鏁版嵁綾誨瀷,鎻愪緵浜嗗嚑涓粯璁ょ殑閲嶈澆,鑻ユ槸娌℃湁鐨勮瘽,鍙互浣跨敤 typeof 鏉ユ寚瀹氱被鍨?騫剁敤瀛楃涓茬殑褰㈠紡璁劇疆榛樿鍊兼樉紺?
          • 鍋氬ソ榪欎竴鍒囧悗,鍚姩紼嬪簭,鏉ヨ瀵熼粯璁ゅ€兼槸鍚﹁緗垚鍔?

          • 鍙互鐪嬪埌榪欎竴鍒囧潎鎸夌収鎴戜滑鐨勯鏈熷疄鐜?

          • 鍒拌繖閲屾垜鍦ㄥ伐浣滀腑浣跨敤鐨勫姛鑳藉凡緇忎粙緇嶅畬,鑻ユ槸浣犳湁鍏朵粬鐨勭帺娉?璇鋒彁渚?PR馃榿 鎴栬€呭憡璇夋垜涓€璧風爺絀?

          • 婧愮爜宸蹭笂浼犺嚦 GitHub: https://github.com/joesdu/Swagger.Sample

          • 浠ヤ笂鍔熻兘鍚屾牱鍦ㄦ垜鐨勫簱涓凡緇忛瀹氫箟.鍙互鍙傝€僂asilyNET.WebCore

          • Nuget 鍦板潃: https://www.nuget.org/packages/EasilyNET.WebCore

          • GitHub 鍦板潃: https://github.com/EasilyNET/EasilyNET

          • 鏈枃閾炬帴: https://github.com/EasilyNET/docs

          HP7宸茬粡鍙戝竷浜? 浣滀負PHP10騫存潵鏈€澶х殑鐗堟湰鍗囩駭, 鏈€澶х殑鎬ц兘鍗囩駭, PHP7鍦ㄥ鏀劇殑嫻嬭瘯涓兘琛ㄧ幇鍑哄緢鏄庢樉鐨勬€ц兘鎻愬崌, 鐒惰€? 涓轟簡璁╁畠鑳藉彂鎸ュ嚭鏈€澶х殑鎬ц兘, 鎴戣繕鏄湁鍑犱歡浜嬫兂鎻愰啋涓?

          PHP7 VS PHP5.6

          1. Opcache

          璁板緱鍚敤Zend Opcache, 鍥犱負PHP7鍗充嬌涓嶅惎鐢∣pcache閫熷害涔熸瘮PHP-5.6鍚敤浜哋pcache蹇? 鎵€浠ヤ箣鍓嶆祴璇曟椂鏈熷氨鍙戠敓浜嗘湁浜轟竴鐩存病鏈夊惎鐢∣pcache鐨勪簨鎯? 鍚敤Opcache闈炲父綆€鍗? 鍦╬hp.ini閰嶇疆鏂囦歡涓姞鍏?

          zend_extension=opcache.so
          opcache.enable=1
          opcache.enable_cli=1"
          

          2. 浣跨敤鏂扮殑緙栬瘧鍣?/strong>

          浣跨敤鏂頒竴鐐圭殑緙栬瘧鍣? 鎺ㄨ崘GCC 4.8浠ヤ笂, 鍥犱負鍙湁GCC 4.8浠ヤ笂PHP鎵嶄細寮€鍚疓lobal Register for opline and execute_data鏀寔, 榪欎釜浼氬甫鏉?%宸﹀彸鐨勬€ц兘鎻愬崌(Wordpres鐨凲PS瑙掑害琛¢噺)

          鍏跺疄GCC 4.8浠ュ墠鐨勭増鏈篃鏀寔, 浣嗘槸鎴戜滑鍙戠幇瀹冩敮鎸佺殑鏈塀ug, 鎵€浠ュ繀欏繪槸4.8浠ヤ笂鐨勭増鏈墠浼氬紑鍚繖涓壒鎬?

          3. HugePage

          鎴戜箣鍓嶇殑鏂囩珷涔熶粙緇嶈繃: 璁╀綘鐨凱HP7鏇村揩涔婬ugepage , 棣栧厛鍦ㄧ郴緇熶腑寮€鍚疕ugePages, 鐒跺悗寮€鍚疧pcache鐨刪uge_code_pages.

          浠ユ垜鐨凜entOS 6.5涓轟緥, 閫氳繃:

          $sudo sysctl vm.nr_hugepages=512
          

          鍒嗛厤512涓鐣欑殑澶ч〉鍐呭瓨:

          $ cat /proc/meminfo | grep Huge
          AnonHugePages: 106496 kB
          HugePages_Total: 512
          HugePages_Free: 504
          HugePages_Rsvd: 27
          HugePages_Surp: 0
          Hugepagesize: 2048 kB
          

          鐒跺悗鍦╬hp.ini涓姞鍏?

           opcache.huge_code_pages=1
          

          榪欐牱涓€鏉? PHP浼氭妸鑷韓鐨則ext孌? 浠ュ強鍐呭瓨鍒嗛厤涓殑huge閮介噰鐢ㄥぇ鍐呭瓨欏墊潵淇濆瓨, 鍑忓皯TLB miss, 浠庤€屾彁楂樻€ц兘.

          4. Opcache file cache

          寮€鍚疧pcache File Cache(瀹為獙鎬?, 閫氳繃寮€鍚繖涓? 鎴戜滑鍙互璁㎡pcache鎶妎pcode緙撳瓨緙撳瓨鍒板閮ㄦ枃浠朵腑, 瀵逛簬涓€浜涜剼鏈? 浼氭湁寰堟槑鏄劇殑鎬ц兘鎻愬崌.

          鍦╬hp.ini涓姞鍏?

          opcache.file_cache=/tmp
          

          榪欐牱PHP灝變細鍦?tmp鐩綍涓婥ache涓€浜汷pcode鐨勪簩榪涘埗瀵煎嚭鏂囦歡, 鍙互璺≒HP鐢熷懡鍛ㄦ湡瀛樺湪.

          5. PGO

          鎴戜箣鍓嶇殑鏂囩珷: 璁╀綘鐨凱HP7鏇村揩(GCC PGO) 涔熶粙緇嶈繃, 濡傛灉浣犵殑PHP鏄笓闂ㄤ負涓€涓」鐩湇鍔? 姣斿鍙槸涓轟綘鐨刉ordpress, 鎴栬€卍rupal, 鎴栬€呭叾浠栦粈涔? 閭d箞浣犲氨鍙互灝濊瘯閫氳繃PGO, 鏉ユ彁鍗嘝HP, 涓撻棬涓轟綘鐨勮繖涓」鐩彁楂樻€ц兘.

          鍏蜂綋鐨? 浠ordpress 4.1涓轟紭鍖栧満鏅?. 棣栧厛鍦ㄧ紪璇慞HP鐨勬椂鍊欓鍏?

          $ make prof-gen
          

          鐒跺悗鐢ㄤ綘鐨勯」鐩緇働HP, 姣斿瀵逛簬Wordpress:

          $ sapi/cgi/php-cgi -T 100 /home/huixinchen/local/www/htdocs/wordpress/index.php >/dev/null
          

          涔熷氨鏄php-cgi璺?00閬峸ordpress鐨勯欏? 浠庤€岀敓鎴愪竴浜涘湪榪欎釜榪囩▼涓殑profile淇℃伅.

          鏈€鍚?

          $ make prof-clean
          $ make prof-use && make install
          

          榪欎釜鏃跺€欎綘緙栬瘧寰楀埌鐨凱HP7灝辨槸涓轟綘鐨勯」鐩噺韜墦閫犵殑鏈€楂樻€ц兘鐨勭紪璇戠増鏈?


          主站蜘蛛池模板: 高清无码一区二区在线观看吞精| 国产精品日本一区二区在线播放| 中日韩一区二区三区| 免费一本色道久久一区| 激情亚洲一区国产精品| 日韩人妻无码一区二区三区综合部| 久久99精品免费一区二区| 无码精品久久一区二区三区| 色窝窝无码一区二区三区色欲 | 久久亚洲AV午夜福利精品一区| 无码少妇精品一区二区免费动态| 国产成人一区二区三中文| 欧洲精品码一区二区三区| 狠狠色成人一区二区三区| 国产在线精品一区二区在线看 | 色综合视频一区二区三区44| 一区二区三区免费在线视频| 麻豆天美国产一区在线播放| 国产成人欧美一区二区三区| 中文字幕日本精品一区二区三区| 国产精品无码一区二区在线观| 午夜性色一区二区三区免费不卡视频| 美女AV一区二区三区| 日本一区二区三区不卡在线视频 | 无码国产精品一区二区免费3p | 精品国产日韩一区三区| 中日韩一区二区三区| 久久久91精品国产一区二区| 国模无码人体一区二区| 久久久国产精品亚洲一区| 国产精品福利一区| 中文字幕精品一区| 国产乱码精品一区二区三区麻豆 | 无码少妇一区二区浪潮av| 无码囯产精品一区二区免费| 99在线精品一区二区三区| 国产成人精品亚洲一区| 成人免费视频一区二区三区| 国产精品女同一区二区| 欧美日韩综合一区二区三区| 韩国福利一区二区三区高清视频|