├── .gitignore ├── LICENSE ├── README.md ├── app ├── affix │ ├── event │ │ └── event.php │ ├── lang │ │ └── lin.en.php │ ├── response │ │ ├── jsonxml │ │ │ └── template.php │ │ └── view │ │ │ └── welcome.php │ └── route │ │ └── route.php ├── block │ ├── formatter │ │ └── Formatter.php │ ├── mapper │ │ └── Mapper.php │ ├── model │ │ └── Model.php │ └── validator │ │ └── Validator.php ├── boot.php ├── boot.production.php ├── config │ ├── lin-servers.php │ ├── lin-servers.production.php │ ├── lin.php │ └── lin.production.php ├── layer │ ├── Error.php │ └── Index.php ├── lib │ └── helper.php └── register.php ├── composer.json └── public ├── .htaccess ├── index.php ├── resource └── lin.css ├── robots.txt └── web.config /.gitignore: -------------------------------------------------------------------------------- 1 | /data 2 | /cache 3 | /vendor 4 | /.idea 5 | /.vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 本程序采用apache2.0开源协议。作者:林澜叶(linlanye)版权所有 2 | 3 | 4 | Apache License 5 | Version 2.0, January 2004 6 | http://www.apache.org/licenses/ 7 | 8 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 9 | 10 | 1. Definitions. 11 | 12 | "License" shall mean the terms and conditions for use, reproduction, 13 | and distribution as defined by Sections 1 through 9 of this document. 14 | 15 | "Licensor" shall mean the copyright owner or entity authorized by 16 | the copyright owner that is granting the License. 17 | 18 | "Legal Entity" shall mean the union of the acting entity and all 19 | other entities that control, are controlled by, or are under common 20 | control with that entity. For the purposes of this definition, 21 | "control" means (i) the power, direct or indirect, to cause the 22 | direction or management of such entity, whether by contract or 23 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 24 | outstanding shares, or (iii) beneficial ownership of such entity. 25 | 26 | "You" (or "Your") shall mean an individual or Legal Entity 27 | exercising permissions granted by this License. 28 | 29 | "Source" form shall mean the preferred form for making modifications, 30 | including but not limited to software source code, documentation 31 | source, and configuration files. 32 | 33 | "Object" form shall mean any form resulting from mechanical 34 | transformation or translation of a Source form, including but 35 | not limited to compiled object code, generated documentation, 36 | and conversions to other media types. 37 | 38 | "Work" shall mean the work of authorship, whether in Source or 39 | Object form, made available under the License, as indicated by a 40 | copyright notice that is included in or attached to the work 41 | (an example is provided in the Appendix below). 42 | 43 | "Derivative Works" shall mean any work, whether in Source or Object 44 | form, that is based on (or derived from) the Work and for which the 45 | editorial revisions, annotations, elaborations, or other modifications 46 | represent, as a whole, an original work of authorship. For the purposes 47 | of this License, Derivative Works shall not include works that remain 48 | separable from, or merely link (or bind by name) to the interfaces of, 49 | the Work and Derivative Works thereof. 50 | 51 | "Contribution" shall mean any work of authorship, including 52 | the original version of the Work and any modifications or additions 53 | to that Work or Derivative Works thereof, that is intentionally 54 | submitted to Licensor for inclusion in the Work by the copyright owner 55 | or by an individual or Legal Entity authorized to submit on behalf of 56 | the copyright owner. For the purposes of this definition, "submitted" 57 | means any form of electronic, verbal, or written communication sent 58 | to the Licensor or its representatives, including but not limited to 59 | communication on electronic mailing lists, source code control systems, 60 | and issue tracking systems that are managed by, or on behalf of, the 61 | Licensor for the purpose of discussing and improving the Work, but 62 | excluding communication that is conspicuously marked or otherwise 63 | designated in writing by the copyright owner as "Not a Contribution." 64 | 65 | "Contributor" shall mean Licensor and any individual or Legal Entity 66 | on behalf of whom a Contribution has been received by Licensor and 67 | subsequently incorporated within the Work. 68 | 69 | 2. Grant of Copyright License. Subject to the terms and conditions of 70 | this License, each Contributor hereby grants to You a perpetual, 71 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 72 | copyright license to reproduce, prepare Derivative Works of, 73 | publicly display, publicly perform, sublicense, and distribute the 74 | Work and such Derivative Works in Source or Object form. 75 | 76 | 3. Grant of Patent License. Subject to the terms and conditions of 77 | this License, each Contributor hereby grants to You a perpetual, 78 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 79 | (except as stated in this section) patent license to make, have made, 80 | use, offer to sell, sell, import, and otherwise transfer the Work, 81 | where such license applies only to those patent claims licensable 82 | by such Contributor that are necessarily infringed by their 83 | Contribution(s) alone or by combination of their Contribution(s) 84 | with the Work to which such Contribution(s) was submitted. If You 85 | institute patent litigation against any entity (including a 86 | cross-claim or counterclaim in a lawsuit) alleging that the Work 87 | or a Contribution incorporated within the Work constitutes direct 88 | or contributory patent infringement, then any patent licenses 89 | granted to You under this License for that Work shall terminate 90 | as of the date such litigation is filed. 91 | 92 | 4. Redistribution. You may reproduce and distribute copies of the 93 | Work or Derivative Works thereof in any medium, with or without 94 | modifications, and in Source or Object form, provided that You 95 | meet the following conditions: 96 | 97 | (a) You must give any other recipients of the Work or 98 | Derivative Works a copy of this License; and 99 | 100 | (b) You must cause any modified files to carry prominent notices 101 | stating that You changed the files; and 102 | 103 | (c) You must retain, in the Source form of any Derivative Works 104 | that You distribute, all copyright, patent, trademark, and 105 | attribution notices from the Source form of the Work, 106 | excluding those notices that do not pertain to any part of 107 | the Derivative Works; and 108 | 109 | (d) If the Work includes a "NOTICE" text file as part of its 110 | distribution, then any Derivative Works that You distribute must 111 | include a readable copy of the attribution notices contained 112 | within such NOTICE file, excluding those notices that do not 113 | pertain to any part of the Derivative Works, in at least one 114 | of the following places: within a NOTICE text file distributed 115 | as part of the Derivative Works; within the Source form or 116 | documentation, if provided along with the Derivative Works; or, 117 | within a display generated by the Derivative Works, if and 118 | wherever such third-party notices normally appear. The contents 119 | of the NOTICE file are for informational purposes only and 120 | do not modify the License. You may add Your own attribution 121 | notices within Derivative Works that You distribute, alongside 122 | or as an addendum to the NOTICE text from the Work, provided 123 | that such additional attribution notices cannot be construed 124 | as modifying the License. 125 | 126 | You may add Your own copyright statement to Your modifications and 127 | may provide additional or different license terms and conditions 128 | for use, reproduction, or distribution of Your modifications, or 129 | for any such Derivative Works as a whole, provided Your use, 130 | reproduction, and distribution of the Work otherwise complies with 131 | the conditions stated in this License. 132 | 133 | 5. Submission of Contributions. Unless You explicitly state otherwise, 134 | any Contribution intentionally submitted for inclusion in the Work 135 | by You to the Licensor shall be under the terms and conditions of 136 | this License, without any additional terms or conditions. 137 | Notwithstanding the above, nothing herein shall supersede or modify 138 | the terms of any separate license agreement you may have executed 139 | with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade 142 | names, trademarks, service marks, or product names of the Licensor, 143 | except as required for reasonable and customary use in describing the 144 | origin of the Work and reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or 147 | agreed to in writing, Licensor provides the Work (and each 148 | Contributor provides its Contributions) on an "AS IS" BASIS, 149 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 150 | implied, including, without limitation, any warranties or conditions 151 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 152 | PARTICULAR PURPOSE. You are solely responsible for determining the 153 | appropriateness of using or redistributing the Work and assume any 154 | risks associated with Your exercise of permissions under this License. 155 | 156 | 8. Limitation of Liability. In no event and under no legal theory, 157 | whether in tort (including negligence), contract, or otherwise, 158 | unless required by applicable law (such as deliberate and grossly 159 | negligent acts) or agreed to in writing, shall any Contributor be 160 | liable to You for damages, including any direct, indirect, special, 161 | incidental, or consequential damages of any character arising as a 162 | result of this License or out of the use or inability to use the 163 | Work (including but not limited to damages for loss of goodwill, 164 | work stoppage, computer failure or malfunction, or any and all 165 | other commercial damages or losses), even if such Contributor 166 | has been advised of the possibility of such damages. 167 | 168 | 9. Accepting Warranty or Additional Liability. While redistributing 169 | the Work or Derivative Works thereof, You may choose to offer, 170 | and charge a fee for, acceptance of support, warranty, indemnity, 171 | or other liability obligations and/or rights consistent with this 172 | License. However, in accepting such obligations, You may act only 173 | on Your own behalf and on Your sole responsibility, not on behalf 174 | of any other Contributor, and only if You agree to indemnify, 175 | defend, and hold each Contributor harmless for any liability 176 | incurred by, or claims asserted against, such Contributor by reason 177 | of your accepting any such warranty or additional liability. 178 | 179 | END OF TERMS AND CONDITIONS 180 | 181 | APPENDIX: How to apply the Apache License to your work. 182 | 183 | To apply the Apache License to your work, attach the following 184 | boilerplate notice, with the fields enclosed by brackets "[]" 185 | replaced with your own identifying information. (Don't include 186 | the brackets!) The text should be enclosed in the appropriate 187 | comment syntax for the file format. We also recommend that a 188 | file or class name and description of purpose be included on the 189 | same "printed page" as the copyright notice for easier 190 | identification within third-party archives. 191 | 192 | Copyright 2018- linlanye 193 | 194 | Licensed under the Apache License, Version 2.0 (the "License"); 195 | you may not use this file except in compliance with the License. 196 | You may obtain a copy of the License at 197 | 198 | http://www.apache.org/licenses/LICENSE-2.0 199 | 200 | Unless required by applicable law or agreed to in writing, software 201 | distributed under the License is distributed on an "AS IS" BASIS, 202 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 203 | See the License for the specific language governing permissions and 204 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lin/1.0 2 | [![Latest Stable Version](https://poser.pugx.org/lin/lin/v/stable)](https://packagist.org/packages/lin/lin) 3 | [![Total Downloads](https://poser.pugx.org/lin/lin/downloads)](https://packagist.org/packages/lin/lin) 4 | [![PHP Version](https://img.shields.io/badge/php-%3E%3D7.2-8892BF.svg)](http://www.php.net/) 5 | [![License](https://poser.pugx.org/lin/lin/license)](https://packagist.org/packages/lin/lin) 6 | 7 | ## 介绍 8 | 9 | **Lin是**一套基于php7.2的全新web框架,它具有一套全组件化的开发理念,避免了以往web框架可定制性差、扩展开发繁杂、布局耦合度较高等缺点,完美实现了三重分离:应用层、框架层、组件层。使用者只需通过堆积木形式将一个个功能进行组装即可,而无需花费大量精力去理解一个框架的核心理念。Lin解耦了绝大多数开发场景,让协同开发更为简单,并且应用结构从一开始就基于高度弹性化的架构模式,对后续扩展、维护、升级都可以0成本轻松实现。 10 | 11 | ## 特性 12 | 13 | * 全组件化,框架运行流程完全由使用者自行控制,通过一个个组件堆积而成。 14 | * 自带模拟kv、queue服务器,无需安装memcache和redis等外部环境,并可轻松一键切换。 15 | * 原生透明化支持SQL、Key-Value、Queue等服务器主从、多节点访问。 16 | * 极简主义设计。所有的方法无论命名、调用都保持简单一致,只呈现最基本的php语法。 17 | * 新的组织架构,解决传统MVC模式的短板,可对应用轻量化弹性升级,该架构称为LBA(Layer, Block, Affix,见下述解释)。 18 | * 涵盖web开发的绝大多数场景,组件功能接口简单,学习接近0成本。(参见[lin/components](http://github.com/linlanye/lin-components)) 19 | * 高度优化并整合的组件功能,如数据模型、数据校验、安全场景、视图、路由等。 20 | * 生产环境和开发环境无缝替换,生产部署极致简单。 21 | 22 | 23 | ## LBA架构 24 | 25 | LBA(Layer, Block, Affix)架构由层、块、摆件三个部分构成,由**林澜叶**独自提出。 26 | 27 | * **层**:核心架构所在,由整套不同的逻辑单元组成,彼此之间相互独立,是整个应用的骨架部分。如缓存层、数据访问层、控制器层、响应层等等。不同的层提供不同的应用场景,一个层可以看作一个用于调度不同功能的类。 28 | * **块**:依托于层而存在,为层提供一种功能,是对层功能的具体实现,是整个应用的血肉部分。一个块可以看作是具有某个功能的类,不同的块在同一个层中构成一个完备的应用场景。如在数据访问层中,数据模型提供对数据库的对象化操作,数据格式化器和映射器则提供存储数据到应用数据的一个映射。 29 | * **摆件**:作为对层的点缀或装饰,是一种可选的功能,它的添加和移除对整个应用架构没有影响。不同的摆件可以看作是一种功能扩展,它可以是一个类,也可以是一个脚本,一句代码,起到强化应用的作用。如视图页面、路由文件、语言包等在小型应用中都可以看作摆件,可以无需视图(API开发),也可以无需路由(仅通过层来调度),更可以无需语言包。 30 | 31 | 对于MVC架构,Model相当于块,View则为摆件,Controller则对应层。基于MVC的各种变体也能在LBA架构中找到对应,实际上LBA正是对这套架构体系的一个更抽象的扩展,它能够适用于更大型的应用架构中。值得注意的是,LBA架构并没有对功能进行约束,开发者需根据实际情况选型。例如小型应用中路由可以看作摆件,但在大型应用中,路由则应作为层。 32 | 33 | ## 目录结构 34 | 35 | 初始主要结构如下: 36 | ~~~ 37 | your_app 38 | │ 39 | ├─app 应用目录 40 | │ │ 41 | │ ├─affix 摆件目录 42 | │ │ ├─event 事件目录 43 | │ │ ├─lang 语言包目录 44 | │ │ ├─response 响应目录 45 | │ │ │ ├─jsonxml json和xml的模版目录 46 | │ │ │ └─view 视图页面目录 47 | │ │ │ 48 | │ │ └─route 路由规则目录 49 | │ │ 50 | │ ├─block 块目录 51 | │ │ ├─formatter 数据格式化器目录 52 | │ │ ├─mapper 数据映射器目录 53 | │ │ ├─model 数据模型目录 54 | │ │ └─validator 数据验证器目录 55 | │ │ 56 | │ ├─config 配置目录 57 | │ │ ├─lin-servers.php 服务器配置 58 | │ │ ├─lin-servers.production.php 服务器配置(生产环境) 59 | │ │ ├─lin.php 组件配置 60 | │ │ └─lin.production.php 组件配置(生产环境) 61 | │ │ 62 | │ ├─layer 层目录 63 | │ │ 64 | │ ├─lib 库目录 65 | │ │ └─helper.php lin组件的助手函数 66 | │ │ 67 | │ ├─boot.production.php 启动文件(生产环境) 68 | │ ├─boot.php 启动文件 69 | │ └─register.php basement组件注册文件 70 | │ 71 | ├─public 入口根目录 72 | │ ├─resource 资源文件夹 73 | │ └─index.php 入口文件 74 | │ 75 | ├─vendor 组件目录 76 | │ ├─composer composer组件 77 | │ ├─basement basement组件 78 | │ └─lin lin组件 79 | │ 80 | ~~~ 81 | 82 | 83 | ## 安装 84 | 85 | ``` 86 | //1.composer方式 87 | composer create-project lin/lin 88 | 89 | //2.源码+composer 90 | 进入源码根目录,执行composer install 91 | 92 | //3.下载压缩文件 93 | https://downloads.lin-php.com/lin-1.0.0.zip 94 | ``` 95 | 96 | 97 | ## 使用 98 | 99 | * 在`app/boot.php`文件中定义整个应用执行流程。同理编写生产环境的`app/boot.production.php`文件 100 | * 在`app/register.php`文件中注册[basement](http://github.com/linlanye/basement)的标准组件。 101 | * 在`app/layer`目录中,根据应用复杂度,建立不同的层或建立不同的目录归档不同的层。 102 | * 在`app/block`目录中,根据具体业务场景,建立各种块,如数据模型、映射、校验、格式化等。 103 | * 在`app/affix`目录中,根据需求建立摆件,如定义事件、路由、多语言、视图页面或json的响应模版。 104 | * 在`app/config`目录中,根据实际情况更改配置文件。 105 | * 在`app/lib`目录中,存放自己的库函数或第三方类库。 106 | * 生产环境下,更改`public/index.php`中启动文件为`app/boot.production.php`。 107 | 108 | 109 | ## 开发建议 110 | * 使用basement组件的情况,使用`Linker`类来调用,具体见[basement](http://github.com/linlanye/basement)。 111 | * 文件夹全小写。 112 | * 满足psr-4规则。 113 | * 使用 `/` 作为目录分隔符。 114 | 115 | 116 | ## 详细文档 117 | * [github](https://github.com/linlanye/lin-docs) 118 | * [官网](https://docs.lin-php.com) 119 | 120 | ## 捐赠 121 | ![捐赠林澜叶](https://img.lin-php.com/donations.png) 122 | 123 | ## 版权信息 124 | * 作者:林澜叶(linlanye)版权所有。 125 | * Eemail:linlanye@sina.cn 126 | * 开源协议:[Apache-2.0](LICENSE) 127 | -------------------------------------------------------------------------------- /app/affix/event/event.php: -------------------------------------------------------------------------------- 1 | 'failed to create folder', 5 | '文件打开失败' => 'failed to open file', 6 | '文件不存在' => 'file not exists', 7 | '缺少可用文件' => 'lack of valid file', 8 | '路由无法缓存闭包,闭包占用需超1行' => 'unable to cache the Closure, there must be two lines of code at least', 9 | '路由规则需用"."分割' => 'routing rules need "." to explode', 10 | '路由规则冲突' => 'conflict in routing rules', 11 | '验证方法不存在' => 'validation method not exists', 12 | '验证规则不存在' => 'validation rule not exists', 13 | '格式化方法不存在' => 'formatting method not exists', 14 | '当前数据超过文件大小限制' => 'the size of data exceeds the max file size', 15 | '冗余文件阈值不可超过PHP_INT_MAX' => 'the thrshold of the redundant file size must be less than PHP_INT_MAX', 16 | '无法写入数据,当前队列已满' => 'unable to write data due to full queue', 17 | '服务器连接失败' => 'failed to connect server', 18 | '缺少可用服务器' => 'lack of valid server', 19 | '预处理语句失败' => 'failed to preprocess statement', 20 | '未定义的方法' => 'undefined method', 21 | '未指定表名' => 'lack of table name', 22 | '未指定主键' => 'lack of primary key', 23 | '关联主字段和从字段数量不一致' => 'the count of relational fields between master and slave is inconsistent', 24 | '主键数量不匹配' => 'the number of primary keys is inconsistent', 25 | '缺少主键数据,更新或删除无法执行' => 'lack of primary keys, the method of update or delete can not be executed', 26 | '关系模型数据为空,不可写入' => 'unable to write due to the empty relational model', 27 | '更新和删除必须存在条件限制' => 'there must be conditions for updating and deleting', 28 | '操作符不存在' => 'operator not exists', 29 | '批量插入数据的格式不一致' => 'the format of bulk data for insertion is inconsistent', 30 | 31 | /**错误信息**/ 32 | '缺少有效从模型,当前关联操作已略过' => 'lack of valid slave, the current relational operation is skipped', 33 | '缺少有效关联主字段,当前关联操作已略过' => 'lack of valid master fields, the current relational operation is skipped', 34 | 35 | /*DEBUG信息*/ 36 | '总耗时' => 'Total Time Cost', 37 | '吞吐率' => 'Throughput', 38 | '内存用量' => 'Memory Cost', 39 | '操作系统' => 'Operate System', 40 | '服务器软件' => 'Server Software', 41 | '临时文件夹' => 'Temporary Folder', 42 | '统计' => 'Statistics', 43 | '执行数' => 'Running Count', 44 | '文件数' => 'File Count', 45 | '事件数' => 'Event Count', 46 | '日志数' => 'Log Count', 47 | '记录数' => 'Record Count', 48 | '格式化数' => 'Formatting Count', 49 | '映射数' => 'Mapping Count', 50 | '创建数' => 'Building Count', 51 | '流程数' => 'Flow Count', 52 | '规则数' => 'Rule Count', 53 | '文件明细' => 'File List', 54 | '事件明细' => 'Event List', 55 | '日志明细' => 'Log List', 56 | '记录明细' => 'Record List', 57 | '格式化明细' => 'Formatting List', 58 | '映射明细' => 'Mapping List', 59 | '执行明细' => 'Running List', 60 | '流程明细' => 'Flow List', 61 | '创建明细' => 'Building List', 62 | '规则明细' => 'Rule List', 63 | '配置明细' => 'Configuration List', 64 | '路由类型' => 'Routing Type', 65 | '缓存文件' => 'Cache File', 66 | ]; 67 | -------------------------------------------------------------------------------- /app/affix/response/jsonxml/template.php: -------------------------------------------------------------------------------- 1 | 'ok', 'content' => null, 'code' => 0]; 8 | -------------------------------------------------------------------------------- /app/affix/response/view/welcome.php: -------------------------------------------------------------------------------- 1 | {use lin\url\URL} 2 | 3 | 4 | 5 | Lin: 全组件化php框架 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

Lin

14 |

简单、高效、完备

15 |

基于PHP7.2的极简主义框架

16 |
17 | 34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/affix/route/route.php: -------------------------------------------------------------------------------- 1 | 动态 > 通用 5 | */ 6 | 7 | $Route = lin\route\Route::getCreator(); 8 | 9 | $Route->create([ 10 | '/' => 'Index.index', 11 | ]); 12 | -------------------------------------------------------------------------------- /app/block/formatter/Formatter.php: -------------------------------------------------------------------------------- 1 | setRule('format_id', [ 12 | 'id: must' => 'toInt', //创建format_id规则,将id强行格式化为整型 13 | ]); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/block/mapper/Mapper.php: -------------------------------------------------------------------------------- 1 | setRule('map_id', [ 12 | 'id: must' => 'user_id', //创建map_id规则,将id字段强制映射为user_id 13 | ]); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/block/model/Model.php: -------------------------------------------------------------------------------- 1 | setTable('table')->setPK('id'); //手动指定表名和主键名 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/block/validator/Validator.php: -------------------------------------------------------------------------------- 1 | setRule('valid_id', [ 13 | 'id: must' => ['isInt', 'id必须为整数'], //创建valid_id规则,对id字段强制校验整型且设置错误信息 14 | ]); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/boot.php: -------------------------------------------------------------------------------- 1 | [ //使用pdo作为sql配置的代表 12 | 'r' => ['dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8', //不同sql产品的dsn参考pdo说明 13 | 'user' => 'root', //连接账号 14 | 'pwd' => 'root', //连接密码 15 | 'weight' => 99, //权重,多个数据服务器存在时有用,不同模式下权重分开计算 16 | 'mode' => 'r', //访问模式,r为只读,w为只写,其余为读写,分别设置两个便可实现读写分离 17 | ], 18 | 'w' => ['dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8', 19 | 'user' => 'root', 20 | 'pwd' => 'root', 21 | 'weight' => 99, 22 | 'mode' => 'w', 23 | ], 24 | ], 25 | 'memcached' => [ 26 | ['host' => '127.0.0.1', 'port' => 11211, 'weight' => 99], 27 | ], 28 | 'redis' => [ 29 | 'kv0' => ['host' => '127.0.0.1', 'port' => '6379', 'pwd' => '', 'weight' => 99, 'timeout' => 1], 30 | 'queue0' => ['host' => '127.0.0.1', 'port' => '6379', 'pwd' => '', 'weight' => 99, 'timeout' => 1], 31 | ], 32 | ]; 33 | -------------------------------------------------------------------------------- /app/config/lin-servers.production.php: -------------------------------------------------------------------------------- 1 | [ 7 | 'r' => ['dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8', 8 | 'user' => 'root', 9 | 'pwd' => 'root', 10 | 'weight' => 99, 11 | 'mode' => 'r', 12 | ], 13 | 'w' => ['dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8', 14 | 'user' => 'root', 15 | 'pwd' => 'root', 16 | 'weight' => 99, 17 | 'mode' => 'w', 18 | ], 19 | ], 20 | 'memcached' => [ 21 | ['host' => '127.0.0.1', 'port' => 11211, 'weight' => 99], 22 | ], 23 | 'redis' => [ 24 | 'kv0' => ['host' => '127.0.0.1', 'port' => '6379', 'pwd' => '', 'weight' => 99, 'timeout' => 1], 25 | 'queue0' => ['host' => '127.0.0.1', 'port' => '6379', 'pwd' => '', 'weight' => 99, 'timeout' => 1], 26 | ], 27 | ]; 28 | -------------------------------------------------------------------------------- /app/config/lin.php: -------------------------------------------------------------------------------- 1 | $root . '/data', //数据目录 15 | 'cache' => $root . '/cache', //缓存目录 16 | 'config' => $root . '/config', //配置目录 17 | 'lang' => $root . '/app/affix/lang', //语言包目录 18 | 'route' => $root . '/app/affix/route', //路由目录 19 | 'event' => $root . '/app/affix/event', //事件目录 20 | 'view' => $root . '/app/affix/response/view', //视图目录 21 | 'jsonxml' => $root . '/app/affix/response/jsonxml', //json, xml模板目录 22 | 'components' => $root . '/vendor/lin/components/src', //框架目录 23 | ]; 24 | 25 | //以下才为配置信息 26 | return [ 27 | /*****basement组件*****/ 28 | 29 | /*配置组件*/ 30 | 'config' => [ 31 | 'path' => $lin['config'], //配置文件夹路径 32 | 'debug' => true, 33 | ], 34 | /*调试组件*/ 35 | 'debug' => [ 36 | 'panel' => [ //调试面板 37 | 'display' => 'only', //显示模式,空或none不显示,both显示全部,only显示小图标 38 | 'name' => [ 39 | 'prior' => 'SYSTEM', //优先选中标识名 40 | 'hidden' => [], //隐藏的标识名 41 | ], 42 | ], 43 | 'lang' => 'none', //多语言显示,空或none为关闭,only为多语言仅用于显示,但数据依然为原文,both为数据和显示都为多语言 44 | 'default' => [ 45 | 'name' => 'LIN', //默认调试标识名 46 | ], 47 | ], 48 | /*事件组件*/ 49 | 'event' => [ 50 | 'path' => $lin['event'], //存放定义事件的文件夹 51 | 'debug' => true, 52 | ], 53 | /*语言映射组件*/ 54 | 'lang' => [ 55 | 'default' => [ //默认映射和自动加载 56 | 'name' => 'lin', //默认标签名 57 | 'map' => '', //找不到映射时使用的回调,入参为源字符,非回调则返回原值 58 | 'i18n' => 'en', //默认语言类型 59 | 'autoload' => function ($label, $i18n) use ($lin) { 60 | $lang = $lin['lang'] . "/$label.$i18n.php"; //默认自动映射规则 61 | if (file_exists($lang)) { 62 | return include $lang; 63 | } 64 | return []; 65 | }, 66 | ], 67 | ], 68 | /*日志组件*/ 69 | 'log' => [ 70 | 'use' => 'local', //使用的服务器 71 | 'server' => [ 72 | 'local' => [ 73 | 'path' => $lin['data'] . '/log', 74 | 'size' => 100 * 1024 * 1024, //单个日志文件大小最大值,最大不超过2gb 75 | 'frequency' => 720, //使用文件夹对日志汇总的频率,0不汇总,(0,24]按小时,(24,720]按天,(>720)按月 76 | 'format' => function ($type, $content, $time) { 77 | return "[$type]; " . date('Y-m-d H:i:s', $time) . "; $content"; //对日志进行格式化后写入 78 | }, 79 | ], 80 | 'sql' => [ 81 | 'table' => 'logs', 82 | 'fields' => [ //表字段 83 | 'name' => 'name', //日志名,建议varchar类型 84 | 'type' => 'type', //日志类型,建议varchar类型 85 | 'content' => 'content', //内容,text类型,容量根据单条日志内容上限定 86 | 'time' => 'created_time', //创建时间,最少4字节int 87 | ], 88 | ], 89 | 'queue' => [ //使用队列进行异步操作,入参为日志类型,日志内容,日志创建时间 90 | 'format' => function ($type, $content, $time) { 91 | return ['type' => $type, 'content' => $content, 'time' => $time]; //对日志进行格式化后存入队列 92 | }, 93 | 'prefix' => '_linlog_', //队列名前缀 94 | ], 95 | ], 96 | 'default' => [ 97 | 'name' => 'linlog', //默认日志名 98 | ], 99 | 'debug' => true, 100 | ], 101 | 102 | /*请求组件*/ 103 | 'request' => [ 104 | 'type' => [ //自定义请求类型 105 | 'tag' => '__method', //标示自定义类型的键名,值为自定义类型。如表单中name为:__method,value为PUT,则请求类型为PUT 106 | 'substitute' => 'POST', //用于模拟自定义请求的类型,在该请求类型下自定义类型才会生效 107 | ], 108 | 'uploads' => [ 109 | 'path' => $lin['data'] . '/upload', //上传文件存放路径 110 | 'rename' => '', //可使用回调对上传文件重命名,入参为原文件名 111 | 'filter' => function ($fileType, $fileSize) { 112 | return true; //对上传文件进行过滤 113 | }, 114 | ], 115 | ], 116 | 117 | /*访问服务器的客户端组件*/ 118 | 'server' => [ 119 | 'file' => [ 120 | 'debug' => true, 121 | ], 122 | 'local' => [ 123 | 'path' => $lin['data'], //存放路径 124 | 'debug' => true, 125 | ], 126 | //若使用指定服务器(以下'use'项),用'*'代表使用所有, 'a*'代表所有索引前缀为a的服务器 127 | // 'a,b,c'代表使用索引为a,b,c的服务器。 128 | //(皆按数组元素原始顺序,服务器配置从servers配置文件获取) 129 | 'kv' => [ 130 | 'driver' => [ //可使用的不同驱动配置 131 | 'memcached' => [ 132 | 'use' => '*', //使用所有服务器 133 | ], 134 | 'redis' => [ 135 | 'use' => 'kv*', //使用所有kv标识的服务器 136 | ], 137 | 'local' => [ //使用本地文件驱动的配置 138 | 'path' => $lin['data'] . '/kv', //存放路径 139 | ], 140 | ], 141 | 'prefix' => '', //键前缀 142 | 'default' => [ 143 | 'life' => 3600 * 24 * 7, //默认的缓存时间,单位s 144 | ], 145 | 'debug' => true, 146 | ], 147 | 'queue' => [ //队列服务器 148 | 'driver' => [ 149 | 'redis' => [ //使用redis驱动的配置 150 | 'use' => 'queue*', //使用所有queue标识的服务器 151 | ], 152 | 'local' => [ //使用本地文件驱动的配置 153 | 'path' => $lin['data'] . '/queue', //存放路径 154 | ], 155 | ], 156 | 'default' => [ 157 | 'name' => 'lin', //默认的队列名 158 | ], 159 | 'debug' => true, 160 | ], 161 | 'sql' => [ 162 | 'use' => '*', //使用所有服务器 163 | 'debug' => true, 164 | ], 165 | ], 166 | 167 | /**********************/ 168 | 169 | /*****一般组件*****/ 170 | /*异常错误处理组件*/ 171 | 'exception' => [ 172 | 'exception' => [ 173 | 'lang' => 'both', //多语言显示,空或none为关闭,only为仅用于显示,但日志记录仍为原文,both为都用于显示和日志记录 174 | 'default' => [ 175 | 'type' => 'General', //默认的异常类型 176 | ], 177 | 'log' => [ 178 | 'on' => true, //是否日志记录异常 179 | 'name' => 'exception', //日志名 180 | ], 181 | 'show' => true, //是否显示异常 182 | 'callback' => '', //异常发生时回调函数,空则不回调,入参为异常类$Exception 183 | ], 184 | 'error' => [ //错误 185 | 'lang' => 'none', 186 | 'log' => [ 187 | 'on' => true, //是否日志记录错误 188 | 'name' => 'error', //日志名 189 | ], 190 | 'show' => true, //是否显示错误 191 | 'callback' => '', //错误发生时回调函数,空则不回调,入参为$errNo, $errStr, $errFile, $errLine 192 | ], 193 | ], 194 | 195 | /*层组件*/ 196 | 'layer' => [ 197 | 'namespace' => [ 198 | 'layer' => 'app\\layer', //层所处命名空间 199 | 'block' => 'app\\block', //块所处命名空间 200 | ], 201 | 'debug' => true, 202 | ], 203 | 204 | /*对象-关系映射组件*/ 205 | 'orm' => [ 206 | 'model' => [ 207 | 'default' => [ 208 | 'table' => function ($className, $namespace) { 209 | return strtolower($className); //默认表名,可使用任何回调,入参为类名(不含命名空间)和所在命名空间 210 | }, 211 | 'pk' => function ($className, $namespace) { 212 | return rtrim(strtolower($className), 's') . '_id'; //默认主键名。如模型为Users,则pk为user_id 213 | }, 214 | ], 215 | 'relation' => [ 216 | 'namespace' => 'app\\block\\model', //关联模型所处的命名空间 217 | ], 218 | ], 219 | 'page' => [ 220 | 'number' => 20, //分页时一次查询的条数 221 | ], 222 | 'debug' => true, 223 | ], 224 | 225 | /*数据处理组件*/ 226 | 'processor' => [ 227 | 'formatter' => [ //格式化器 228 | 'default' => [ 229 | 'value' => function ($field) {return null;}, //使用回调对must模式下缺少的字段赋于默认值才进行格式化,入参为字段名 230 | 'type' => 'should', //默认格式化模式,可为must, should, may分别代表,必须格式化,存在才格式化,存在且非空格式化(trim后长度大于0) 231 | ], 232 | ], 233 | 'mapper' => [ //映射器 234 | 'default' => [ 235 | 'value' => function ($field) {return null;}, //使用回调对must模式下缺少的字段赋值,入参为字段名 236 | 'type' => 'should', 237 | ], 238 | ], 239 | 'debug' => true, 240 | ], 241 | 242 | /*响应组件*/ 243 | 'response' => [ 244 | 'view' => [ 245 | 'error' => $lin['components'] . '/response/structure/error.html', //错误页面 246 | 'success' => $lin['components'] . '/response/structure/success.html', //成功页面 247 | 'countdown_id' => 'lin-jump-countdown', //跳转倒计时所在的html节点id 248 | 'method' => function ($template, $data) { 249 | $View = new lin\view\View; //嵌入的视图响应方法,入参为视图模板名、视图数据 250 | return $View->withData($data)->show($template); 251 | }, 252 | ], 253 | 'jsonxml' => [ 254 | 'charset' => 'utf8', //编码 255 | 'path' => $lin['jsonxml'], //模板目录 256 | 'cross_origin' => [ 257 | 'on' => false, // 是否允许跨域 258 | 'domain' => '*', //允许的域名列表 259 | ], 260 | ], 261 | 'file' => [ 262 | 'path' => $lin['data'] . '/files', //默认响应文件的存放路径 263 | ], 264 | 'default' => [ 265 | 'error' => [ 266 | 'countdown' => 3, //跳转倒计时(单位:s),0为不跳转 267 | 'info' => 'Error!', //默认错误信息 268 | ], 269 | 'success' => [ 270 | 'countdown' => 3, 271 | 'info' => 'Success!', 272 | ], 273 | 'json' => [ 274 | 'opt' => JSON_UNESCAPED_UNICODE, //json选项设置,见json_encode第二个参数 275 | 'depth' => 512, //编码深度,见json_encode第三个参数 276 | 'template' => null, //默认模板名,为空则不使用 277 | ], 278 | 'xml' => [ 279 | 'header' => '', //xml头 280 | 'template' => null, 281 | ], 282 | ], 283 | ], 284 | 285 | /*路由组件*/ 286 | 'route' => [ 287 | 'ci' => false, //路由是否大小写不敏感 288 | 'suffix' => ['html', 'htm'], //支持的伪静态后缀名,数组索引为优先级顺序 289 | 'path' => $lin['route'], //存放路由规则的文件夹 290 | 'terminal' => [false], //终止符,返回该数组中任一符号则终止执行 291 | 'namespace' => [ //执行类的命名空间前缀,在执行规则包含根'\'空间时不起作用,如'\Class' 292 | 'pre' => 'app\\layer\\middleware', //前置执行类的命名空间 293 | 'main' => 'app\\layer', //主执行行类的命名空间 294 | 'post' => 'app\\layer\\middleware', //后置执行类的命名空间 295 | ], 296 | 'general' => function ($url, $method) { 297 | $Class = 'app\\layer\\Error'; //未匹配到路由时使用的通用规则,入参为当前请求url和method, 298 | (new $Class)->status404(); 299 | }, 300 | 'cache' => [ //缓存相关 301 | 'on' => false, 302 | 'path' => $lin['cache'] . '/route', //路由缓存路径 303 | ], 304 | 'debug' => true, 305 | ], 306 | 307 | /*安全组件*/ 308 | 'security' => [ 309 | 'use' => 'local', 310 | 'server' => [ 311 | 'local' => [ //使用本地存储 312 | 'path' => $lin['data'] . '/security', //存放路径 313 | ], 314 | 'sql' => [ //使用sql服务器 315 | 'table' => 'security', //表名 316 | 'fields' => [ //键值为数据库字段名, 317 | 'id' => 'client_id', //最少char(70),主键 318 | 'type' => 'type', //客户端类型,临时或正式,最少1字节int 319 | 'content' => 'content', //可空text类型,数据增量无上限,有效场景越多越大, 320 | 'time' => 'created_time', //客户端创建时间,最少4字节int 321 | ], 322 | ], 323 | ], 324 | 'gc' => [ //对临时客户端执行垃圾回收 325 | 'probability' => 0.0001, //触发概率 326 | 'max_life' => 1800, //临时客户端的静止生命期(s),同session机制 327 | ], 328 | 'default' => [ 329 | 'cost' => 4, //加密token的消耗等级,越高越安全,见password_hash函数 330 | 'life' => 1200, //默认场景时效,单位s 331 | ], 332 | 'image' => [ //图片专用(即图片验证码) 333 | 'resolution' => [130, 50], //生成的图片分辨率,宽和高 334 | 'length' => 5, //验证码长度,最短1位,最长20位 335 | 'level' => 2, //复杂等级,最高级6,最低级0,等级越高越耗资源 336 | 'seed' => '23456789ABCDEFGHJKLMNPQRSTUWXYZ', //生成验证码的种子 337 | 'background' => [], //背景图片(完整路径名),若有则随机选择 338 | 'ttf' => [ //随机使用的ttf字体库, 339 | $lin['components'] . '/security/structure/captcha/stencil-four.ttf', 340 | ], 341 | ], 342 | 'debug' => true, 343 | ], 344 | 345 | /*session组件*/ 346 | 'session' => [ 347 | 'life' => 1200, //过期时长,单位秒,0则永不过期 348 | 'use' => 'local', //当前使用的服务器 349 | 'server' => [ //可选的服务器列表 350 | 'local' => [ //使用本地存储 351 | 'path' => $lin['data'] . '/session', //存放路径 352 | 'deep' => 0, //子目录深度 353 | ], 354 | 'kv' => [ //使用kv服务器 355 | 'prefix' => '_ssid_', //使用的key前缀 356 | ], 357 | 'sql' => [ //使用sql服务器 358 | 'table' => 'sessions', //表名 359 | 'fields' => [ //键值为数据库字段名, 360 | 'id' => 'session_id', //字段类型根据session_id长度来定,主键,最少char(32) 361 | 'content' => 'content', //可空text类型,数据增量无上限,sessoin内容越多越大 362 | 'time' => 'created_time', //创建日期,最少3字节int 363 | ], 364 | ], 365 | 'custom' => 'SessionHandlerClass', //使用自定义的处理类,需实现SessionHandlerInterface 366 | ], 367 | ], 368 | 369 | /*url组件*/ 370 | 'url' => [ //构建url 371 | 'dynamic' => [ //使用回调生成完整path,入参为输入的当前有效域,输入的路径值,当前入口脚本名 372 | 'path' => function ($domin, $path, $script) { 373 | if ($path == '/') { 374 | return "http://$domin"; 375 | } 376 | $path = trim($path, '/'); //动态url规则 377 | return "http://$domin/$path.html"; 378 | }, 379 | 'query' => function ($params) { 380 | return '?' . http_build_query($params); //使用回调生产查询(GET)参数 381 | }, 382 | ], 383 | 'static' => [ //构建静态资源专用的path,位于public目录下 384 | 'path' => function ($domin, $path, $script) { 385 | $path = trim($path, '/'); 386 | return "http://$domin/resource/$path"; 387 | }, 388 | ], 389 | ], 390 | 391 | /*验证组件*/ 392 | 'validator' => [ 393 | 'default' => [ //默认 394 | 'info' => function ($fields) {return "${fields}字段验证失败";}, //默认字段验证失败后的信息回调,入参为字段名 395 | 'type' => 'may', //默认验证模式。可为must, should, may分别代表,必须验证,存在才验证,存在且不为空验证(trim后长度大于0) 396 | ], 397 | 'debug' => true, 398 | ], 399 | 400 | /*视图组件*/ 401 | 'view' => [ 402 | 'charset' => "utf8", //输出编码 403 | 'path' => $lin['view'], //模板文件路径 404 | 'tag' => [ //模板标签 405 | 'left' => '{', //左界定符,用于包裹模版语句 406 | 'right' => '}', //右界定符 407 | 'begin_static' => 'STATIC', //静态化开始关键字,将其中内容输出为静态内容,而不是php代码 408 | 'end_static' => '/STATIC', //静态化结束关键字 409 | 'escape' => '\\', //转义标签, 410 | 'location' => 'LOCATION', //继承位置所在关键字 411 | 'extends' => 'EXTENDS', //界定符内继承视图关键字, 如{extends parent_view} 412 | 'include' => 'INCLUDE', //引入视图文件关键字,如{include some_view} 413 | ], 414 | 'cache' => [ //缓存相关 415 | 'life' => -1, //有效期,单位s,0则不过期,小于0立即过期 416 | 'path' => $lin['cache'] . '/view', //缓存路径 417 | ], 418 | 'security' => 'htmlspecialchars', //对分配变量中的每一个标量做安全处理的回调,入参为每一个标量值 419 | 'debug' => true, 420 | ], 421 | 422 | ]; 423 | -------------------------------------------------------------------------------- /app/config/lin.production.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'debug' => false, 10 | ], 11 | /*调试组件*/ 12 | 'debug' => [ 13 | 'panel' => [ 14 | 'display' => 'none', 15 | ], 16 | ], 17 | /*事件组件*/ 18 | 'event' => [ 19 | 'debug' => false, 20 | ], 21 | /*日志组件*/ 22 | 'log' => [ 23 | 'debug' => false, 24 | ], 25 | 26 | /*访问服务器的客户端组件*/ 27 | 'server' => [ 28 | 'file' => [ 29 | 'debug' => false, 30 | ], 31 | 'local' => [ 32 | 'debug' => false, 33 | ], 34 | 'kv' => [ 35 | 'debug' => false, 36 | ], 37 | 'queue' => [ 38 | 'debug' => false, 39 | ], 40 | 'sql' => [ 41 | 'debug' => false, 42 | ], 43 | ], 44 | 45 | /**********************/ 46 | 47 | /*****一般组件*****/ 48 | /*异常错误处理组件*/ 49 | 'exception' => [ 50 | 'exception' => [ 51 | 'show' => false, 52 | ], 53 | 'error' => [ 54 | 'show' => false, 55 | ], 56 | ], 57 | 58 | /*层组件*/ 59 | 'layer' => [ 60 | 'debug' => false, 61 | ], 62 | 63 | /*对象-关系映射组件*/ 64 | 'orm' => [ 65 | 'debug' => false, 66 | ], 67 | 68 | /*数据处理组件*/ 69 | 'processor' => [ 70 | 'debug' => false, 71 | ], 72 | 73 | /*路由组件*/ 74 | 'route' => [ 75 | 'cache' => [ 76 | 'on' => true, 77 | ], 78 | 'debug' => false, 79 | ], 80 | 81 | /*安全组件*/ 82 | 'security' => [ 83 | 'debug' => false, 84 | ], 85 | 86 | /*验证组件*/ 87 | 'validator' => [ 88 | 'debug' => false, 89 | ], 90 | 91 | /*视图组件*/ 92 | 'view' => [ 93 | 'cache' => [ 94 | 'life' => 0, 95 | ], 96 | 'debug' => false, 97 | ], 98 | 99 | ]; 100 | -------------------------------------------------------------------------------- /app/layer/Error.php: -------------------------------------------------------------------------------- 1 | withStatus(404)->error('不可访问的地址', 0); 15 | } 16 | public function status301() 17 | { 18 | $Response = new Response; 19 | $Response->withStatus(301)->redirect('/'); 20 | } 21 | public function status302() 22 | { 23 | $Response = new Response; 24 | $Response->withStatus(302)->redirect('/'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/layer/Index.php: -------------------------------------------------------------------------------- 1 | use('http'); //使用http对象,Response和Request 13 | } 14 | 15 | public function index() 16 | { 17 | $this->Response->view('welcome'); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/lib/helper.php: -------------------------------------------------------------------------------- 1 | record($msg, $type); 24 | } 25 | //显示视图 26 | function view(string $view, array $data = []) 27 | { 28 | $View = new View; 29 | return $View->withData($data)->show($view); 30 | } 31 | //设置调试标识,用于收集两个相同标识之间代码的运行信息 32 | function flag(string $flag) 33 | { 34 | Debug::flag($flag); 35 | } 36 | //打印 37 | function dump($var, ...$vars) 38 | { 39 | if (empty($vars)) { 40 | return Debug::dump($var); 41 | } 42 | $var = [$var]; 43 | return call_user_func_array(['\lin\basement\debug\Debug', 'dump'], array_merge($var, $vars)); 44 | 45 | } 46 | //生成动态url 47 | function url(string $url, array $params = []) 48 | { 49 | return URL::get($url, $params); 50 | } 51 | //生成静态资源的url 52 | function resource(string $url) 53 | { 54 | return URL::getStatic($url); 55 | } 56 | 57 | //导入自定义文件 58 | function import(string $filename) 59 | { 60 | $filename = __DIR__ . '/' . preg_replace('/\./', '/', $filename) . '.php'; 61 | if (file_exists($filename)) { 62 | return include $filename; 63 | } 64 | Linker::Exception()::throw ('文件不存在', 1, 'Import', $filename); 65 | } 66 | 67 | /** 68 | * 快速读取配置 69 | * @param string|array $strOrArr 字符串的时读取配置,数组时设置配置。支持点语法 70 | * @param string $confName 配置文件名 71 | * @return mixed 72 | */ 73 | function conf($strOrArr, string $configName = 'lin') 74 | { 75 | return Config::$configName($strOrArr); 76 | } 77 | 78 | /** 79 | * 获得请求参数或设置请求参数 80 | * @param string|array $strOrArr 字符串的时读取请求,数组时设置请求。支持链式调用, 81 | * 如get.id为获取$_GET['id'],['get.id'=>anything]为$_GET['id']=anything 82 | * @return mixed 83 | */ 84 | function req($strOrArr = '*') 85 | { 86 | return (new Request)->params($strOrArr); 87 | } 88 | -------------------------------------------------------------------------------- /app/register.php: -------------------------------------------------------------------------------- 1 | '\\lin\\basement\\config\\Config', 9 | 'Request' => '\\lin\\basement\\request\\Request', 10 | 'Event' => '\\lin\\basement\\event\\Event', 11 | ], true); 12 | 13 | //插件,生命期内可更改 14 | Linker::register([ 15 | 'ServerSQL' => '\\lin\\basement\\server\\sql\\SQLPDO', 16 | 'ServerKV' => '\\lin\\basement\\server\\kv\\KVLocal', 17 | 'ServerLocal' => '\\lin\\basement\\server\\local\\Local', 18 | 'ServerQueue' => '\\lin\\basement\\server\\queue\\QueueLocal', 19 | 'Exception' => '\\lin\\basement\\exception\\GeneralException', 20 | 'Log' => '\\lin\\basement\\log\\Log', 21 | 'Debug' => '\\lin\\basement\\debug\\Debug', 22 | 'Lang' => '\\lin\\basement\\lang\\Lang', 23 | ]); 24 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lin/lin", 3 | "description": "高性能、全组件化、极简主义php7.2框架", 4 | "type": "project", 5 | "keywords": [ 6 | "framework", 7 | "lin", 8 | "orm", 9 | "server" 10 | ], 11 | "homepage": "https://www.lin-php.com", 12 | "license": "Apache-2.0", 13 | "authors": [ 14 | { 15 | "name": "linlanye", 16 | "email": "linlanye@sina.cn" 17 | } 18 | ], 19 | "require": { 20 | "php": ">=7.2.0", 21 | "basement/basement": "1.0.*@stable", 22 | "lin/components": "^1.0" 23 | }, 24 | "support": { 25 | "email": "linlanye@sina.cn", 26 | "issues": "https://www.lin-php.com", 27 | "docs": "https://docs.lin-php.com" 28 | }, 29 | "autoload": { 30 | "psr-4": { 31 | "app\\": "app" 32 | } 33 | }, 34 | "config": { 35 | "preferred-install": "dist", 36 | "optimize-autoloader": true 37 | } 38 | } -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | # Handle Authorization Header 18 | RewriteCond %{HTTP:Authorization} . 19 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 20 | 21 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------