关于thinkphp:小编推荐ThinkPHP3x基础管理系统

CMS管理系统 介绍 这是一套应用ThinkPHP3.X开发的根底零碎,蕴含后盾用户权限管制,后盾用户分组治理、网站系统配置性能,可用他来衍生各种产品。网址:http://139.155.45.209:1024/admin 账号:admin 明码:admin 装置办法 1 创立MYSQL数据库,导入 cms.sql2 把根目录的config.php.bak文件名改成config.php3 依据你的数据库,配置config.php “db_host db_name db_user db_pwd db_port”4 后盾入口 http://domain/admin5 后盾帐号密码 admin admin6 后盾菜单设置办法请参考已有的那些菜单 目录构造 |-admin 后盾入口跳转门路|-Core 系统核心| ├Common 我的项目公共函数文件目录| ├Conf 我的项目配置目录| | ├Admin/config.php 我的项目后盾配置文件| | └Home/config.php 我的项目前台配置文件| || ├Lang 我的项目多语言包目录| | ├en-us 英文言包目录| | └zh-cn 中文言包目录| || ├Lib 我的项目类库目录| | ├Action 控制器| | └Model 模型| || ├config.php 我的项目配置文件| ├define.php 我的项目门路常量配置文件| └tags.php 我的项目扩大行为调用配置文件||-Public 公共动态文件目录| ├Admin 后盾公共动态目录| ├Home 前台公共动态目录| ├js 公共JS目录| └tips 信息提醒跳转页面||-Temp 零碎缓存目录|-Template 我的项目模板目录| ├Admin/default 后盾模板目录| └Home/default 前台模板目录||-config.php 网站配置文件└-index.php 零碎入口文件 ...

April 28, 2023 · 1 min · jiezi

关于thinkphp:20220204thinkphp源码详细阅读二

thinkphp源码具体浏览(二)申请流程实例化 http ,注入 app 和设置 routePath 执行 run 办法,首先初始化 initialize,初始化操作是在容器 app 中执行 初始化执行的是,记录初始化标记、开始工夫、开始内存、加载环境变量、配置文件后缀、设置调试模式、加载配置文件、加载语言配置、加载语言包、触发 AppInit 事件、设置时区、注册谬误和异样解决、注册零碎服务、启动零碎服务其中加载配置文件执行的是,引入自定义函数、零碎帮忙函数、配置文件、注册事件、注册服务初始化这个过程代码还是绝对较多的,不过浏览起来也是绝对简略的,有点急躁即可创立 request 对象,而后绑定到容器中,而后执行运行程序加载全局中间件,并给中间件放入执行队列触发 HttpRun 事件,而后调度管道 下一期管道剖析 pipeline

February 4, 2022 · 1 min · jiezi

关于thinkphp:20220202thinkphp源码详细阅读一

thinkphp源码具体浏览(一)申请流程从入口 index.php 开始实例化 App ,咱们看一下实例化所做的工作 设置 thinkPath、 rootPath 、 appPath 、 runtimePath加载服务文件 provider.php ,具体如何实现,咱们能够看绑定到容器实现局部代码 provider.php 中返回的数组,代码的执行就是先循环,而后调用 bind 传入标识和类名称,类名称不是闭包,也不是类对象,所以进入 else而后依据别名获取实在的类名称 绑定闭包和对象也须要理解,如果是闭包则间接绑定,如果是对象,则获取实在类名,而后绑定到实例上,目前暂未可知为什么闭包不应用实在类名? 设置以后容器实例最初把标识 app 和 think\Container 绑定到容器实例上实例化实现当前,获取 http 属性,这个时候发现 App 和它的父类 Container 中并没有这个属性,这个时候就会执行魔术办法 __get 判断容器中是否有 http ,有的话就创立实例,没有就抛出异样 下一期创立类实例 make 剖析

February 3, 2022 · 1 min · jiezi

关于thinkphp:20220202thinkphp源码无差别阅读三十五

thinkphp源码无差别浏览(三十五)ORM浏览model/relation/OneToOne.php属性:joinType、bindAttr、relation设置join类型:joinType预载于关联查问:eagerly预载于关联查问:eagerlySet预载于关联查问:eagerlyOne预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult保留:save绑定属性:bind获取绑定属性:getBindAttr预查问拼装:match绑定属性:bindAttr预载于关联查问:eagerlyWherepaginator/driver/Bootstarp.php获取上一页按钮:getPreviousButton下一页按钮:getNextButton页码按钮:getLinks渲染:render生成一个可点击按钮:getAvailablePageWrapper生成一个不可点击按钮:getDisabledTextWrapper生成一个激活的按钮:getActivePageWrapper生成省略号按钮:getDots批量生产url按钮:getUrlLinks生成一般按钮:getPageLinkWrapper打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

February 2, 2022 · 1 min · jiezi

关于thinkphp:20220131thinkphp源码无差别阅读三十四

thinkphp源码无差别浏览(三十四)ORM浏览model/relation/MorphOne.php属性:morphKey、morphType、type、bindAttr构造方法:__construct提早获取关联数据:getRelation依据关联条件查问以后模型:has依据关联条件查问以后模型:hasWhere预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult预载于关联查问:eagerlyMorphToOne保留:save创立关联对象实例:make根底查问:baseQuery绑定属性:bind获取绑定属性:getBindAttr绑定属性:bindAttrmodel/relation/MorphTo.php属性:morphKey、morphType、alias、relation构造方法:__construct获取以后关联模型类实例:getModel提早获取关联数据:getRelation依据关联条件查问以后模型:has依据关联条件查问以后模型:hasWhere解析模型残缺命名空间:parseModel设置多态别名:setAlias移除关联查问参数:removeOption预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult关联统计:relationCount预载于关联查问:eagerlyMorphToOne增加关联数据:associate登记关联数据:dissociatemodel/relation/MorphToMany.php属性:morphType、morphClass、inverse构造方法:__construct预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult关联统计:relationCount获取关联统计子查问:getRelationCountQuery关联查问:belongsToManyQuery预载于关联查问:eagerlyManyToMany附加关联的一个两头表数据:attach判断是否存在关联数据:attached解除关联的一个两头表数据:detach数据同步:sync根底查问:baseQuery打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

February 1, 2022 · 1 min · jiezi

关于thinkphp:20220131thinkphp源码无差别阅读三十三

thinkphp源码无差别浏览(三十三)ORM浏览model/concern/BelongsToMany.php属性:middle、pivotName、pivot、pivotDataName构造方法:__construct设置两头表模型:pivot设置两头表数据名称:name实例化两头模型;newPivot合成两头表模型:hydratePivot提早获取关联数据:getRelation重载select:select重载paginate:paginate重载find:find依据关联条件查问以后模型:has依据关联条件查问以后模型:hasWhere设置两头表查问条件:wherePivot预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult关联统计:relationCount获取关联统计子查问:getRelationCountQuery关联模型预查问:eagerlyManyToMany关联查问:belongsToManyQuery保留:save批量保留:saveAll附加关联的一个两头表数据:attach判断是否存在关联数据:attached解除关联的一个两头表数据:detach数据同步:sync根底查问:baseQuerymodel/concern/HasMany.php构造方法:__construct提早获取关联数据:getRelation预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult关联统计:relationCount关联统计子查问:getRelationCountQuery关联预查问:eagerlyOneToMany保留:save创立关联对象实例:make批量保留:saveAll依据关联条件查问以后模型:has依据关联条件查问以后模型:hasWhere根底查问:baseQuery打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 31, 2022 · 1 min · jiezi

关于thinkphp:20220130thinkphp源码无差别阅读三十二

thinkphp源码无差别浏览(三十二)ORM浏览model/concorn/SoftDelete.php属性:withTrashed判断以后实例是否被软删除:trashed查问软删除数据:withTrashed是否蕴含软删除数据:withTrashedData只查问软删除数据:onlyTrashed获取软删除的查问条件:getWithTrashedExp删除:delete删除:destroy复原:restore获取软删除字段:getDeleteTimeField排除软删除数据:withNoTrashedmodel/concern/TimeStamp.php属性:autoWriteTimeStamp、createTime、updateTime、dateFormat是否主动写入工夫戳:isAutoWriteTimestamp检测时间字段类型:checkTimeFieldType设置工夫字段名称:setTimeField获取主动写入的工夫字段:getAutoWriteTimestamp设置工夫字段格式化:setDataFormat获取主动写入工夫字段:getDateFormat主动写入工夫戳:autoWriteTimestamp获取主动类型的工夫字段值:getTimeTypeValue工夫日期格式化:formatDateTime获取工夫字段值:getTimestampValuemodel/concern/Virtual.php获取查问对象:db获取字段类型信息:getFieldType保留数据:save删除以后记录:deletemodel/concern/BelongsTo.php构造方法:__construct提早获取关联数据:getRelation创立关联统计子查问:getRelationCountQuery关联统计:relationCount依据关联条件查问关联模型:has依据关联条件查问关联模型:hasWhere预载于关联查问:eagerlySet预载于关联查问:eagerlyOne增加关联数据:associate登记关联数据:dissociate执行根底查问:baseQuery打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 30, 2022 · 1 min · jiezi

关于thinkphp:20220129thinkphp源码无差别阅读三十一

thinkphp源码无差别浏览(三十一)ORM浏览model/concern/ModelEvent.php属性:event、、withEvent设置事件:setEvent设置事件是否须要响应:withEvent触发事件:triggermodel/concern/OptimLock.php未知:getOptimLockField数据查看:checkData记录乐观锁:recordLockVersion更新乐观锁:updateLockVersion获取更新条件:getWhere未知:checkResultmodel/concern/RelationShip.php属性:parent、relation、together、relationWrite设置父关联对象:setParent获取父关联对象:getParent获取以后模型的关联模型数据:getRelation设置关联数据:setRelation查问关联数据:relationQuery关联数据写入:together依据关联条件查问以后模型:has依据关联条件查问以后模型:hasWhere+预载于关联查问:eagerly预载于关联查问:eagerlyResultSet预载于关联查问:eagerlyResult绑定属性:bindAttr关联统计:relationCount关联定义:hasOne关联定义:belongsTo关联定义:hasMany近程关联定义:hasManyThrough近程关联定义:hasOneThrough关联定义:belongsToMany关联定义:morphOne关联定义:morphMany关联定义:morphTo关联定义:morphToMany关联定义:morphByMany解析模型:parseModel获取外键:getForeignKey查看是否是关联属性:isRelationAttr获取关联数据:getRelationData关联数据主动写入查看:checkAutoRelationWrite主动关联数据更新:autoRelationUpdate主动关联数据写入:autoRelationInsert主动关联数据删除:autoRelationDelete移除关联属性:autoRelationDelete打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 29, 2022 · 1 min · jiezi

关于thinkphp:20220127thinkphp源码无差别阅读三十

thinkphp源码无差别浏览(三十)ORM浏览model/concern/Attribute.php属性:pk、schema、field、type、disuse、readonly、data、origin、json、jsonType、jsonAssoc、strict、get、withAttr获取主键:getPk判断是否主键:isPk获取主键:getKey设置容许写入字段:allowField设置只读字段:readOnly获取理论字段名:getRealFieldName设置数据对象值:data批量追加数据对象值:appendData获取原始数据:getOrigin获取以后对象数据:getData获取变动的数据:getChangedData设置数据对象值:set通过修改器批量批改对象值:setAttrs设置对象值:setAttr数据写入,类型转换:writeTransform获取器:getAttr获取器:getValue获取json字段值:getJsonValue获取关联属性值:getRelationValue数据读取,类型转换:readTransform设置获取器:withAttributemodel/concern/Conversion.php属性:visible、hidden、append、scene、mapping、resultSetType、convertNameToCamel是否主动驼峰:convertNameToCamel设置须要附加的输入属性:append设置输入层场景:scene设置附加关联对象属性:appendRelationAttr设置暗藏属性:hidden设置输入属性:visible设置属性的映射输入:mapping模型对象转数组:toArray追加值到数组:appendAttrToArray获取绑定属性值:getBindAttrValue模型转json:toJson转json:__toString转数组:JsonSerialize转换为数据集对象:toCollection打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 28, 2022 · 1 min · jiezi

关于thinkphp:20220125thinkphp源码无差别阅读二十九

thinkphp源码无差别浏览(二十九)ORM浏览db/Where.plhp属性:where、enclose构造方法:__construct设置是否增加括号:enclose解析query对象为数组:parse剖析查问表达式:parseItem修改器:__set获取器:__get检测数组对象的值:__isset销毁:__unset数组式拜访:offsetSet、offsetExists、offsetUnset、offsetGetfacade/Db.php获取以后facade对应的类名:getFacadeClassmodel/Collection.php提早预载于关联查问:load删除:delete更新:update设置暗藏:hidden设置显示:visible设置须要追加的属性:append设置模型输入场景:scene设置父模型:setParent设置获取器:withAttr关联属性到以后模型:bindAttr按指定键整顿数据:dictionary差集:diff交加:intersectmodel/Pivot.php属性:parent、autoWriteTimestamp构造方法:__constructmodel/Relation.php属性:parent、model、query、foreignKey、localKey、baseQuery、selfRelation、withLimit、withField、withoutField、default获取关联模型:getParent获取query:getQuery获取外键:getForeignKey获取主键:getLocalKey获取以后模型:getModel是否自关联:isSelfRelation封装关联数据集:resultSetBuild获取查问字段:getQueryFields获取查问字段:getRelationQueryFields获取查问条件:getQueryWhere限度关联数量:withLimit限度关联字段:withField排除关联字段:withoutField设置关联数据不存在时的默认:withDefault获取关联数据默认值:getDefaultModel判断闭包的参数类型:getClosureType执行根底查问:baseQuery动静调用:__call打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 25, 2022 · 1 min · jiezi

关于thinkphp:20220124thinkphp源码无差别阅读二十八

thinkphp源码无差别浏览(二十八)ORM浏览db/Query.php表达式形式指定排序:orderRaw表达式形式指定查问字段:fieldRaw指定field排序:orderField随机排序:orderRand应用表达式设置数据:exp表达式形式指定以后数据表:tableRaw获取执行的sql,而不进行查问:fetchSql批量执行:batchSqlusing反对:using存储过程调用:procedure指定group:group指定having:having指定district:district强制索引:force查问正文:comment设置是否replace:replace设置以后分区:partition设置duplicate:duplicate设置查问的额定参数:extra创立子查问sql:buildSql获取以后数据库的主键:getPk指定数据表自增主键:autoInc获取数据表的自增主键:getAutoInc自增字段值:inc自减字段值:dec获取以后查问标识:getQueryGuid获取PDOStatement:getPDOStatement应用游标查问:cursor分批解决:chunkdb/Raw.php属性:value、bind构造方法:__construct获取表达式:getValue获取参数绑定:getBind字符串化:toString打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 24, 2022 · 1 min · jiezi

关于thinkphp:20220123thinkphp源码无差别阅读二十七

thinkphp源码无差别浏览(二十七)ORM浏览db/PDOConnection.php常量:PARAM_FLOAT属性:config、PDOStatement、querySt、transTimes、reConnectTimes、fetchType、attrCase、info、queryStartTime、params、bindType、breakMatchStr、bind获取query类:getQueryClass获取builder类:getBuilderClass解析pdo链接的dsn:parseDsn获取数据表的字段信息:getFields获取表信息:getTable对字段进行大小写转换:fieldCache获取字段类型:getFieldType获取字段绑定类型:getFieldBindType获取表信息缓存key:getSchemaCacheKey获取表信息:getSchemaInfo获取表信息:getTableInfo获取字段信息:getTableFieldInfo获取主键;getPk获取自增主键:getAutoInc获取字段信息:getTableFields获取字段类型:getFieldsType获取数据表绑定信息:getFieldsBind连贯数据库:connect试图查问:view创立pdo实例:createPdo开释查问后果:free获取pdo:getPdo执行查问,应用生成器返回后果:getCursor执行查问,返回数据集:query执行语句:execute执行查问,返回数据集:pdoQuery执行查问,返回PDOStatement:pdo获取PDOStatement:getPDOStatement执行语句:pdoExecute执行查问:queryPDOStatement查问单条语句:find应用游标查问记录:cursor查问记录:select插入:insert插入多条:insertAll通过select插入:selectInsert更新:update删除:delete查问某个字段的值:value聚合查问:aggregate查问一列:column依据参数绑定组装最初的sql:getRealSql参数绑定:bindValue存储过程的参数绑定:bindParam获取数据集数组:getResult获取存储过程数据集:procedure执行数据库事务:transaction启动事务:startTrans提交事务:commit事务回滚:rollback是否反对事务嵌套:supportSavepoint生成保留点的sql:parseSavePoint生成回盾到保留点的sql:parseSavePointRollback批处理执行sql:batchQuery敞开数据库:close是否断线:isBreak获取最近一次的查问sql:getLastSql获取最近的插入ID:getLastInsID获取最近的插入ID:autoInsIDType获取最近的错误信息:getError初始化数据库连贯:initConnect连贯分布式服务器:multiConnect执行数据库xa事务:transactionXa启动sa事务:startTransXa预编译xa:prepareXa提交xa:commitXa回滚xa:rollbackXa打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 23, 2022 · 1 min · jiezi

关于thinkphp:20220122thinkphp源码无差别阅读二十六

thinkphp源码无差别浏览(二十六)ORM浏览db/Fetch.php属性:query、connection、builder构造方法:__construct聚合查问:aggregate获取某个字段的值:value获取某列的值:column插入:insert获取插入的ID:insertGetId保留数据:save插入多条:insertAll通过select插入:selectInsert更新:update删除记录:delete查问记录:select查问一条:find查问多条,不存在就抛出异样:selectOrFail查问一条,不存在就抛出异样:findOrFail获取理论的sql:fetchcount查问:countsum查问:summin查问:minmax查问:maxavg查问:avg动静查问:__calldb/Mongo.php属性:connection执行指令,返回数据集:command执行指令:cmd指定distinct查问:getDistinct获取数据集:listCollectionscount查问:count聚合查问:aggregate多聚合查问:multiAggregate字段值增长:inc字段值缩小:dec指定以后的collection:tabletable别名:collection设置typeMap:typeMap未知:awaitData未知:batchSize未知:exhaust设置modifiers:modifiers设置noCursorTimeout:noCursorTimeout设置oplogReplay:oplogReplay设置partial:partial设置maxTimeMS:maxTimeMS未知:collation设置是否replace:replace设置返回字段:field指定排除字段:withoutField设置skip:skip设置slaveOk:slaveOk指定查问数量:limit排序:order设置tailable:tailable设置writeConcern:writeConcern获取主键:getPk获取getCursor:getCursor获取查问标识:getQueryGuid分页:paginate分批解决数据:chunk剖析表达式:parseOptions获取字段类型信息:getFieldsType打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 22, 2022 · 1 min · jiezi

关于thinkphp:20220121thinkphp源码无差别阅读二十五

thinkphp源码无差别浏览(二十五)ORM浏览db/CacheItem.php属性:key、value、expire、tag、isHit构造方法:__construct为此缓存项设置键:setKey获取键:getKey获取有效期:getExpire获取tag:getTag获取缓存值:get是否命中:isHit设置值:set设置tag:tag设置有效期:expire设置精确的有效期:expireAt设置有效期:expireAfterdb/Connection.php属性:queryStr、numRows、transTimes、error、links、linkID、linkRead、linkWrite、info、queryStartTime、builder、db、readMaster、config、cache构造方法:__construct获取builder:getBuilder创立查问对象:newQuery指定表名称:table指定表名称:name设置db对象:setDb设置缓存对象:setCache获取缓存对象:getCache获取配置:getConfigSQL监控:trigger缓存数据:cacheData获取缓存key:getCacheKey剖析缓存:parseCache获取返回或影响记录数:getNumRows析构办法:__destructdb/ConnectionInterface.php获取Query名称:getQueryClass指定表名称:table指定表名称:name连贯数据库:connect设置db:setDb设置缓存:setCache获取配置:getConfig敞开数据库:close查找单条记录:find查找记录:select插入:insert插入多条:insertAll更新:update删除:delete获取指定值:value获取指定列的值:column执行数据库事务:transaction启动事务:startTrans提交事务:commit事务回滚:rollback获取最近执行的sql:getLastSql打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 21, 2022 · 1 min · jiezi

关于thinkphp:20220119thinkphp源码无差别阅读二十四

thinkphp源码无差别浏览(二十四)ORM浏览db/Builder.php属性:connection、exp、parser、selectSql、insertSql、updateSql、deleteSql构造方法:__construct获取连贯对象:getConnection注册查问表达式解析:bindParser数据分析:parseData数据绑定解决:parseDataBind字段名剖析:parseKey查问额定参数剖析:parseExtrafield剖析:parseFieldtable剖析:parseTablewhere剖析:parseWhere生成查问条件:buildWhere不同字段应用雷同查问条件:parseWhereLogic不同字段应用雷同查问条件:parseFieldsAnd不同字段应用雷同查问条件:parseFieldsOr闭包查问:parseClosureWhere符合条件查问:parseMultiWhereFieldwhere子单元剖析:parseWhereItem含糊查问:parseLike表达式查问:parseExp列查问:parseColumnnull查问:parseNull范畴查问:parseBetweenexists查问:parseExists工夫比拟查问:parseTime大小比拟查问:parseCompare工夫范畴查问:parseBetweenTimein查问:parseIn闭包查问:parseClosure日期工夫条件解析:parseDateTimelimit剖析:parseLimitjoin剖析:parseJoinorder剖析:parseOrder剖析Raw对象:parseRaw随机排序:parseRandorderField剖析:parseOrderFieldgroup剖析:parseGrouphaving剖析:parseHavingcomment剖析:parseCommentdistrict剖析:parseDistrictunion剖析:parseUnionindex剖析:parseForce设置锁机制:parseLock生成select语句:select生成insert:inseret生成insertall:insertAll生成select insert:selectInsert生成update:update生成delete:delete打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 19, 2022 · 1 min · jiezi

关于thinkphp:2022118thinkphp源码无差别阅读二十三

thinkphp源码无差别浏览(二十三)ORM浏览Paginator.php属性:simple、items、currentPage、lastPage、total、listRows、hasMore、options、currentPageResolver、currentPathResolver、maker构造方法:__construct生成分页:make获取maker:maker设置以后页码:setCurrentPage获取页码对应的链接:url获取以后页面:getCurrentPage设置以后页码闭包:currentPageResolver获取path:getCurrentPath获取门路闭包:currentPathResolver获取总条数:total获取每页数量:listRows获取以后页码:currentPage获取最初一页页码:lastPage判断是否足够分页:hasPages创立一组分页:getUrlRange设置锚点:fragment增加url数据:appends结构锚点字符串:buildFragment渲染分页html:render获取数据:items获取数据集:getCollection判断是否为空:isEmpty遍历:each数组式拜访和递归:获取总条数:count获取html字符串:__toString转换为数组:toArray转换为数组:jsonSerialize动静调用:__calldb/BaseQuery.php属性:connection、name、pk、autoinc、prefix、options构造方法:__construct动静调用:__call创立一个新的查问对相干:newQuery获取数据库连贯:getConnection指定以后数据库表名:name获取以后数据库表名:getName获取数据库配置参数:getConfig获取表名称:getTable设置字段类型信息:setFieldType获取最近一次的sql查问语句:getLastSql获取返回或者影响的记录条数:getNumRows获取最近插入的id:getLastID获取某个字段的值:value获取某列的值:columnunion:unionunionAll:unionAll指定查问字段:field排除查问字段:withoutField指定其它表的查问字段:tableField设置数据:data去除查问参数:removeOption指定查问数量:limit指定分页:page指定数据库表:table指定排序:order分页查问:paginate分页查问:paginateX查问更多:more查问缓存:cache指定查问lock:lock指定数据库表别名:alias设置主服务器读取数据:master设置严格查看字段:strict设置自增序列值:sequence设置json字段:json指定数据表主键:pk设置查问参数:options获取查问参数:getOptions设置查问参数:setOption设置表别名:via保留记录:save插入记录:insert插入记录并获取自增ID:insertGetID批量插入:insertAll通过select形式插入记录:selectInsert更新记录:update删除记录:delete查问记录:select查找单条记录:find剖析查问参数:parseOptions剖析更新条件:parseUpdateData把主键转为查问条件:parsePkWhere获取模型更新条件:getModelUpdateCondition打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 18, 2022 · 1 min · jiezi

关于thinkphp:2022117thinkphp源码无差别阅读二十二

thinkphp源码无差别浏览(二十二)ORM浏览DbManager.php属性:instance、config、event、listen、dbLog、queryTimes、cache、log构造方法:__construct注入模型对象:modelMaker监听sql:triggerSQL初始化配置参数:setConfig设置缓存对象:setCache设置日志对象:setLog记录sql日志:log获取查问日志:getDbLog获取配置参数:getConfig创立或者切换数据库连贯查问:connect创立数据库连贯实例:instance获取连贯配置:getConnectionConfig创立连贯:createConnection应用表达式设置数据:raw更新查问次数:updateQueryTimes重置查问次数:clearQueryTimes获取查问次数:getQueryTimes监听sql执行:listen获取监听sql执行:getListen注册事件:event触发事件:trigger动静调用:__callModel.php属性:exists、force、replace、suffix、updateWhere、connection、name、key、table、initialized、defaultSoftDelete、globalScope、lazySave、db、invoker、maker、macro设置服务注入:maker设置办法注入:macro设置db:setDb设置容器对象的依赖注入办法:setInvoker调用反射执行模型办法:invoke构造方法:__construct获取模型名称:getName创立新的模型实例:newInstance设置更新条件:setUpdateWhere设置数据库连贯:setConnection获取连贯:getConnection设置后缀:setSuffix获取后缀:getSuffix获取db:db初始化模型:initialize初始化解决:init未知:checkData未知:checkResult强制更新:force判断force:isForce应用replace:replace刷新模型数据:refresh设置数据是否存在:exists判断数据是否存在:isExists判断模型是否为空:isEmpty提早保留以后数据:lazySave保留以后数据对象:save检查数据是否容许写入:checkAllowFields保留写入数据:saveData新增写入数据:insertData获取以后更新条件:updateWhere保留多个数据到以后数据对象:saveAll删除以后记录:delete写入数据:create更新:update删除:destroy唤醒:__wakeup修改器:__set获取器:__get检测是否有:__isset销毁数据对象的值:__unset数组式拜访设置不实用全局查问范畴:withGlobalScope切换后缀进行查问:suffix切换数据库连贯进行查问:connect动静调用:__call、__callStatic析构办法:__destruct打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 17, 2022 · 1 min · jiezi

关于thinkphp:2022116thinkphp源码无差别阅读二十一

thinkphp源码无差别浏览(二十一)Helper浏览contract/Arrayable.php转换为数组:toArraycontract/Jsonable.php转换为数组:toJsonhelper/Arr.php判断是否能够数组式拜访:accessible增加元素:add未知:collapse未知:crossJoin宰割数组,一个是键名,一个是键值:divide未知:dot排除指定key的数组:except判断是否存在ken:exists返回第一个元素:first返回最初一个元素:last未知:flatten未知:forget未知:get未知:has判断是否关联数组:isAssoc返回指定的key:only未知:pluck未知:explodePluckParameters向数组结尾插入值:prepend移除值:pull随机:random未知:set打乱:shuffle排序:sort递归排序:sortRecursive数组转为query字符串:query过滤筛选:where强制转数组:wraphelper/Str.php属性:snakeCache、camelCache、studlyCache查看是否蕴含字符串:contains,PHP8的str_contains查看字符串以某些字符串结尾:endsWith,PHP8的str_ends_with查看字符串以某些字符串开始:startsWith,PHP8的str_starts_with获取指定长度的字符串:random字符串转小写:lower字符串转大写:upper获取字符串长度:length截取字符串:substr转下划线:snake转驼峰:camel转驼峰(首字母大写):studly转为首字母大写的题目格局:title打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 16, 2022 · 1 min · jiezi

关于thinkphp:2022115thinkphp源码无差别阅读二十

thinkphp源码无差别浏览(二十)Helper浏览helper.php抛出异样:throw_if抛出异样:throw_unless调用闭包:tap默认值:value数据集:collect未知:data_fill未知:data_get未知:data_set获取trait援用的trait:trait_uses_recursive获取类名(不蕴含命名空间):class_basename获取类中用到的所有trait:class_uses_recursiveCollection.php属性:items构造方法:__construct创立数据集:make是否为空:isEmpty转化为数组:toArray获取数据:all合并:merge按指定键整顿数据:dictionary比拟数组,返回差集:diff比拟数组,返回交加:intersect替换数组中的键和值:flip返回数组中的键名:keys返回数组中的值:values删除数组中的最初一个:pop通过应用用户自定义函数,以字符串返回数组:reduce以相同的程序返回数组:reverse删除数组中首个:shift想数组结尾插入:push把一个数组分隔成新的数组快:chunk在数组结尾插入一个元素:unshift给每个元素执行回调:each用回调函数解决数组中的元素:map用回调函数过滤数组中的元素:filter依据字段条件过滤数组中的元素:wherelike过滤:whereLikenotlike过滤:whereNotLikein过滤:whereInnotin过滤:whereNotInbetween过滤:whereBetweennotbetween:whereNotBetween返回数据中指定的列:column排序:sort指定字段进行排序:order打乱数组:shuffle获取第一个单元数据:first获取最初一个单元数据:last截取数组:slice转换为json字符串:toJson转换为数组:convertToArray打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 15, 2022 · 1 min · jiezi

关于thinkphp:2022114thinkphp源码无差别阅读十九

thinkphp源码无差别浏览(十九)framework浏览think/validate/ValidateRule.php属性:title、rule、message增加验证因子:addItem获取验证规定:getRule获取验证字段名称:getTitle获取验证提示信息:getMsg设置验证字段名称:title未知:__call未知:__callStaticthink/view/driver/Php.php属性:config构造方法:__construct检测是否存在模板文件:exists渲染模板文件:fetch渲染模板内容:display主动定位模板内容:parseTemplate配置模板引擎:config获取模板引擎配置:getConfigframework无差别浏览实现,上面进行orm无差别浏览打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 14, 2022 · 1 min · jiezi

关于thinkphp:2022113thinkphp源码无差别阅读十八

thinkphp源码无差别浏览(十八)framework浏览think/route/dispatch/Callback.php执行:execthink/route/dispatch/Controller.php属性:controller、actionName初始化:init执行:exec应用反射机制注册控制器中间件:registerControllerMiddleware实例化拜访控制器:controllerthink/route/dispatch/Url.php构造方法:__construct解析url地址:parseUrl查看url是否曾经定义过路由:hasDefineRoutethink/service/ModelService.php启动:bootthink/service/PaginatorService.php注册:register启动:bootthink/service/ValidateService.php启动:bootthink/session/Store.php属性:data、init、name、id、handler、serialize构造方法:__construct设置数据:setData初始化:init设置name:setName获取name:getName设置id:setId获取id:getId获取所有数据:all设置:set获取:get获取并删除:pull增加:push判断是否有:has删除:delete清空:clear销毁:destroy从新生成id:regenerate保留:savesession设置,下次无效:flash将本次闪存推延到下次申请:reflash清空以后申请的session:clearFlashData序列化数据:serialize反序列化:unserializethink/session/driver/Cache.php属性:handler、expire、prefix构造方法:__construct读取:read删除:delete写入:writethink/session/driver/File.php属性:config构造方法:__construct初始化:initgc垃圾回收查找文件:findFiles获取文件名称:getFileName读取:read写文件(加锁):writeFile读文件(加锁):readFile写入:write删除:delete删除文件:unlink打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 13, 2022 · 1 min · jiezi

关于thinkphp:2022111thinkphp源码无差别阅读十七

thinkphp源码无差别浏览(十七)framework浏览think/route/RuleGroup.php属性:rules、rule、miss、fullName、alias构造方法:__construct设置分组路由规定:setFullName获取所属域名:getDomain获取分组别名:getAlias检测分组路由:check分组url匹配查看:checkUrl设置分组别名:alias提早解析分组路由规定:lazy解析分组规定及绑定:parseGroupRule检测分组路由:checkMergeRuleRegex获取分组miss路由:getMissRule注册miss路由:miss增加分组下的路由规定:addRule注册分组下的路由规定:addRuleItem设置路由分组前缀:prefix合并路由规定正则:mergeRuleRegex设置分组调度:dispatcher获取残缺分组名称:getFullName获取分组路由规定:getRule清空分组路由规定:clearthink/route/RuleItem.ph属性:miss、autoOption构造方法:__construct设置miss路由:setMiss判断miss:isMiss设置路由为主动注册为option:setAutoOptions判断是否主动注册option:isAutoOptins获取后缀:getSuffix路由规定预处理:setrule设置别名:name设置路由标识:setRuleName检测路由:checkRule检测路由:checkurl后缀以及slash查看:urlSlashCheck检测url和路由是否匹配:match设置路由所属分组:groupthink/route/RuleName.php属性:item、rule、group注册路由标识:setItem注册路由分组标识:setGroup注册路由规定:setRule依据路由规定获取路由对象:getRule获取路由分组:getGroup清空路由规定:clear获取路由列表:getRuleList导入路由标识:import依据路由标识获取路由信息:getName获取路由信息:getRuleItemInfothink/route/Url.php属性:app、route、vars、url、root、https、suffix、domain构造方法:__construct设置参数:vars设置后缀:suffix设置域名:domain设置url跟地址:root设置https:https检测域名:parseDomain解析后缀:parseSuffix解析地址:parseUrl剖析路由规定中的变量:parseVar匹配路由地址:getRuleUrl生成url:build字符串解决:__toStringdebug信息:__debugInfo打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 11, 2022 · 1 min · jiezi

关于thinkphp:2022110thinkphp源码无差别阅读十六

thinkphp源码无差别浏览(十六)framework浏览think/route/Dispatch.php属性:app、request、rule、dispatch、param构造方法:__construct初始化:init执行调度:run响应:autoResponse查看路由后置操作:doRouteAfter路由绑定过模型:createBindModel验证数据:autoValidate获取调度:getDispatch获取参数:getParam执行:exec休眠:__sleep唤醒:__wakeupdebug信息:__debugInfothink/route/Domain.php构造方法:__construct检测域名路由:check设置路由绑定:bind检测url绑定:checkUrlBind解析绑定参数:parseBindAppendParam绑定到类:bindToClass绑定到命名空间:bindToNamespace绑定到控制器:bindToControllerthink/route/Resource.php属性:resource、route、rest、model、validate、middleware构造方法:__construct生成资源路由规定:buildResourceRule设置资源容许:only设置资源排除:except设置资源路由的变量:vars绑定资源验证:withValidate绑定资源模型:withModel绑定资源中间件:withMiddlewarerest办法定义和批改think/route/Rule.php属性:name、domain、router、parent、rule、method、vars、option、pattern、mergeOptions查看:check设置路由参数:option设置路由参数:setOption注册变量规定:pattern设置标识:name获取路由对象:getRouter获取路由标识:getName获取以后路由规定:getRule获取以后路由地址:getRoute获取以后路由变量:getVars获取以后分组:getParent获取路由所在域名:getDomain获取路由参数:config获取变量规定:getPattern获取路由参数:getOption获取路由申请类型:getMethod设置申请类型:method查看后缀:ext查看禁止后缀:denyExt查看域名:domain设置参数过滤:filter绑定模型:model附加路由隐式参数:append绑定验证:validate指定路由中间件:middleware容许跨域:allowCrossDomain表单令牌验证:token设置路由缓存:cache查看路由分隔符:depr设置须要合并的路由参数:mergeOptions查看是否是https:https查看是否是json申请:json查看是否是ajax请去:ajax查看是否是pjax申请:pjax路由到模板地址:view设置路由残缺匹配:complateMatch是否去除url最初的斜线:removeSlash设置路由规定全局无限:crossDomainRule解析匹配到的路由规定:parseRule路由调度:dispatch解析url地址:dispatchController路由查看:checkOption解析url参数:parseUrlParams解析pathinfo:parseUrlPath生成路由正则规定:buildRouteRegex生成路由变量的正则规定:buildNameregex设置路由参数:__call睡眠:__sleep唤醒:__wakeupdebug:debugInfo打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 10, 2022 · 1 min · jiezi

关于thinkphp:202219thinkphp源码无差别阅读十五

thinkphp源码无差别浏览(十五)framework浏览think/middleware/AllowCrossDomain.php属性:cookieDomain、header构造方法:__construct容许跨域申请:handlethink/middleware/CheckRequestCache.php属性:cache、config构造方法:__construct设置以后地址的申请缓存:handle读取以后地址的申请缓存:getRequestCache读取以后地址的申请缓存:parseCacheKeythink/middleware/FormTokenCheck.php表单令牌检测:handlethink/middleware/LoadLangPack.php属性:app、lang、config构造方法:__construct路由初始化:handle主动侦测获取语言设置:detect保留以后语言到cookie:saveToCookiethink/middleware/SessionInit.php属性:app、session构造方法:__constructsession初始化:init保留session数据think/response/File.php属性:expire、name、mimeType、isContent、force构造方法:__construct解决数据:output设置是否为内容:isContent设置有效期:expire设置文件类型:mimeType设置文件强制下载:force获取文件类型:getMimeType设置下载时文件名称:namethink/response/Html.php属性:contentType构造方法:__constructthink/response/Json.php属性:options、contentType初始化:__construct解决数据:outputthink/response/Jsonp.php属性:options、contentType、request构造方法:__construct解决数据:outputthink/response/Redirect.php属性:request构造方法:__construct解决数据:output重定向传值:with记住以后url后跳转:remember跳转到上次记住的url:restorethink/response/View.php属性:options、vars、filter、contentType、view、isContent构造方法:__construct设置是否为内容:isContent解决数据:output获取试图变量:getVars模板变量赋值:assign试图内容过滤:filter查看模板是否存在:existsthink/response/Xml.php属性:options、contentType构造方法:__construct解决数据:outputxml编码:xmlEncode数据xml编码:dataToXml打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 9, 2022 · 1 min · jiezi

关于thinkphp:202218thinkphp源码无差别阅读十四

thinkphp源码无差别浏览(十四)framework浏览think/initializer/BootService.php初始化:initthink/initializer/Error.php属性:app注册异样解决:init异样解决:appException错误处理:appErrorshutdown解决:appShutdown是否致命:isFatal获取异样处理器:getExceptionHandlerthink/initializer/RegisterService.php属性:services初始化:initthink/log/Channel.php属性:name、logger、event、lazy、log、close、allow构造方法:__construct敞开通道:close清空日志:clear记录日志:record实时写入日志:write获取日志信息:getLog保留日志:save记录日志:emergency记录日志:alert记录日志:critical记录日志:error记录日志:warning记录日志:notice记录日志:info记录日志:debug记录日志:log动静调用:__callthink/log/ChannelSet.php属性:log、channels构造方法:__construct动静调用:__callthink/log/driver/File.php属性:config构造方法:__construct写入日志:save写入日志:write获取主日志文件名:getMasterLogFile获取独立日志文件名:getApartLevelFile查看日志大小并生成备份文件:checkLogSizethink/log/driver/Socket.php属性:app、config、css、allowForceClientIds、clientArg构造方法:__construct写入日志:save发送给指定客户端:sendToClient查看客户端受权:check获取客户端参数:getClientArg发送:send打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 8, 2022 · 1 min · jiezi

关于thinkphp:202216thinkphp源码无差别阅读十三

thinkphp源码无差别浏览(十三)framework浏览think/facade/App.php属性:getFacadeClassthink/facade/Cache.php属性:getFacadeClassthink/facade/Config.php属性:getFacadeClassthink/facade/Console.php属性:getFacadeClassthink/facade/Cookie.php属性:getFacadeClassthink/facade/Env.php属性:getFacadeClassthink/facade/Event.php属性:getFacadeClassthink/facade/FileSystem.php属性:getFacadeClassthink/facade/Lang.php属性:getFacadeClassthink/facade/Log.php属性:getFacadeClassthink/facade/Middleware.php属性:getFacadeClassthink/facade/Request.php属性:getFacadeClassthink/facade/Route.php属性:getFacadeClassthink/facade/Session.php属性:getFacadeClassthink/facade/Validate.php属性:getFacadeClassthink/facade/View.php属性:getFacadeClassthink/file/UploadedFile.php属性:text、originalName、mimeType、error构造方法:__construct是否是无效文件:isValid上传文件:move获取错误信息:getErrorMessage获取上传文件类型:getOriginalMime获取文件名称:getOriginalName获取文件扩展名:getOriginalExtension获取文件扩展名:extensionthink/filesystem/CacheStore.php属性:store、key、expire构造方法:__construct保留:save加载:loadthink/filesystem/Driver.php属性:cache、filesystem构造方法:__construct创立缓存存储:createCacheStore创立适配器:createAdapter创立文件系统:createFilesystem获取文件残缺门路:path门路转换为url:convertPathToUrl获取url:url保留文件:putFile指定文件名保留文件:putFileAs未知:__callthink/filesystem/driver/Local.php属性:config创立适配器:createAdapter获取文件url:url打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码

January 6, 2022 · 1 min · jiezi

关于thinkphp:202215thinkphp源码无差别阅读十二

thinkphp源码无差别浏览(十二)framework浏览think/event/AppInit.phpthink/event/HttpEnd.phpthink/event/HttpEnd.phpthink/event/LogRecord.php属性:type、message构造方法:__constructthink/event/LogWrite.php属性:channel、log构造方法:__constructthink/event/RouteLoaded.php构造方法:__constructthink/exception/ClassNotFoundException.php属性:class构造方法:__construct、getClassthink/exception/ErrorException.php属性:severity构造方法:__construct获取谬误级别:getSeveritythink/exception/FailException.php获取谬误级别:getSeveritythink/exception/FuncNotFoundException.php属性:func构造方法:__construct获取办法名:getFuncthink/exception/Handle.php属性:app、ignoreReport、isJson构造方法:__construct上报或者记录异样:report是否疏忽:isIgnoreReport渲染异样:render渲染异样renderForConsole渲染http异样:renderHttpException收集异样数据:convertExceptionToArray收集异样数据:convertExceptionToResponse渲染异样:renderExceptionContent获取报错编码:getCode获取报错信息:getMessage读取出错文件内容:getSourceCode获取异样扩大数据:getExtendData获取常量:getConstthink/exception/HttpException.php属性:statusCode、headers构造方法:__construct获取状态码:getStatusCode获取header:getHeadersthink/exception/HttpResponseException.php属性:response构造方法:__construct获取响应:getResponsethink/exception/InvalidArgumentException.phpthink/exception/RouteNotFoundException.phpthink/exception/ValidateException.php属性:error构造方法:__construct获取验证错误信息:getError打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

January 5, 2022 · 1 min · jiezi

关于thinkphp:202214TCP和websocket通讯

TCP和websocket通信应用场景:通过网页管制硬件设施,或者硬件设施的信息显示到网页上所用技术PHP环境workerman实现原理启动一个websocket服务端,过程启动的时候启动tcp,把tcp设置为websocket的一个属性上socketArray,而后在websocket承受音讯的回调里获取socketArray,循环取出tcp链接,发送音讯代码<?phpuse Workerman\Worker;require_once __DIR__ . '/vendor/autoload.php';$websocket = new Worker('Websocket://0.0.0.0:8888');$websocket->count = 1;$websocket->onWorkerStart = function ($websocket) { // 启动第一个tcp过程 $tcp1 = new Worker('tcp://0.0.0.0:6000'); // 设置到socketArray属性上 $websocket->tcpArray[] = $tcp1; $tcp1->listen(); // 启动第二个tcp $tcp2 = new Worker('tcp://0.0.0.0:6001'); $websocket->tcpArray[] = $tcp2; $tcp2->listen();};// 承受websocket音讯后转发给tcp$websocket->onMessage = function ($conn, $data) { global $websocket; foreach($websocket->tcpArray as $tcpItem) { foreach ($tcpItem->connections as $tcpConn) { $tcpConn->send($data); } }};Worker::runAll();

January 4, 2022 · 1 min · jiezi

关于thinkphp:202212thinkphp源码无差别阅读十

thinkphp源码无差别浏览(十)framework浏览console/command/optimize/Route.php配置:configure执行:execute生成路由缓存:buildRouteCache framework浏览console/command/optimize/Schema.php配置:configure执行:execute未知:buildModelSchema未知:buildDataBaseSchemaconsole/command/input/Argument.php常量:REQUIRED、OPTIONAL、IS_ARRAY属性:name、mode、default、description构造方法:__construct获取参数名:getName判断是否必须:isRequired判断是否是数组:isArray设置默认值:setDefault获取默认值:getDefault获取形容:getDescriptionconsole/command/input/Definition.php属性:arguments、requiredCount、hasAnArrayArgument、hasOptional、options、shortcuts构造方法:__construct设置指令的定义:setDefinition设置参数:setArguments增加参数:addArguments增加参数:addArgument获取参数:getArgument判断是否有参数:hasArgument获取所有参数:getArguments获取参数数量:getArgumentCount获取必填参数数量:getArgumentRequiredCount获取参数默认值:getArgumentDefaults设置选项:setOptions增加选项:addOptions增加选项:addOption获取选项:getOption判断是否有这个选项:hasOption获取所有选项:getOptions判断是否有短名称:hasShortcut依据短名称获取选项:getOptionForShortcut获取所有选项默认值:getOptionDefaults依据短名称获取选项名:shortcutToName获取该指令的介绍:getSynopsisconsole/command/input/Option.php常量:VALUE_NONE、VALUE_REQUIRED、VALUE_OPTIONAL、VALUE_IS_ARRAY属性:name、shortcut、mode、default、description构造方法:__construct获取短名称:getShortcut获取选项明:getName判断是否能够设置值:acceptValue是否必传参数:isValueRequired是否可选参数:isValueOptional是否数组:isArray设置默认值:setDefault获取默认值:getDefault获取形容:getDecription查看所给选项是否是以后这个:equalsconsole/command/output/Ask.php属性:stty、shell、input、output、question构造方法:__construct执行:run未知:doAsk未知:autocomplate未知:getResponse未知:validateAttempts显示问题的提示信息:writePrompt未知:getShell未知:hasSttyAvailableconsole/command/output/Descriptor.php属性:output、形容:describe输入内容:write形容参数:describeInputArgument形容选项:describeInputOption形容输出:describeInputDefinition形容指令:describeCommand形容控制台:describeConsole输入:writeText格式化:formatDefaultValue未知:getColumnWidth未知:calculateTotalWidthForOptions打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

January 2, 2022 · 1 min · jiezi

关于thinkphp:20211231thinkphp源码无差别阅读九

thinkphp源码无差别浏览(九)framework浏览console/Table.php常量:ALIGN_LEFT、ALIGN_RIGHT、ALIGN_CENTER属性:header、headerAlign、rows、cellAlign、colWidth、style、format设置表头信息:setHeader设置表格数据和对齐形式:setRows设置单元格对齐形式:setCellAlign查看列显示宽度:checkColWidth减少一行表格:addRow设置表格输入款式:setStyle输入分隔行:renderSeparator输出表头:renderHeader获取输入款式:getStyle输入表格:renderconsole/command/Clear.php配置指令:configure执行:execute革除:clear判断缓存是否过期:cacheHasExpiredconsole/command/Help属性:command配置:configure设置要获取帮忙的指令:setCommand执行:executeconsole/command/Lists.php配置:configure获取定义:getNativeDefinition执行:execute创立定义:createDefinitionconsole/command/Make.php属性:type获取模板:getStub配置:configure执行:execute生成类内容:buildClass获取文件名称:getPathName获取类名称:getClassName获取命名空间:getNamespaceconsole/command/RouteList.php属性:sortBy配置:configure执行:execute获取路由列表:getRouteListconsole/command/RunServer.php配置:configure执行:executeconsole/command/ServiceDiscover.php配置:configure执行:executeconsole/command/VerdorPublish.php配置:configure执行:handleconsole/command/Version.php配置:configure执行:executeconsole/command/make/stubs下模板模板:自定义命令、api控制器、空控制器、资源控制器、事件、事件监听、中间件、模型、服务、事件订阅、验证器cosole/command/make/Command.php属性:type配置:configure生成类内容:buildClass获取模板:getStub获取命名空间:getNamespaceconsole/command/make/Controller.php属性:type配置:configure获取模板:getStub获取类名称:getClassName获取命名空间:getNamespaceconsole/lcommand/make/Event.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespaceconsole/lcommand/make/Listener.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace获取命名空间:getNamespaceconsole/lcommand/make/Middleware.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace获取命名空间:getNamespaceconsole/lcommand/make/Model.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace获取命名空间:getNamespaceconsole/lcommand/make/Service.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace获取命名空间:getNamespaceconsole/lcommand/make/Subscribe.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace获取命名空间:getNamespaceconsole/lcommand/make/Validate.php属性:type配置:configure获取模板:getStub获取命名空间:getNamespace打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

January 1, 2022 · 1 min · jiezi

关于thinkphp:20211230thinkphp源码无差别阅读八

thinkphp源码无差别浏览(八)framework浏览console/Command.php属性:console、name、processTitle、aliases、definition、help、description、ignoreValidationErrors、consoleDefinitionMerged、consoleDefinitionMergedWithArgs、synopsis、usages、input、output、app构造方法:__construct疏忽验证谬误:ignoreValidationErrors设置控制台:setConsole获取控制台:getConsole设置app:setApp获取app:getApp是否无效:isEnabled配置指令:configure执行指令:execute用户验证:interact初始化:initialize执行指令:run合并参数定义:mergeConsoleDefinition设置参数定义:setDefinition获取参数定义:getDefinition获取以后指令的参数定义:getNativeDefinition增加参数:addArgument增加选项:addOption设置指令名称:setName设置过程名称:setProcessTitle获取指令名称:getName设置形容:setDescription获取形容:getDescription设置帮忙信息:setHelp获取帮忙:getHelp形容信息:getProcessedHelp设置别名:setAliases获取别名:getAliases获取简介:getSynopsis增加用户:addUsage获取用户:getUsage验证指令名称:validateName输入表格:tableconsole/Input.php属性:definition、options、arguments、interactive、tokens、parsed构造方法:__construct设置token:setTokens绑定实例:bind解析参数:parse解析短选项:parseShortOption解析短选项:parseShortOptionSet解析残缺选项:parseLongOption解析参数:parseArgument增加短选项:addShortOption增加残缺选项:addLongOption获取第一个参数:getFirstArgument判断是否有选项:hasParameterOption获取选项:getParameterOption验证输出:validate查看输出是否是交互的:isInterActive设置输出交互:setInterActive获取所有参数:getArguments获取参数:getArgument设置参数:setArgument判断是否有参数:hasArgument获取所有选项:getOptions获取选项:getOption设置选项:setOption判断是否有选项:hasOption本义指令:escapeToken返回传递给命令的参数:__toStringconsole/Output.php常量:VERBOSITY_QUIET、VERBOSITY_NORMAL、VERBOSITY_VERBOSE、VERBOSITY_VERY_VERBOSE、VERBOSITY_DEBUG、OUTPUT_NORMAL、OUTPUT_RAW、OUTPUT_PLAIN、属性:verbosity、handle、styles构造方法:__construct未知:ask、askHidden、confirm、choice、askQuestion输入空行:newLine输入信息并换行:writeln输入信息:write渲染异样:renderException设置输入信息级别:setVerbosity获取输入信息级别:getVerbosity判断是否不输入:isQuiet判断是否一般输入:isVerBose判断是否详情输入:isVeryVerbose判断是否调试:isDebug未知:describe、__call打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 30, 2021 · 1 min · jiezi

关于thinkphp:20211229thinkphp源码无差别阅读七

thinkphp源码无差别浏览(七)framework浏览View.php属性:namespace、data、filter、获取模板引擎:engine模板变量赋值:assign试图过滤:filter解析和获取模板内容:fetch渲染内容输入:display获取模板渲染内容:getContent模板变量赋值:__set获取模板变量:__get监测是否有模板变量:__isset未知:resolveConfig获取默认驱动:getDefaultDrivercache/Driver.php属性:handler、readTimes、writeTimes、options、tag获取有效期:getExpireTime获取理论缓存标识:getCacheKey读取缓存并删除:pull追加缓存:push追加缓存:append获取缓存,如果不存在则写入:remember获取缓存标签:tag获取标签蕴含的缓存标识:getTagItems获取理论标签名:getTagKey序列化:serialize反序列化:unserialize获取句柄对象:handler获取读取缓存次数:getReadTimes获取写入缓存次数:getWriteTimes读取缓存:getMultiple写入缓存:setMultiple删除缓存:deleteMultiple动静办法条用:__callcache/TagSet.php属性:tag、handle构造方法:__construct写入缓存:set追加缓存标识到标签:append写入缓存:setMultiple如果不存在则写入:remember革除缓存:clearcache/driver/File.php属性:options构造方法:__construct获取变量的存储文件名:getCacheKey获取缓存数据:getRaw判断缓存是否存在:has读取缓存:get写入缓存:set自增缓存:inc自减缓存:dec删除缓存:delete革除缓存:clear删除缓存标签:clearTag删除文件:unlink删除文件夹:rmdircache/driver/Memcache.php属性:options构造方法:__construct判断是否有缓存:has读取缓存:get写入缓存:set自增缓存:inc自减缓存:dec删除缓存:delete革除缓存:clear删除缓存标签:clearTagcache/driver/Memcached.php属性:options构造方法:__construct判断是否有缓存:has读取缓存:get写入缓存:set自增缓存:inc自减缓存:dec删除缓存:delete革除缓存:clear删除缓存标签:clearTagcache/driver/Redis.php属性:options构造方法:__construct判断是否有缓存:has读取缓存:get写入缓存:set自增缓存:inc自减缓存:dec删除缓存:delete革除缓存:clear删除缓存标签:clearTag追加缓存:append获取标签蕴含的缓存标识:getTagItemscache/driver/Wincache.php属性:options构造方法:__construct判断是否有缓存:has读取缓存:get写入缓存:set自增缓存:inc自减缓存:dec删除缓存:delete革除缓存:clear删除缓存标签:clearTag打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 29, 2021 · 1 min · jiezi

关于thinkphp:20211228thinkphp源码无差别阅读六

thinkphp源码无差别浏览(六)framework浏览Service.php属性:app构造方法:__construct加载路由:loadRoutesFrom注册路由:registerRoutes增加指令:commandsSession.php属性:namespace设置驱动:createDriver获取配置:getConfig未知:resolveConfig获取默认驱动:getDefaultDriverValidate.php属性:type、alias、rule、message、field、typeMsg、currentScene、defaultRegex、filter、scene、error、batch、failException、only、remove、append、regex、db、lang、request、maker构造方法:__construct设置服务注入:maker设置Lang对象:setLang设置Db对象:setDb设置Request对象:setRequest增加验证规定:rule注册验证规定:extend设置验证规定的默认提示信息:setTypeMsg设置提示信息:message设置验证场景:scene是否有验证场景:hasScene设置批量验证:batch设置验证失败抛出异样:failException指定须要验证的字段:only移除验证规定:remove追加验证规定:append测验数据:check依据验证规定验证数据:checkRule验证单个字段规定:checkItem获取以后验证类型及规定:getValidateType是否统一规定:confirm是否不同规定:diffrent大于等于规定:egt大于规定:gt小于等于规定:elt小于规定:lt相等规定:eq必须规定:must无效格局:is获取图片类型:getImageType验证表单令牌:token验证域名和ip:activeUrl验证ip:ip验证文件后缀:checkExt验证文件大小:checkSize验证文件类型:checkMime验证文件后缀:fileExt验证文件类型:fileMime验证文件大小:fileSize验证图片宽高以及类型:image验证工夫和日期格局:dateFormat验证唯一性:unique应用filter_var验证:filter验证等于某个值:requireIf应用回调验证:requireCallback验证某个字段有值的时候,必须:requireWith验证某个字段没有值的时候,必须:requireWithout验证在范畴之内:in验证不在范畴之内:notIn验证在之间:between验证不在之间:notBetween验证数据长度:length验证数据最大值:max验证数据最小值:min验证日期在之后:after验证日期在之前:before验证日期在之后:afterWith验证日期在之前:beforeWith验证有效期:expire验证容许的ip:allowIp验证禁止ip:denyIp应用正则验证:regex获取谬误:getError获取数据的值:getDataValue获取验证规定谬误提示信息:getRuleMsg获取验证规定谬误提示信息:parseErrorMsg错误信息数组解决:errorMsgIsArray获取验证场景:getScene动静办法,间接调用is办法进行验证:__call打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 28, 2021 · 1 min · jiezi

关于thinkphp:20211227thinkphp源码无差别阅读五

thinkphp源码无差别浏览(五)framework浏览Response.php属性:data、contentType、chatset、code、allowCache、options、header、content、cookie、session、初始化:init创立Response对象设置session对象:setSession发送数据到客户端:send解决数据:output输入数据:sendData设置输入的参数:options设置输入数据:data设置申请缓存:allowCache是否容许申请缓存:isAllowCache设置cookie:cookie设置响应头:header设置content:content设置状态码:code设置lastmodified:lastModified设置expires:expires设置eTag:eTag设置缓存管制:cacheControl设置页面输入类型:contentType获取头部信息:getHeader获取原始数据:getData获取输入数据:getContent获取状态码:getCodeRoute.php属性:rest、config、app、request、ruleName、host、group、bind、domains、cross、lazy、isTest、mergeRuleRegx、removeSlash构造函数:__construct初始化:init获取配置:config设置提早解析:lazy设置测试模式:setTestMode是否测试模式:isTest设置合并解析:mergeRuleRegx初始化默认域名:setDefaultDomain设置以后分组:setGroup获取分组:getGroup注册变量规定:pattern注册路由参数:option注册域名路由:domain获取域名:getDomains获取ruleName:getRuleName设置路由绑定:bind获取路由绑定:getBind读取路由绑定:getDomainBind获取路由标识:getName批量导入路由标识:import注册路由标识:setName保留理由规定:setRule读取路由规定:getRule读取路由列表:getRuleList清空路由规定:clear注册路由规定:rule设置无效跨域路由规定:setCrossDomainRule注册路由分组:group注册路由:any注册get路由:get注册post路由:post注册put路由:put注册delete路由:delete注册patch路由:patch注册options路由:options注册资源路由:resource注册试图路由:view注册重定向路由:redirectrest定义和批改:rest获取rest定义的参数:getRest注册miss路由:miss路由调度:dispatch检测路由:check获取pathinfo:pathurl解析:url监测域名路由规定:checkDomainurl生成:buildUrl设置全局路由分组参数:__call打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 27, 2021 · 1 min · jiezi

关于thinkphp:20211226thinkphp源码无差别阅读四

thinkphp源码无差别浏览(四)framework浏览Middleware.php属性:queue、app构造方法:__construct导入中间件:import注册中间件:add注册路由中间件:route注册控制器中间件:controller注册中间件到开始地位:unshift获取所有中间件:all调度广告:pipeline完结调度:end移除解决:handleException解析中间件:buildMiddleware中间件排序:sortMiddleware获取中间件优先级:getMiddlewarePriorityPipeline.php属性:passable、pipes、exceptionHandler初始数据:send调用栈:through执行:then设置异样处理器:whenException未知:carry异样解决:handleExceptionRequest.ph属性:pathinfoFetch、varPathinfo、varMethod、varAjax、varPjax、rootDomain、httpsAgentName、proxyServerIp、proxyServerIpHeader、method、domain、host、subDomain、panDomain、url、baseUrl、baseFile、root、pathinfo、path、realIp、controller、action、param、get、post、request、rule、route、middleware、put、session、cookie、env、server、file、header、mimeType、content、filter、input、secureKey、mergeParam构造函数:__construct自定义实例化:__make设置域名:setDomain获取域名:domain获取以后根域名:rootDomain设置子域名:setSubDomain获取子域名:subDomain设置泛域名:setPanDomain获取泛域名:panDomain设置url:setUrl获取url:url设置以后url:setBaseUrl获取url:baseUrl获取以后执行的文件:baseFile设置url拜访根地址:setRoot获取url跟地址:root获取url根目录:rootUrl设置以后pathinfo:setPathinfo获取以后pathinfo:pathinfo获取拜访后缀:ext获取以后请去工夫:time以后申请资源的类型:type设置资源类型:mimeType设置申请类型:setMethod获取申请类型:method是否get:isGet是否post:isPost是否put:isPut是否delete:isDelete是否head:isHead是否patch:isPatch是否options:isOptions是否cli:isCli是否cgi:isCgi获取申请参数:param获取所有参数:all设置路由:setRule获取路由:rule设置路由:setRoute获取路由:route获取get参数:get获取中间件参数:middleware获取post参数:post获取put参数:put获取参数:getInputData获取delete参数:delete获取patch参数:patch获取参数:request获取环境变量:env获取session:session获取cookie:cookie获取server:server获取上传文件:file解决上传文件:dealUploadFile抛出异样:throwUploadFileException设置或者获取header:header获取参数:input过滤数据:filterData类型转换:typeCast获取数据:getData设置或者获取过滤规定:filter获取过滤规定:getFilter递归过滤:filterValue判断是否有参数:has获取指定的参数:only排除指定的参数:except是否ssl:isSsl是否json:isJson是否ajax:isAjax是否pjax:isPjax获取客户ip:ip是否非法ip:isValidIpip转化为二进制:ip2bin是否手机拜访:isMobile获取scheme:scheme获取query参数:query设置host:setHost获取host:host获取port:port获取protocol:protocol近程端口:remotePort获取contentType:contentType获取以后平安key:secureKey设置以后控制器:setController设置以后操作:setAction获取控制器:controller获取办法:action设置或者获取content:getContent获取以后的php://input:getInput生成申请令牌:buildToken查看申请令牌:checkToken设置中间件传递数据:withMiddleware设置get数据:withGet设置post数据:withPost设置cookie数据:withCookie设置session:withSession设置server:withServer设置header:withHeader设置env:withEnv设置input:withInput设置上传文件:withFiles设置路由变量:withRoute设置中间件传递数据:__set获取中间件传递数据:__get判断中间件数据:__isset数据式拜访:offsetSet、offsetGet、offsetExists、offsetUnset打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 26, 2021 · 1 min · jiezi

关于thinkphp:20211225-thinkphp源码无差别阅读三

【2021/12/25】thinkphp源码无差别浏览(三) framework浏览Http.php属性:app、name、path、routePath、isBild构造方法:__construct设置利用名称:name获取利用名称:getName设置利用目录:path获取利用目录:getPath获取路由目录:getRoutePath设置路由目录:setRoutePath设置利用绑定:setBind判断利用是否绑定:isBind执行应用程序:run初始化利用:initialize执行用于程序:runWithRequest路由调度:dispatchToRoute加载全局中间件:loadMiddleware加载路由:loadRoutes上报异样:reportException渲染异样:renderException申请完结:endLang.php属性:config、lang、range构造方法:__construct自定义实例化:__make设置以后语言:setLangSet获取以后语言:getLangSet获取默认语言:defaultLangSet加载语言:load解析语言文件:parse判断是否有语言配置项:has获取语言配置:get主动设置获取以后语言:detect保留以后语言设置到cookie:saveToCookieLog.php常量:emergency、alert、critical、error、warning、notice、info、debug、sql属性:namespace获取默认驱动:getDefaultDriver获取日志配置:getConfig获取渠道配置:getChannelConfig获取渠道实例:channel获取渠道类型:resolveType创立驱动:createDriver获取驱动配置:resolveConfig清空日志:clear敞开日志写入:close获取日志信息:getLog保留日志信息:save记录日志:record写入日志:write注册日志写入事件:listen记录日志:log记录emergency:emergency记录alert:alert记录critical:critical记录error:error记录warning:warning记录notice:notice记录info:info记录debug:debug记录sql:sql魔术办法:__callManager.php属性:app、drivers、namespace构造方法:__construct获取驱动实例:driver获取驱动实例:getDriver获取驱动类型:resolveType获取驱动配置:resolveConfig获取驱动类:resolveClass获取驱动参数:resolveParams创立驱动:createDriver移除驱动:forgetDriver获取默认驱动:getDefaultDriver动静调用:__call打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 25, 2021 · 1 min · jiezi

关于thinkphp:20211224thinkphp源码无差别阅读二

thinkphp源码无差别浏览(二) framework浏览Cookie.php属性:config、cookie、request、构造方法:__construct自定义实例化:__make获取cookie:get是否存在:has设置cookie:set报错cookie:setCookie永恒保留:forever删除cookie:delete获取所有cookie:getCookie保留cookie:save保留cookie:saveCookieDb.php自定义实例化:__make注入模型对象:modelMaker设置配置对象:setConfig获取配置:getConfig设置Event对象:setEvent注册事件:event触发事件:triggerEnv.php属性:data构造方法:__construct加载环境变量文件:load获取环境变量值:get获取环境变量值:getEnv设置环境变量值:set判断环境变量:has魔术办法:__set、__get、__isset数组式拜访:offsetSet、offsetExists、offsetUnset、offsetGetEvent.php属性:listener、bind、app构造方法:__construct批量注册事件监听:listenEvents注册事件监听:listen判断工夫监听:hasListener移除事件监听:remove指定事件别名:bind注册事件订阅:subscribe主动注册事件观察者:observe触发事件:trigger触发事件(只容许一个返回值):until执行事件调度:dispatchException.php属性:data设置异样额定数据:setData获取异样额定数据:getDataFacade.php属性:alwaysNewInstance创立实例:createFacade获取facade对应的类名:getFacadeClass实例化以后facade:instance获取类的实例:make调用实例类的办法:__callStaticFile.php属性:hash、hashName构造方法:__construct获取文件hash:hash获取文件md5:md5获取文件sha1:sha1获取文件类型信息:getMime挪动文件:move实例化一个新文件:getTargetFile获取文件名:getName文件扩展名:extension主动生成文件名:hasNameFilesystem.php属性:namespace获取磁盘:disk获取磁盘类型:resolveType获取磁盘配置:resolveConfig获取磁盘配置:getConfig获取磁盘配置:getDiskConfig获取默认驱动:getDefaultDriver打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 24, 2021 · 1 min · jiezi

关于thinkphp:thinkphp源码无差别阅读一

thinkphp源码无差别浏览(一)thinkphp的framework源码大略165个文件,咱们不依照逻辑剖析浏览源码,咱们一个文件一个文件浏览,浏览完当前有个大略理解,而后在运行逻辑下进行浏览framework浏览App.php浏览常量:VERSION-定义框架版本号属性:$appDebug、envName、beginTime、beginRem、namespace、rootPath、thinkPath、appPath、runtimePath、routePath、configExt、initializers、services、initialized、bind构造方法:__construct注册服务:register执行服务:bootService获取服务:getService设置调试模式:debug是否调试模式:isDebug设置利用命名空间:setNamespace获取利用命名空间:getNamespace设置环境变量标识:setEnvName获取框架版本:version获取利用根目录:getRootPath获取利用根底魔力:getBasePath获取以后利用目录:getAppPath设置利用目录:setAppPath获取利用运行目录:getRuntimePath设置利用运行目录:setRuntimePath获取框架外围目录:getThinkPath获取利用配置目录:getConfigPath获取配置后缀:getConfigExt获取用于开启工夫:getBeginTime获取利用初始内存占用:getBeginRem加载环境变量:loadEnv初始化利用:initialize是否初始化:initialized加载语言包:loadLangPack疏导援用:boot加载利用文件和配置:load调试模式设置:debugModeInit注册利用事件:loadEvent解析利用类名:parseClass是否在命令行下运行:runningInConsole获取利用根目录:getDefaultRootPathCache.php浏览属性:namespace获取默认驱动:getDefaultDriver获取缓存配置:getConfig获取驱动配置:getStoreConfirm未知:resolveType未知:resolveConfig连贯获取切换缓存:store清空缓存池:clear读取缓存:get写入缓存:set删除缓存:delete读取缓存:getMultiple写入缓存:setMultiple删除缓存:deleteMultiple判断缓存是否存在:has缓存标签:tagConfig.php浏览属性:config、path、ext构造方法:__construct未知:__make加载配置文件:load解析配置文件:parse判断配置是否存在:has获取一级配置:pull获取配置:get设置配置:setConsole.php浏览属性:app、commands、wantHelps、catchExceptions、autoExit、definition、defaultCommand、defaultCommands、startCallbacks构造方法:__construct初始化:initialize结构request:makeRequest增加初始化器:starting清空启动器:flushStartCallbacks设置执行用户:setUser启动:start加载指令:loadCommands未知:call执行以后指令:run执行指令:doRun设置输出参数:setDefinition获取输出参数:getDefinition获取帮忙:getHelp是否捕捉异样:setCatchException是否主动退出:setAutoExit获取残缺版本号:getLongVersion增加指令集:addCommands增加指令:addCommand获取指令:getCommand判断指令是否存在:hasCommand获取所有的命名空间:getNamespaces查找命名空间的名称或缩写:findNamespace查找指令:find获取所有指令:all配置输入输出:configurateIO执行指令:doRunCommand获取指令的根底名称:getCommandName获取默认输出:getDefaultInputDefinition获取倡议:getAbbreviationSuggestions返回命名空间局部:extractNamespace查找可代替倡议:findAlternatives返回所有命名空间:extractAllNamesapcesContainer.php属性:instance、instances、bind、invokeCallback获取以后容器实例:getInstance设置以后容器实例:setInstance注册一个容器对象回调:resolving获取容器中的对象实例:pull获取容器中的对象实例:get绑定类、闭包、对象、接口到容器:bind依据别名获取类实在的名字:getAlias绑定一个类实例到容器:instance判断容器中是否存在类和标识:bound判断容器中是否存在类和标识:has判断容器中是否存在类和标识:exists创立类实例,单例:make删除容器中的对象实例:delete执行函数或者闭包:invokeFunction执行反射类的办法:invokeMethod执行反射类的办法:invokeReflectMethod调用反射执行callable:invoke调用反射,执行类的实例化:invokeClass执行invokeClass回调:invokeAfter绑定参数:bindParams创立工厂对象实例:factory获取对象类型的参数值:getObjectParam魔术办法和数组是拜访:__set、__get、__isset、__unset、offsetExists、offsetGet、offsetSet、offsetUnset、count、getIterator打算浏览[ ] framework源码 [ ] orm源码 [ ] helper源码 留言点击留言

December 18, 2021 · 1 min · jiezi

关于thinkphp:独立thinkphp323中Image操作

参考thinkphp3.2.3中Image操作 https://www.kancloud.cn/manua... 不依赖任何框架 个别状况下都会装置gd库 须要Imagick请装置 https://pecl.php.net/package/... 装置composer require whereof/think-image实例化类库$image = new \whereof\ThinkImage\Image();默认应用GD库进行图像操作,如果须要应用Imagick库操作的话,须要改成: $image = new \whereof\ThinkImage\Image(\Think\Image::IMAGE_IMAGICK); // 或者采纳$image = new \whereof\ThinkImage\Image('Imagick');图像操作上面来看下根底的图像操作性能的应用办法。 关上图像文件假如以后入口文件目录上面有一个1.jpg文件 应用open办法关上图像文件进行相干操作: $image = \whereof\ThinkImage\Image(); $image->open('./1.jpg');也能够简化成上面的形式: $image = new \whereof\ThinkImage\Image(\whereof\ThinkImage\Image::IMAGE_GD,'./1.jpg'); // GD库// 或者$image = new \whereof\ThinkImage\Image(\whereof\ThinkImage\Image::IMAGE_IMAGICK,'./1.jpg'); // imagick库获取图像信息能够获取关上图片的信息,包含图像大小、类型等,例如: $width = $image->width(); // 返回图片的宽度$height = $image->height(); // 返回图片的高度$type = $image->type(); // 返回图片的类型$mime = $image->mime(); // 返回图片的mime类型$size = $image->size(); // 返回图片的尺寸数组 0 图片宽度 1 图片高度裁剪图片应用crop和save办法实现裁剪图片性能。 //将图片裁剪为400x400并保留为corp.jpg$image->crop(400, 400)->save('./crop.jpg');反对从某个坐标开始裁剪,例如上面从(100,30)开始裁剪: //将图片裁剪为400x400并保留为corp.jpg$image->crop(400, 400,100,30)->save('./crop.jpg');生成缩略图应用thumb办法生成缩略图 // 依照原图的比例生成一个最大为150*150的缩略图并保留为thumb.jpg$image->thumb(150, 150)->save('./thumb.jpg');能够反对其余类型的缩略图生成,设置包含\whereof\ThinkImage\Image的下列常量或者对应的数字: ...

December 11, 2021 · 1 min · jiezi

关于thinkphp:在-Thinkphp-应用程序中记录-HTTP-请求

这个包增加了一个中间件,能够将传入的申请记录到默认日志中。 如果在用户申请期间呈现任何问题,您依然能够拜访该用户发送的原始申请数据。 装置您能够通过 composer 装置软件包: composer require whereof/think-http-logger配置文件config/http-logger.php内容: <?phpreturn [ /* * The log profile which determines whether a request should be logged. * It should implement `LogProfile`. */ 'log_profile' => \whereof\think\HttpLogger\LogNonGetRequests::class, /* * The log writer used to write the request to a log. * It should implement `LogWriter`. */ 'log_writer' => \whereof\think\HttpLogger\DefaultLogWriter::class, /* * The log channel used to write the request. */ 'log_channel' => env('LOG_CHANNEL', 'file'),];控制器中应用use whereof\think\HttpLogger\Middlewares\HttpLogger;class Index extends BaseController{ protected $middleware =[ HttpLogger::class ]; public function index() { return 'test HttpLogger'; }}路由中应用Route::get('think', function () { return 'hello,ThinkPHP6!';})->middleware(\whereof\think\HttpLogger\Middlewares\HttpLogger::class);全局app/middleware.php<?php// 全局中间件定义文件return [ ...... \whereof\think\HttpLogger\Middlewares\HttpLogger::class];日志记录两个类用于解决传入申请的日志记录:LogProfile 类将确定是否应记录申请,LogWriter 类将申请写入日志。 ...

December 5, 2021 · 1 min · jiezi

关于thinkphp:thinkphp6速查手册

申请变量use think\facade\Request;Request::param('name');Request::param();全副申请变量 返回数组Request::param(['name', 'email']); 多个变量Request::param('a','1') $a不存在应用默认值1Request::param('username','','strip_tags'); 参数过滤 去掉html标签 htmlspecialchars转换成实体入库 strtolower小写Request::header(); 申请头数组,反对单个 cookieinput("name");Request::session();获取 $_SESSION 变量Request::cookie();获取 $_COOKIE 变量Request::server();获取 $_SERVER 变量Request::env();返回env数组Request::file();获取 $_FILES 变量Request::baseUrl(); /index/indexRequest::host(true); 域名:www.baidu.com,默认无参数蕴含端口:80Request::url(1); 残缺域名和地址 http://www.baidu.com:80/index/indexRequest::domain(1) http://www.baidu.comRequest::time() 申请工夫戳Request::app() 利用名 indexRequest::controller() 控制器 Index 参数true小写Request::action() 操作 index 参数true 小写Request::method(true); 申请类型获取 GETisGet isPost isPut isDelete isAjax isMobile isHead 判断是否某种类型Request::has('id','get'); 检测变量id是否存在响应$data=['code'=>200,'msg'=>'胜利','data'=>['中国']];json($data);jsonp($data);xml($data);redirect('http://www.thinkphp.cn');redirect('/index/hello/name'); //站内跳转download('./static/2.xlsx'); 下载路由Route::get('new/<id>','News/read'); // 定义GET申请路由规定Route::post('new/<id>','News/update'); // 定义POST申请路由规定Route::put('new/:id','News/update'); // 定义PUT申请路由规定Route::delete('new/:id','News/delete'); // 定义DELETE申请路由规定Route::any('new/:id','News/read'); // 所有申请都反对的路由规定->allowCrossDomain();跨域url生成url('index/hello', ['id'=>5,'name'=>'李白'],'do'); http://www.baidu.com/index/hello/李白.do?id=5url('index/hello#aa'); 锚点数据库操作use think\facade\Db;$rs =Db::name('user')->where('id',1)->find(); 查问一条记录 name不含前缀$rs =Db::table('ims_user')->where('sex', 2)->select(); 多条数据 table含前缀$rs1 =Db::name('user')->where('id', 1)->value('name'); 查问某个字段值$rs =Db::table('ims_user')->where('sex', 2)->column('name,id','id'); 返回name,id列,前面是key$userId = Db::name('user')->insertGetId($data);//插入数据返回idDb::name('user')->limit(100)->insertAll($data); 插入多条数据,分每次100Db::name('user')->where('id', 1)->update(['name' => 'thinkphp']); 更新Db::table('think_user')->delete(1);Db::table('think_user')->delete([1,2,3]);Db::table('think_user')->where('id',1)->delete();Db::name('user')->delete(true);//清空数据where('id','<>',1) 不等于1 > >= like where("id=:id and username=:name", ['id' => 1 , 'name' => 'thinkphp'])field('id,title,content') 指定字段limit(10,25) 第十条开始25条 单数字返回数据条数page(1,10) 第一页十条order(['id'=>'desc','sex'=>'desc']) 排序group('user_id,test_time') 分组count() max('id') min() avg() sum() 聚合函数whereTime('birthday', '>=', '1970-10-1') 反对< = whereTime('create_time','-2 hours') 查问2小时whereBetweenTime('create_time', '2017-01-01', '2017-06-30') 查问时间段whereYear('create_time') 往年 whereYear('create_time','2018') last year 去年whereMonth('create_time') last month上月 2018-06 具体月份whereWeek('create_time') last week 上周whereDay('create_time')明天 yesterday昨天 2018-11-1具体Db::query("select * from think_user where status=1"); 原生查问Db::execute("update think_user set name='thinkphp' where status=1");//更新插入删除Db::query("select * from think_user where id=? AND status=?", [8, 1]);//绑定$list = Db::name('user')->where('status',1)->paginate(10); 分页每页10条缓存操作Cache::set('name', $value, 3600); 1小时后过期Cache::get('name'); 获取缓存多缓存类型配置return [ // 缓存类型为File 'type' => 'redis', // 全局缓存有效期(0为永恒无效),开发下肯定要设置-1 否在刷新后 还在 'expire'=> -1, // 缓存前缀 'prefix'=> 'think', // 缓存目录 'host' => '127.0.0.1',];return [ // 应用复合缓存类型 'type' => 'complex', // 默认应用的缓存 'default' => [ // 驱动形式 'type' => 'file', // 缓存保留目录 'path' => '../runtime/default', ], // 文件缓存 'file' => [ // 驱动形式 'type' => 'file', // 设置不同的缓存保留目录 'path' => '../runtime/file/', ], // redis缓存 'redis' => [ // 驱动形式 'type' => 'redis', // 服务器地址 'host' => '127.0.0.1', ],];use think\facade\Cache;Cache::store('file')->set('name','123',0);$v = Cache::store('redis')->get('name'); Cache::store('default')->get('name');文件缓存Cache::delete('name');Cache::clear();Cache::set('name', [1,2,3]);Cache::push('name', 4);Cache::remember('start_time', time()); 不存在则创立Cache::inc('name',1); 自增1Cache::dec('name',1); 自减1$redis = Cache::handler(); redis对象配置redis sessionreturn [ 'type' => 'redis', 'prefix' => 'think', 'auto_start' => true, // redis主机 'host' => '127.0.0.1', // redis端口 'port' => 6379, // 明码 'password' => '',]session('name', ['thinkphp']); 设置反对字符串 数组session('name');获取session('name', null);删除session(null);清空cookie操作 设置不反对数组,序列化后存储cookie('name');cookie('name', null);cookie('think_lang','en-us');//设置语言类型数据验证think\facade\Validate$rule = [ 'name' => 'require|max:25', 'age' => 'number|between:1,120', 'email' => 'email',];$msg = [ 'name.require' => '名称必须', 'name.max' => '名称最多不能超过25个字符', 'age.number' => '年龄必须是数字', 'age.between' => '年龄只能在1-120之间', 'email' => '邮箱格局谬误',];$data = [ 'name' => 'thinkphp', 'age' => 10, 'email' => 'thinkphp@qq.com',];$validate = Validate::rule($rule)->message($msg);$result = $validate->check($data);if(!$result) { dump($validate->getError());}

July 24, 2021 · 2 min · jiezi

关于thinkphp:ThinkPHP里无法输出图片-设置响应头

明天写了一个PHP生成图片,想用浏览器查看,然而每次关上都是一串乱码,看样子是图片源二进制数据,而后查看了下响应头是text/html,那我明明设置了image/jpeg header("Content-type", "image/jpeg");这阐明TP默认设置了text/html,查了官网文档,啥也没说,去网上查,才晓得TP有个Response类,默认所有控制器输入text/html,官网文档啥也没说,只好本人去翻Response这个类了 ThinkPHP6\vendor\topthink\framework\src\think\Response.php基类Response被这几个类继承,我试了下File类,然而这个File是输入文件,浏览器间接下载了 $file = new File('123.jpg');$response = $file->mimeType('image/jpeg');throw new HttpResponseException($response);在看看基类Response /** * 创立Response对象 * @access public * @param mixed $data 输入数据 * @param string $type 输入类型 * @param int $code 状态码 * @return Response */ public static function create($data = '', string $type = 'html', int $code = 200): Response { $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst(strtolower($type)); return Container::getInstance()->invokeClass($class, [$data, $code]); }这里是主动找response目录下的响应类,但我只想设置一个响应头来显示我的图片,文档翻遍了没找到办法,而后看了看目录下的Html类,那咱们能够本人写一个自定义类来输入本人想要的响应格局 ...

August 22, 2020 · 1 min · jiezi

JSON-Web-Token-使用详解

JWT是什么?JSON Web Token(缩写 JWT)是目前最流行的<font color='red'>跨域</font>认证解决方案。它是有三部分组成,示例如下,具体的讲解如下(jwt是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjMfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c它是由一个"."号隔开、三部分组成。第一部分是header信息, { "alg": "HS256",// 加密的算法 "typ": "JWT"// 加密的方式,填写JWT}第二部分是Payload,有固定的六个部分和自定义数据组成,自定义数据看自己的情况需要来定义,是可以省去的。 'iss' => 'https://www.qqdeveloper.com',// 签发人'exp' => time() + 86400,// 过期时间(这里的有效期时间为1天)'sub' => '主题内容',// 主题'aud' => '受众内容',// 受众'nbf' => $time,// 生效时间'iat' => $time,// 签发时间'jti' => 123,// 编号第三部分是Signature(是对前两部分加密得来的)。由于前两部分是公开透明的数据,因此防止数据的篡改和泄露,我们需要加密处理。首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。 第一部分的加密方式(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)最终生成的就是上面很长的一段字符串了。 为什么会使用JWT这就需要从我们传统的认证模式来说了,传统的认证模式是基于session和cookie来实现用户的认证和鉴权。具体的流程模式如下图。<center>(图一)Session与Cookie认证与鉴权</center>1.客户端向服务端发送一个http请求。 2.服务端在收到客户端的请求时,生成一个唯一的sessionid,<font color='red'>这里需要将该生成的session存储在服务端</font>,这个sessionid存储具体的session内容,默认的是文件存储,当然我们可以修改具体的存储方式,例如数据库存储。3.客户端在接受到这个sessionid时,存在cookie里面,每次请求时携带该sessionid。4.服务端在接收到客户端的请求之后,根据客户端发送的sessionid来进行认证与授权。这里也推荐一下自己之前分享的一篇有关session于cookie的知识点。session与cookie详解<center>(图二)传统的token授权</center>1.客户端向服务端发送一个http请求。 2.服务端在收到客户端的请求之后,生成一个唯一token,<font color='red'>这里需要将该生成的token存储在服务端</font>,至于怎么存,可以和上面session与cookie的方式一致。也可以存在缓存数据库中,如redis,memcached。3.服务端将该token返回给客户端,客户端存在本地,可以存请求头header中,也可以存在cookie中,同时也可以存在localstorage中。4.向服务端发送请求时,携带该token,服务端进行认证或者授权。<center>(图三)JWT认证模式</center>1.客户端向服务端发送一个http请求。 2.服务端根据jwt的生成规则,生成一个token,并返回给客户端,<font color='red'>这里服务端是不需要存储的</font>。3.客户端在接受到该token时,存在客户端。4.客户端向服务端发送请求时,服务端对请求的token进行解析,如果发现解析出来的数据和生成的数据是一致的代表是一个合法的token,则进行相应的操作。 基于session和cookie的认证和鉴权模式有什么好与不好的地方呢?总结如下几点:通过上面几张图,我们也大致可以看得出来,基于session都是需要服务端存储的,而JWT是不需要服务端来存储的。针对以上几点,总结如下:一、缺点1.容易遇到跨域问题。不同域名下是无法通过session直接来做到认证和鉴权的。2.分布式部署的系统,需要使用共享session机制3.容易出现csrf问题。 二、优点1.方便灵活,服务器端直接创建一个sessionid,下发给客户端,客户端请求携带sessionid即可。2.session存储在服务端,更加安全。3.便于服务端清除session,让用户重新授权一次。 JWT与session有什么区别呢?JWT是基于客户端存储的一种认证方式,然而session是基于服务端存储的一种认证方式。JWT虽然不用服务端存储了,也可以避免跨域、csrf等情况。但也存在如下几个不太好的地方。1.无法清除认证token。由于JWT生成的token都是存储在客户端的,不能有服务端去主动清除,只有直到失效时间到了才能清除。除非服务端的逻辑做了改变。2.存储在客户端,相对服务端,安全性更低一些。当JWT生成的token被破解,我们不便于清除该token。 如何使用JWT这里推荐使用GitHub上面人家封装好的包,这里我使用的是firebase/php-jwt,在项目中直接使用即可安装成功。 composer require firebase/php-jwt接下来创建一个控制器,我这里使用的ThinkPHP5.1的框架 use think\Controller;use Firebase\JWT\JWT;class Test extends Controller{ private $key = 'jwtKey'; // 生成JWT public function createJwt() { $time = time(); $key = $this->key; $token = [ 'iss' => 'https://www.qqdeveloper.com',// 签发人 'exp' => $time + 86400,// 过期时间(这里的有效期时间为1天) 'sub' => '主题内容',// 主题 'aud' => '受众内容',// 受众 'nbf' => $time,// 生效时间 'iat' => $time,// 签发时间 'jti' => 123,// 编号 // 额外自定义的数据 'data' => [ 'userName' => '编程浪子走四方' ]]; // 调用生成加密方法('Payloadn内容','加密的键',['加密算法'],['加密的可以'],['JWT的header头']) $jwt = JWT::encode($token, $key); return json(['data' => $jwt]); } // 解析JWT public function analysisJwt() { try { $key = $this->key; $jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImV4cCI6MTU2ODA5NjE4MCwic3ViIjoiXHU0ZTNiXHU5ODk4XHU1MTg1XHU1YmI5IiwiYXVkIjoiXHU1M2Q3XHU0ZjE3XHU1MTg1XHU1YmI5IiwibmJmIjoxNTY4MDA5NzgwLCJpYXQiOjE1NjgwMDk3ODAsImp0aSI6MTIzLCJkYXRhIjp7InVzZXJOYW1lIjoiXHU3ZjE2XHU3YTBiXHU2ZDZhXHU1YjUwXHU4ZDcwXHU1NmRiXHU2NWI5In19.kHb_9Np0zjE25YE9czUEGvmFPYtqMJT9tuZzJTuMZl0'; // 调用解密方法('JWT内容','解密的键,和加密时的加密键一直','加密算法') $decoded = JWT::decode($jwt, $key, array('HS256')); return json(['message' => $decoded]); } catch (\Exception $exception) { return json(['message' => $exception->getMessage()]); } }}通过访问第一个方法,可以生成下图一段字符串我们将上图中的字符串复制到第二图中的$jwt变量,访问第二个方法即可解析出具体的数据。 ...

September 9, 2019 · 1 min · jiezi

基于URLOS快速安装ZmCMS企业网站系统

关于ZmCMS企业网站ZmCMS企业网站是一款基于THINKPHP 5.1框架打造的企业形象展示系统,是由php+mysql开发的一套专门用于中小企业网站建设的开源cms。 可以用来快速建设一个企业网站( PC,手机,微信都可以访问)。后台操作简单,维护方便。 系统主要特点: 1、可自定义简化URL模块,静态缓存! 2、源代码全开放无加密,可二次扩展开发集成电商系统,微信,小程序等主流平台。 3、自定义模板标签,不懂后端也可调用数据。 安装ZmCMS企业网站系统首先,我们需要安装URLOS: curl -LO www.urlos.com/siu && sh siuURLOS面板安装完成之后,登录面板,在应用市场中搜素“zmcms”,点击安装按钮: 在基本信息项目中填写服务名称、运行节点、端口号: 在网站项目中填写域名: ][4] 在数据库项目中选择数据库,设置数据库密码: 完成以上步骤后,点击提交,等待应用自动部署完成后,在浏览器中输入域名访问页面,如果页面能正常访问,则ZmCMS企业网站系统部署成功。 本文我们介绍了如何使用URLOS快速创建ZmCMS企业网站系统,对URLOS感兴趣的小伙伴不妨体验一下。

July 16, 2019 · 1 min · jiezi

开源vue2和thinkphp搭建的前后端分离项目

大学生论坛采用vue2和thinkphp搭建的前后端分离项目github地址:https://github.com/lll618xxx/... 项目说明本项目为前后端分离项目: 前端采用vue2全家桶(包括vue-router/vuex)搭建,http请求采用axios,组件UI采用element-ui,对象存储采用七牛云(需要自己配置),实现客户端上传图片,目前已完成功能(用户登录注册、用户中心、基于wangeditor 的富文本发布)。 后端采用tninkphp3.2搭建,使用jwt签发token,搭配mysql数据库和Apache服务器 项目使用前端:需要配置后端接口地址 client/src/http/PathConfig.js 安装npm模块 npm install 运行项目 npm run dev后端:我自己采用的是Apache,将整个server目录放到服务器下,我采用的是虚拟域名指向配置API请求地址,至于数据库,可以将vues.sql导入到数据库中,就可以在本地将项目跑起来.

June 24, 2019 · 1 min · jiezi

带你抛出优雅的处理系统异常

关于抛出异常如在我的上一篇文中所说的一样, 在接口的设计中, 接口的返回的数据是非常重要的, 例如无法避免的500等等, 这些都是要命的错误 同时还有一个极大的问题, 就是在新增模块中, 例如我最近需要新增一个 elasticsearh 的分词查询模块, 这个在添加索引删除索引等等操作的时候, 是非常容易导致抛出错误异常的. 按照平常的解决思路, 我们可能首先就是针对异常处理直接进行使用Exception进行捕获,/偷笑, 我在以前的时候也是非常喜欢这么做的 1) try catch (1) 代码案例: public function addIndex($data){ $params = [ 'index' => 'show', 'type' => 'store', 'body' => $data ]; try{ $this->client->index($params); }catch (\Exception $exception) { halt('参数错误的异常'); # 处理错误1 }}在我们初期的学习和开发当前,以上的方法的确是可行的,类似于我们常常说的 JQ一把梭 , 上面的便是 错误一刀切,这种方式的确是能够进行解决问题, 但是非常不利于针对某个错误的处理 例如 BadRequest400Exception 方法抛出的 getMessage() 的结果是json数据, 而 BadMethodCallException 抛出的是字符串数据 你告诉我怎么处理呢? 所以, 衍生了如下的第二种处理错误方式 2) try catch (2) ...

May 13, 2019 · 4 min · jiezi

PHP & MySQL 「数据关联一对一」的最佳实践

前言在开发过程中,通常会遇到很多 一对一 数据的处理情况。而很多时候我们会要取到的是一个列表,然后列表的单条记录的对应另外一张表,来实现业务。比如下面的商品信息 和 商品详情 两个表,这里为了演示只是使用了基础字段,实际开发中可能会复杂的多,下方演示代码中数据库连接使用 PDO 进行处理。表结构goods列类型注释idint(11) 自动增量主键IDtitlevarchar(100)商品名称pricedecimal(10,2)商品价格covervarchar(100)商品封面goods_detail列类型注释idint(11) 自动增量主键IDgoods_idint(11)商品IDcontentvarchar(5000)商品图文介绍初级坦言,无论是在公司,还是在一些开源项目上,我都看到过如下的代码。$query = $db->query(‘select * from goods’);$result = $query->fetchAll();// 方案一foreach($result as $key => $item){ $query = $db->query(‘select * from goods_detail where goods_id=’ . $item[‘id’]); $result[$key][‘goods_detail’] = $query->fetch();}var_dump($result);// 方案二foreach($result as &$item){ $query = $db->query(‘select * from goods_detail where goods_id=’ . $item[‘id’]); $item[‘goods_detail’] = $query->fetch();}unset($item);var_dump($result);// 方案三$result = array_map(function($item){ $query = $db->query(‘select * from goods_detail where goods_id=’ . $item[‘id’]); $item[‘goods_detail’] = $query->fetch(); return $item;},$result);var_dump($result);这是最暴力的方式,也是立杆见影,而且方案一看起来代码貌似还很繁琐,不是吗?如果学过 引用这一节的朋友,应该知道第二种用法,直接用引用去操作源数据,当然最后最好别忘了 unset 掉 $item,除了第二种,我们还可以用第三种方式,使用 array_map,诚然,这和第二种方式没什么区别,但是这其中有着一个非常大的问题:数据库查询的N+1 。从执行中我们就可以看到,除了查询列表的一条 SQL 外,每查询一条记录对应的都需要执行一条 SQL ,导致了额外的查询,想想一下如果查询没有 limit 限制。会是什么样子的情况?进阶看到这里,有人可能会想到了另一种方案来,先查询列表,然后取出列表里面的 goods_id 之后使用 in 查询,然后再循环分配给列表,看代码。$goods_id = array_column($result,‘id’);$goods_id_str = implode(’,’,$goods_id);$query = $db->query(sprintf(‘select * from goods_detail where goods_id in (%s)’,$goods_id_str));$goods_detail_list = $query->fetchAll();foreach($result as &$item){ $item[‘goods_detail’] = array_first($goods_detail_list,function($item1){ return $item[‘id’] == $item1[‘goods_id’]; });}unset($item);var_dump($result);/** * 来自 Laravel /if (!function_exists(‘value’)) { function value($value) { return $value instanceof Closure ? $value() : $value; }}/* * 来自 Laravel /if (!function_exists(‘array_first’)) { /* * @param $array * @param callable|null $callback * @param null $default * @return mixed */ function array_first($array, callable $callback = null, $default = null) { if (is_null($callback)) { if (empty($array)) { return value($default); } foreach ($array as $item) { return $item; } } foreach ($array as $key => $value) { if (call_user_func($callback, $value, $key)) { return $value; } } return value($default); }}在这个代码中,我们完美避开了 N+1 的窘境,使用了in查询,然后遍历数组,再使用 array_first 方法来查找后传递给 goods_detail 索引,虽然这样的效率相比第一次的要高了很多,但是并不完美,接下来来看最后一种方案。关于 array_first 可以看我的另一篇文章 『PHP 多维数组中的 array_find』。最佳实践$goods_detail_list_by_keys = array_column($goods_detail_list,null,‘goods_id’);foreach($result as &$item){ $item[‘goods_detail’] = array_key_exists($goods_detail_list_by_keys,$item[‘id’]) ? $goods_detail_list_by_keys[$item[‘id’]] : null ; // php 7.1+ // $item[‘goods_detail’] = $goods_detail_list_by_keys[$item[‘id’]] ?? null;}unset($item);var_dump($result);这一次,我们用到了其他两个函数。array_column 、 array_key_exists,接下里一一道来,其实在array_column的官方手册中的我们就能 Example #2 中就介绍了我们想要的方法。套用在这里就是重置goods_detail_list 里面元素的 key 为 单个元素下的 goods_id。在后面我们直接用 array_key_exists 判断是否存在,然后做出相应的处理就好了。在这里我们还可以做另外一个操作,那就是默认值,因为有时候,数据有可能会因对不上,如果查出来直接返回给前端,前端没有预料到这种情况没有做容错处理就会导致前端页面崩溃,下面来改写一下代码// 在 「进阶」 板块中,我们用到了 「array_first」 函数,该函数第三个参数可以直接设置默认值,我们就不多讲了,主要讲讲最后一个$goods_detail_default = [ ‘content’ => ‘默认内容’, ‘id’ => null, ‘goods_id’=> null,];foreach($result as &$item){ $tmp = array_key_exists($goods_detail_list_by_keys,$item[‘id’]) ? $goods_detail_list_by_keys[$item[‘id’]] : [] ; // php 7.1+ // $tmp = $goods_detail_list_by_keys[$item[‘id’]] ?? []; $item[‘goods_detail’] = array_merge($goods_detail_default,$tmp);}unset($item);var_dump($result);结束看到这里就算是完结了但是有的朋友会说,为什么不用 leftJoin 来处理?确实,在处理一对一关系中很多时候我们都会选择 innerJoin 或者 leftJoin 来进行处理,一条 SQL 就能搞定,很少会用到类似于这种方案,其实不然,在主流的框架中,默认的解决方案几乎都是这样处理的,比如Laravel、ThinkPHP,考虑到的场景会有很多,比如有的时候我只是需要按需取一部分的,或者我需要根据我后面的业务结果来决定是不是要加载一对一,然而这种情况下 join 似乎就不太适合。 ...

March 30, 2019 · 2 min · jiezi

PHP 多维数组中的 array_find

过渡最近在开始使用 ThinkPHP 5.1 进行一系列开发工作,因为之前是使用 Laravel 进行开发,像是标题中的这种小问题都在 Laravel 中很容易实现。直接使用 array_first 方法进行查找即可。快速实现但是在 ThinkPHP 中 并没有提供类似方法进行快速处理,所以有需要来重复造轮子了?至此想到的第一个方法就是使用 array_search 不过这个方法中官方提供的方案仅用于简单的一维数组搜索,而且返回的也只是 index 并不是找到的结果,淡然通过 index 我们也可以取出项目来,在 PHP 5.5 带来的新方法 array_column,可以方便的实现二维搜索 在这里的用户笔记 为我们提供了一个小的示例。$userdb=Array( (0) => Array ( (uid) => ‘100’, (name) => ‘Sandra Shush’, (url) => ‘urlof100’ ), (1) => Array ( (uid) => ‘5465’, (name) => ‘Stefanie Mcmohn’, (pic_square) => ‘urlof100’ ), (2) => Array ( (uid) => ‘40489’, (name) => ‘Michael’, (pic_square) => ‘urlof40489’ ));$key = array_search(40489, array_column($userdb, ‘uid’));并且赢得了 800+ 的赞赏,到这里可能你会觉得 通过这个方式取到 index 然后用 index 取出来就行了。一些????但是,如果你再往下翻一下,你会看到另一条用户笔记 ,这条用户笔记告诉我们 当我们使用这种方式来实现二维搜索时你 PHP 版本 必须要在 5.5 + ,作者同时告诉我们Since array_column() will produce a resulting array; it won’t preserve your multi-dimentional array’s keys. So if you check against your keys, it will fail.机翻一下 :由于array_column()将产生一个新的数组; 它不会保留多维数组的原来的键。 因此,如果您检查您的键,它将失败。然后作者也为我们提供了一个????$people = array( 2 => array( ’name’ => ‘John’, ‘fav_color’ => ‘green’ ), 5 => array( ’name’ => ‘Samuel’, ‘fav_color’ => ‘blue’ ));$found_key = array_search(‘blue’, array_column($people, ‘fav_color’)); // 1// Here, you could expect that the $found_key would be “5” but it’s NOT. It will be 1. Since it’s the second element of the produced array by the array_column() function.// 机翻一下:在这里,你预期 $found_key 的将是“5”,但它不是,它将是1.因为它是array_column()函数生成的数组的第二个元素。// 另外 作者还提到了// Secondly, if your array is big, I would recommend you to first assign a new variable so that it wouldn’t call array_column() for each element it searches. For a better performance, you could do;// 机翻一下:其次,如果您的数组很大,我建议您先分配一个新变量,这样它就不会为它搜索的每个元素调用array_column()。 为了获得更好的性能,你可以做到;$colors = array_column($people, ‘fav_color’);$found_key = array_search(‘blue’, $colors);看完了这些提示,你已经发现了这其中的坑,然而,这并没有结束,因为如果数据不够纯净的话,你用 array_search 实现的功能可能就只局限于 in_array 。而且,尽管到了这里,还会遇到另外一个坑,先看????<?php $userdb = array( 0 => array( ‘uid’ => 100, ’name’ => ‘Sandra Shush’, ‘url’ => ‘urlof100’ ), ‘8’ => array( ‘uid’ => 5465, ’name’ => ‘Stefanie Mcmohn’, ‘pic_square’ => ‘urlof100’ ), ‘3’ => Array( // ‘uid’ => 5555, ’name’ => ‘Michael’, ‘pic_square’ => ‘urlof40489’ ), ‘6’ => Array( ‘uid’ => 40489, ’name’ => ‘Michael’, ‘pic_square’ => ‘urlof40489’ )); $found_key = array_search(40489, array_column($userdb, ‘uid’));在这里 猜想一下 $found_key 会是什么?答案是: 2。??? ,因为当在执行 array_column() 时,第三个元素,也就是键为3的数据中 uid 被注释了,这时候 PHP 就会忽略它,并不会被保留索引位置,所以这时候结果只有 3 个元素,第四个向上替补了,因为数组索引是 0 开始,所以 2 就相当于第 3 个元素了。大家都是怎么做的?在 array_search 的用户笔记区中,看到了很多都是数组循环并比对后返回,比如这个,但是这样又遇到一些局限性问题,这时候我们又想到了 Laravel 中把自主权交给调用者,由调用者在匿名方法内进行处理并返回 bool 值 进行处理。至此,看回 Laravel 的 array_fisrt 方法,通过 Laravel 源码可以看到 array_first 是 Arr::fisrt 方法的一个包装,在这里我们可以看到 Laravel 的实现方式,在这一小段代码中 还看到了另一个方法 value(),可以看到,这个方法就是判断是否是一个匿名方法,如果是就执行方法并返回,不是就直接返回。public static function first($array, callable $callback = null, $default = null) { if (is_null($callback)) { if (empty($array)) { return value($default); } foreach ($array as $item) { return $item; } } foreach ($array as $key => $value) { if (call_user_func($callback, $value, $key)) { return $value; } } return value($default); }if (! function_exists(‘value’)) { /** * Return the default value of the given value. * * @param mixed $value * @return mixed */ function value($value) { return $value instanceof Closure ? $value() : $value; }}看到这里,几乎是比较完整的实现,在这里还想到了另外一个和助手函数有关的项目:Underscore.php这是一个 PHP 的方法库,也可以算是是 JS中的 underscore.js和 loadsh、ramda 的 PHP 实现。在这个项目中我们看到了实现方式public static function find($array, Closure $closure) { foreach ($array as $key => $value) { if ($closure($value, $key)) { return $value; } } return; }这里的实现更为简单,最终也实现了我们想要的结果。 ...

March 13, 2019 · 3 min · jiezi

实现一个简单的di容器

之前看了好多框架,laravel,thinkphp,yii等等。基本上都使用了容器。对于我而言,虽然看懂了laravel是怎么写的,但是如果自己不去尝试一下,始终觉得不会这个东西。下面的代码是我实现的一个简单的容器,很多地方处理并不是很好,但是应该已经足够了。<?phpclass Container{ //$binds 这个变量保存,是名字=>实例的映射 private $binds = []; public static $instance = null; /** * 单例 / public static function getInstance(){ if(static::$instance == null){ static::$instance = new static(); return static::$instance ; } return static::$instance; } /* * 一开始是受到laravel的影响,所以写了一个bind函数, * 看完laravel的容器实现,印象之中,$concrete和$abstract来回变换。 * 下面的代码有点像thinkphp的里面的实现,好理解一点 / public static function bind($name,$class = null){ if($class instanceof Closure){ static::getInstance()->binds[$name] = $class; }else if(is_object($class)){ static::getInstance()->binds[$name] = $class; }else{ //在这里开始make一个数组,laravel好像是make和build分开的。 static::getInstance()->make($name); } } /* * 核心是make方法了 / public static function get($name){ return static::getInstance()->make($name); } /* * 核心make方法 */ public function make($name){ try{ //根据类名去查找$this->binds实例是否已经存在,如果存在就直接返回 if(array_key_exists($name,$this->binds)){ return $this->binds[$name]; } //根据类名得到它的反射类 $reflectClass = new ReflectionClass($name); //利用反射类 $constructor = $reflectClass->getConstructor(); //如果没有构造器的话,就直接去实例化它 $params = []; if(!is_null($constructor)){ //获取构造器中的方法 $constructorParams = $constructor->getParameters(); // var_dump($constructorParams); //保存构造器的参数 foreach($constructorParams as $constructorParam){ //这个地方主要是判断参数是否是类,如果是就递归的构造它,不是就简单的添加到$this->params中 if(!is_null($constructorParam->getType())){ $params[] =$this->make($constructorParam->name,$constructorParam->name); }else{ $params[] = $constructorParam->name; } } } //在这个地方构造实例 $class = $reflectClass->newInstanceArgs($params); //绑定 $this->binds[$name] = $class; return $class; }catch(ReflectionException $e){ echo $e->getMessage(); } } private function __construct(){} private function __clone(){}}?>下面是我的测试文件了,<?phprequire “./Container.php”;class TestFather{ private $name = “TestFather”; public function __construct(){ }}class Test extends TestFather{ private $name = “Test”; // public function __construct(DI $di, DI2 $di2,$name){ // } public function __construct(DI $di,$name,$param_2 =[]){ } public function sayName(){ echo $this->name; } public function sayDI2Name(DI2 $di2){ //如果这么写的,di2方法会先于前面的字符串打印出来 // echo “form Test say di2 name: “.$di2->sayName(); echo “form Test say di2 name: “; echo $di2->sayName(); }}class DI{ private $name = “DI”; public function __construct(DI2 $di2){} public function sayName(){ echo $this->name; } }class DI2{ private $name = “DI2”; public function __construct(){} public function sayName(){ echo $this->name; } }class DI3{ private $name = “DI3”; public function __construct(){} public function sayName(){ echo $this->name; } }class DI4{ private $name = “DI4”; public function __construct(){} public function sayName(){ echo $this->name; } }//要不要无所谓了// Container::bind(’test’,‘Test’); $test = Container::get(’test’);$test->sayName();echo “\n”;$test->sayDI2Name(new DI2());echo “\n”;$di = Container::get(‘di’);$di->sayName();echo “\n”;$di2 = Container::get(‘di2’);$di2->sayName();echo “\n”;$di3 = new DI3();Container::get(‘di3’,$di3)->sayName();echo “\n”;$di4 = function(){ return new DI4();};Container::get(‘di4’,$di4)->sayName();echo “\n”;?>最后的结果如下 ...

March 6, 2019 · 2 min · jiezi

thinkphp源码分析(五)—配置篇

源码分析—入口篇源码分析全局配置加载类全局配置类的主要代码如下:class Config{ /** * @var array 配置参数 / private static $config = []; /* * @var string 参数作用域 / private static $range = ‘sys’; /* * 设定配置参数的作用域 * @access public * @param string $range 作用域 * @return void / public static function range($range) { …. } /* * 解析配置文件或内容 * @access public * @param string $config 配置文件路径或内容 * @param string $type 配置解析类型 * @param string $name 配置名(如设置即表示二级配置) * @param string $range 作用域 * @return mixed / public static function parse($config, $type = ‘’, $name = ‘’, $range = ‘’) { …. } /* * 加载配置文件(PHP格式) * @access public * @param string $file 配置文件名 * @param string $name 配置名(如设置即表示二级配置) * @param string $range 作用域 * @return mixed / public static function load($file, $name = ‘’, $range = ‘’) { …. } /* * 检测配置是否存在 * @access public * @param string $name 配置参数名(支持二级配置 . 号分割) * @param string $range 作用域 * @return bool / public static function has($name, $range = ‘’) { …. } /* * 获取配置参数 为空则获取所有配置 * @access public * @param string $name 配置参数名(支持二级配置 . 号分割) * @param string $range 作用域 * @return mixed / public static function get($name = null, $range = ‘’) { …. } /* * 设置配置参数 name 为数组则为批量设置 * @access public * @param string|array $name 配置参数名(支持二级配置 . 号分割) * @param mixed $value 配置值 * @param string $range 作用域 * @return mixed / public static function set($name, $value = null, $range = ‘’) { …. } /* * 重置配置参数 * @access public * @param string $range 作用域 * @return void / public static function reset($range = ‘’) { …. }}添加配置添加配置用的是thinkConfig::set($name, $value = null, $range = ‘’)方法;当$name是字符串时候value是要设置的值,$name为数组时候,批量设置配置。 /* * 设置配置参数 name 为数组则为批量设置 * @access public * @param string|array $name 配置参数名(支持二级配置 . 号分割) * @param mixed $value 配置值 * @param string $range 作用域 * @return mixed / public static function set($name, $value = null, $range = ‘’) { $range = $range ?: self::$range; if (!isset(self::$config[$range])) self::$config[$range] = []; // 字符串则表示单个配置设置 if (is_string($name)) { if (!strpos($name, ‘.’)) { self::$config[$range][strtolower($name)] = $value; } else { // 二维数组 $name = explode(’.’, $name, 2); self::$config[$range][strtolower($name[0])][$name[1]] = $value; } return $value; } // 数组则表示批量设置 if (is_array($name)) { if (!empty($value)) { self::$config[$range][$value] = isset(self::$config[$range][$value]) ? array_merge(self::$config[$range][$value], $name) : $name; return self::$config[$range][$value]; } return self::$config[$range] = array_merge( self::$config[$range], array_change_key_case($name) ); } // 为空直接返回已有配置 return self::$config[$range]; }设置配置时候主要分了两种情况:1. $name是字符串2. $name是二维数组(目前只支持二维数组)配置会先判断配置的作用域,不设置就用默认的_sys_作用域,并且判断该作用域是否存在,不存在就初始化为数组。对于$name这两种不同形式的参数,处理方式也不一样,$name为字符串形式 // 字符串则表示单个配置设置 if (is_string($name)) { if (!strpos($name, ‘.’)) { self::$config[$range][strtolower($name)] = $value; } else { // 二维数组 $name = explode(’.’, $name, 2); self::$config[$range][strtolower($name[0])][$name[1]] = $value; } return $value; }判断字符串中是否带., 没有直接把$name的小写形式作为key,$value作为值设置到配置(self::$config)中.如果带.,只处理前面两项,即把字符串通过.分割成数组,取数组的前面两项,把$value设置到配置中。$name为数组形式 // 数组则表示批量设置 if (is_array($name)) { if (!empty($value)) { self::$config[$range][$value] = isset(self::$config[$range][$value]) ? array_merge(self::$config[$range][$value], $name) : $name; return self::$config[$range][$value]; } return self::$config[$range] = array_merge( self::$config[$range], array_change_key_case($name) ); }如果设置了$value的值,那么把$value作为配置的键,再把$name的配置设置到配置中(如果原来已经有值,数组合并用传入的值替换原来的值,如果原来没有值,直接赋值),如果没有设置$value的值,那么把数组的每一项设置到该作用域下。备注: array_change_key_case( $array, [ int $case = CASE_LOWER ] ) : array 把数组的键设置为大写或小写,默认是小写。获取配置看完了上面的分析,对于获取配置应该也有了一个大致的思路了,就是设置配置的反向。 /* * 获取配置参数 为空则获取所有配置 * @access public * @param string $name 配置参数名(支持二级配置 . 号分割) * @param string $range 作用域 * @return mixed / public static function get($name = null, $range = ‘’) { $range = $range ?: self::$range; // 无参数时获取所有 if (empty($name) && isset(self::$config[$range])) { return self::$config[$range]; } // 非二级配置时直接返回 if (!strpos($name, ‘.’)) { $name = strtolower($name); return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null; } // 二维数组设置和获取支持 $name = explode(’.’, $name, 2); $name[0] = strtolower($name[0]); if (!isset(self::$config[$range][$name[0]])) { // 动态载入额外配置 $module = Request::instance()->module(); $file = CONF_PATH . ($module ? $module . DS : ‘’) . ’extra’ . DS . $name[0] . CONF_EXT; is_file($file) && self::load($file, $name[0]); } return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null; }看了代码,应该对于无参获取和非二级获取已经懂了,那二维数组有个需要注意的地方,就是会动态加载额外的配置。$module = Request::instance()->module();该方法的实现如下: /* * 设置或者获取当前的模块名 * @access public * @param string $module 模块名 * @return string|Request / public function module($module = null) { if (!is_null($module)) { $this->module = $module; return $this; } else { return $this->module ?: ‘’; } }该方法就是获取当前请求的模块。 //二维数组处理逻辑 if (!isset(self::$config[$range][$name[0]])) { // 动态载入额外配置 $module = Request::instance()->module(); $file = CONF_PATH . ($module ? $module . DS : ‘’) . ’extra’ . DS . $name[0] . CONF_EXT; is_file($file) && self::load($file, $name[0]); } return isset(self::$config[$range][$name[0]][$name[1]]) ? self::$config[$range][$name[0]][$name[1]] : null;从代码中可以看出,通过request获取到当前访问的模块,判断当前模块中的或者配置目录中的extra目录总是否存在以为数组中键为名字的配置文件,存在就加载进来,再进行返回,动态加载通过thinkConfig::load($file)来进行加载。 /* * 加载配置文件(PHP格式) * @access public * @param string $file 配置文件名 * @param string $name 配置名(如设置即表示二级配置) * @param string $range 作用域 * @return mixed / public static function load($file, $name = ‘’, $range = ‘’) { $range = $range ?: self::$range; if (!isset(self::$config[$range])) self::$config[$range] = []; if (is_file($file)) { $name = strtolower($name); $type = pathinfo($file, PATHINFO_EXTENSION); if (‘php’ == $type) { return self::set(include $file, $name, $range); } if (‘yaml’ == $type && function_exists(‘yaml_parse_file’)) { return self::set(yaml_parse_file($file), $name, $range); } return self::parse($file, $type, $name, $range); } return self::$config[$range]; }该加载配置的方法主要的逻辑是处理php,yaml,ini,json,xml格式的配置。php类型的是直接include再set配置即可,yaml则是通过yaml_parse_file方法解析成数据再set配置。其他的通过固定的驱动来解析,业务逻辑再thinkConfig::parse()方法中。 /* * 解析配置文件或内容 * @access public * @param string $config 配置文件路径或内容 * @param string $type 配置解析类型 * @param string $name 配置名(如设置即表示二级配置) * @param string $range 作用域 * @return mixed */ public static function parse($config, $type = ‘’, $name = ‘’, $range = ‘’) { $range = $range ?: self::$range; if (empty($type)) $type = pathinfo($config, PATHINFO_EXTENSION); $class = false !== strpos($type, ‘\’) ? $type : ‘\think\config\driver\’ . ucwords($type); return self::set((new $class())->parse($config), $name, $range); }通过pathinfo()方法获取到路径信息, 第二个参数设置返回扩展名,判断扩展名中是否带有\如果有即传入的是一个类。直接通过类的parse方法解析配置,如果是一个文件扩展名称,即通过\think\config\driver\下对应的驱动来解析配置,再set到配置中。总结thinkphp中主要的配置加载方式有两种,1.加载框架内部预设的配置2.动态加载用户配置对于第一中方式,由于默认的配置是php类型的,是直接通过set方法执行配置的,第二中方式是通过load方法,判断文件的扩展名来进行不同的驱动解析,其中php和yaml有直接的方式可以解析成数组,xml,json,ini则是通过对应的驱动来解析再set配置的,通过调用parse方法自动判断扩展,再进行解析。至于Config类中其他的方法比较简单,可以直接查看代码获取相关信息。 ...

February 23, 2019 · 4 min · jiezi

后端_PHP

PHPPHP是超文本预处理语言,一种开源的通用计算机基本语言,尤其适用于网络开发可嵌入式HTML中使用。

February 23, 2019 · 1 min · jiezi

源码分析(四)—错误及异常处理篇

源码分析错误及异常处理机制错误及异常处理机制文件是/thinkphp/library/think/Error.php,在框架引导文件的的基础文件base.php中注册(不知道的可以去看《《源码分析(二)—入口篇》》),通过thinkError::register()进行的注册。 /** * 注册异常处理 * @access public * @return void / public static function register() { error_reporting(E_ALL); set_error_handler([CLASS, ‘appError’]); set_exception_handler([CLASS, ‘appException’]); register_shutdown_function([CLASS, ‘appShutdown’]); }该方法做了四件事情:设置报错级别 E_ALL为E_STRICT所有报错。设置错误处理函数,set_error_handler([CLASS, ‘appError’])设置异常处理函数,set_exception_handler([CLASS, ‘appException’]);设置程序异常终止处理函数,register_shutdown_function([CLASS, ‘appShutdown’]);PHP报错级别php的报错级别有:E_STRICT,E_ALL, E_USER_WARNING等,具体可查看[php预定义常量](http://php.net/manual/zh/erro…。错误处理函数thinkphp中注册了thinkError::appError()方法对错误进行处理。 /* * 错误处理 * @access public * @param integer $errno 错误编号 * @param integer $errstr 详细错误信息 * @param string $errfile 出错的文件 * @param integer $errline 出错行号 * @return void * @throws ErrorException / public static function appError($errno, $errstr, $errfile = ‘’, $errline = 0) { $exception = new ErrorException($errno, $errstr, $errfile, $errline); // 符合异常处理的则将错误信息托管至 think\exception\ErrorException if (error_reporting() & $errno) { throw $exception; } self::getExceptionHandler()->report($exception); }在appError方法中,把符合异常处理的则将错误信息托管至系统的ErrorException,其他的异常通过thinkexceptionHandle进行处理。//think\exception\ErrorException文件/* * ThinkPHP错误异常 * 主要用于封装 set_error_handler 和 register_shutdown_function 得到的错误 * 除开从 think\Exception 继承的功能 * 其他和PHP系统\ErrorException功能基本一样 /class ErrorException extends Exception{ /* * 用于保存错误级别 * @var integer / protected $severity; /* * 错误异常构造函数 * @param integer $severity 错误级别 * @param string $message 错误详细信息 * @param string $file 出错文件路径 * @param integer $line 出错行号 * @param array $context 错误上下文,会包含错误触发处作用域内所有变量的数组 / public function __construct($severity, $message, $file, $line, array $context = []) { $this->severity = $severity; $this->message = $message; $this->file = $file; $this->line = $line; $this->code = 0; empty($context) || $this->setData(‘Error Context’, $context); } /* * 获取错误级别 * @return integer 错误级别 / final public function getSeverity() { return $this->severity; }}errorException设置错误级别,错误信息,出错文件路径,行号,上下文。对exception进行处理的是thinkexceptionHandle的report()方法:self::getExceptionHandler()->report($exception); //self::getExceptionHandler() /* * 获取异常处理的实例 * @access public * @return Handle / public static function getExceptionHandler() { static $handle; if (!$handle) { // 异常处理 handle $class = Config::get(’exception_handle’); if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, “\think\exception\Handle”) ) { $handle = new $class; } else { $handle = new Handle; if ($class instanceof \Closure) { $handle->setRender($class); } } } return $handle; }这里有一个关键的地方是:static $handle; 声明该变量是静态变量时候,当赋值给该变量后,函数调用结束后不会销毁,直到脚本结束才会销毁。这个逻辑就是判断$handle是否已经赋值,没有赋值,获取默认配置文件是否设置处理handle,如果设置,这个handle必须是\think\exception\Handle的子类(is_subclass_of($class, “\think\exception\Handle”)),如果没有设置,那么用默认的thinkexceptionHandle调用report方法进行处理, 记录到日志文件中。 /* * Report or log an exception. * * @param \Exception $exception * @return void / public function report(Exception $exception) { if (!$this->isIgnoreReport($exception)) { // 收集异常数据 if (App::$debug) { $data = [ ‘file’ => $exception->getFile(), ’line’ => $exception->getLine(), ‘message’ => $this->getMessage($exception), ‘code’ => $this->getCode($exception), ]; $log = “[{$data[‘code’]}]{$data[‘message’]}[{$data[‘file’]}:{$data[’line’]}]”; } else { $data = [ ‘code’ => $this->getCode($exception), ‘message’ => $this->getMessage($exception), ]; $log = “[{$data[‘code’]}]{$data[‘message’]}”; } if (Config::get(‘record_trace’)) { $log .= “\r\n” . $exception->getTraceAsString(); } Log::record($log, ’error’); } }把errorException的数据组装成对应的字符串,写入日志。异常处理函数thinkphp中注册了thinkError::appException()方法对错误进行处理。 /* * 异常处理 * @access public * @param \Exception|\Throwable $e 异常 * @return void / public static function appException($e) { if (!$e instanceof \Exception) { $e = new ThrowableError($e); } $handler = self::getExceptionHandler(); $handler->report($e); if (IS_CLI) { $handler->renderForConsole(new ConsoleOutput, $e); } else { $handler->render($e)->send(); } }方法和appError处理差不多,基本都是通过获取ExceptionHandle再调用handle的report方法,但是多了一步把异常呈现,如果是命令行写到命令行输出,如果是web的就把错误信息通过reponse响应返回客户端。异常中止时执行的函数thinkphp中注册了thinkError::appShutdown()方法对错误进行处理。 /* * 异常中止处理 * @access public * @return void */ public static function appShutdown() { // 将错误信息托管至 think\ErrorException if (!is_null($error = error_get_last()) && self::isFatal($error[’type’])) { self::appException(new ErrorException( $error[’type’], $error[‘message’], $error[‘file’], $error[’line’] )); } // 写入日志 Log::save(); }通过error_get_last()获取最后抛出的错误,把信息托管至thinkErrorException,在通过异常处理函数进行记录信息。最后写入日志。总结整体整个错误处理机制都是通过获取ExceptionHandle再调用handle的report方法,但是多了一步把异常呈现,如果是命令行写到命令行输出,如果是web的就把错误信息通过reponse响应返回客户端。默认的处理handle是thinkexceptionHandle,当然也可以自定义handle,但是必须是thinkexceptionHandle的子类, 通过self::getExceptionHandler的is_subclass_of($class, “\think\exception\Handle”)可以知。 ...

February 22, 2019 · 2 min · jiezi

源码分析(三)—自动加载篇(Loader的分析)

源码分析自动加载系统会调用 Loader::register()方法注册自动加载,在这一步完成后,所有符合规范的类库(包括Composer依赖加载的第三方类库)都将自动加载。系统的自动加载由下面主要部分组成:1. 注册系统的自动加载方法 \think\Loader::autoload2. 注册系统命名空间定义3. 加载类库映射文件(如果存在)4. 如果存在Composer安装,则注册Composer自动加载5. 注册extend扩展目录一个类库的自动加载检测顺序为:1. 是否定义类库映射;2. PSR-4自动加载检测;3. PSR-0自动加载检测;4. 可以看到,定义类库映射的方式是最高效的。源码 /** * 注册自动加载机制 * @access public * @param callable $autoload 自动加载处理方法 * @return void / public static function register($autoload = null) { // 注册系统自动加载 spl_autoload_register($autoload ?: ’think\Loader::autoload’, true, true); // Composer 自动加载支持 if (is_dir(VENDOR_PATH . ‘composer’)) { if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . ‘composer’ . DS . ‘autoload_static.php’)) { require VENDOR_PATH . ‘composer’ . DS . ‘autoload_static.php’; $declaredClass = get_declared_classes(); $composerClass = array_pop($declaredClass); foreach ([‘prefixLengthsPsr4’, ‘prefixDirsPsr4’, ‘fallbackDirsPsr4’, ‘prefixesPsr0’, ‘fallbackDirsPsr0’, ‘classMap’, ‘files’] as $attr) { if (property_exists($composerClass, $attr)) { self::${$attr} = $composerClass::${$attr}; } } } else { self::registerComposerLoader(); } } // 注册命名空间定义 self::addNamespace([ ’think’ => LIB_PATH . ’think’ . DS, ‘behavior’ => LIB_PATH . ‘behavior’ . DS, ’traits’ => LIB_PATH . ’traits’ . DS, ]); // 加载类库映射文件 if (is_file(RUNTIME_PATH . ‘classmap’ . EXT)) { self::addClassMap(__include_file(RUNTIME_PATH . ‘classmap’ . EXT)); } self::loadComposerAutoloadFiles(); // 自动加载 extend 目录 self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS); }框架自动加载 /* * 自动加载 * @access public * @param string $class 类名 * @return bool / public static function autoload($class) { // 检测命名空间别名 if (!empty(self::$namespaceAlias)) { $namespace = dirname($class); if (isset(self::$namespaceAlias[$namespace])) { $original = self::$namespaceAlias[$namespace] . ‘\’ . basename($class); if (class_exists($original)) { return class_alias($original, $class, false); } } } if ($file = self::findFile($class)) { // 非 Win 环境不严格区分大小写 if (!IS_WIN || pathinfo($file, PATHINFO_FILENAME) == pathinfo(realpath($file), PATHINFO_FILENAME)) { __include_file($file); return true; } } return false; }检测命名空间别名检查是否添加了命名空间别名,通过别名寻找原命名空间。如://原\App\Http\Controller\Index::class//添加别名后\Controller\Index::classthinkphp通过 thinkLoader::addNamespaceAlias($namespace, $original) 添加命名空间别名。 //位置在thinkphp/library/think/Loader.php的260行 /* * 注册命名空间别名 * @access public * @param array|string $namespace 命名空间 * @param string $original 源文件 * @return void / public static function addNamespaceAlias($namespace, $original = ‘’) { if (is_array($namespace)) { self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace); } else { self::$namespaceAlias[$namespace] = $original; } } 通过键为别名,值为原命名空间的数组,注册到thinkLoader::$namespaceAlias的属性。通过classmap,psr-4,psr-0查找文件/* * 查找文件 * @access private * @param string $class 类名 * @return bool|string / private static function findFile($class) { // 类库映射 if (!empty(self::$classMap[$class])) { return self::$classMap[$class]; } // 查找 PSR-4 $logicalPathPsr4 = strtr($class, ‘\’, DS) . EXT; $first = $class[0]; if (isset(self::$prefixLengthsPsr4[$first])) { foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach (self::$prefixDirsPsr4[$prefix] as $dir) { if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) { return $file; } } } } } // 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) { return $file; } } // 查找 PSR-0 if (false !== $pos = strrpos($class, ‘\’)) { // namespace class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), ‘’, DS); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, ‘’, DS) . EXT; } if (isset(self::$prefixesPsr0[$first])) { foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) { if (0 === strpos($class, $prefix)) { foreach ($dirs as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } } } } // 查找 PSR-0 fallback dirs foreach (self::$fallbackDirsPsr0 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } // 找不到则设置映射为 false 并返回 return self::$classMap[$class] = false; }thinkphp添加的自动加载是通过psr-4和classmap进行加载,方法分别是: thinkLoader::addClassMap($class, $map = ‘’) 和 thinkLoader::addNamespace($namespace, $path = ‘’)。psr-4的加载方式是通过命名空间的首字母,查找对应的命名空间,再通过对应的命名空间拼接对应的文件目录,判断该文件是否存在,如果存在就加载文件,实现类的自动加载。classmap的加载方式是通过composer du生成对应的类映射,通过直接查找class对应的文件,从而实现自动加载。其他的加载方式需要深入了解的可以自行研究代码。/* * 注册自动加载机制 * @access public * @param callable $autoload 自动加载处理方法 * @return void / public static function register($autoload = null) { …. // 注册命名空间定义 self::addNamespace([ ’think’ => LIB_PATH . ’think’ . DS, ‘behavior’ => LIB_PATH . ‘behavior’ . DS, ’traits’ => LIB_PATH . ’traits’ . DS, ]); // 加载类库映射文件 if (is_file(RUNTIME_PATH . ‘classmap’ . EXT)) { self::addClassMap(__include_file(RUNTIME_PATH . ‘classmap’ . EXT)); } …. }composer自动加载thinkphp中的composer自动加载不是通过composer自带的autoload.php进行自动加载的。是通过加载对应的psr文件进行注册加载的。 /* * 注册自动加载机制 * @access public * @param callable $autoload 自动加载处理方法 * @return void */ public static function register($autoload = null) { …. // Composer 自动加载支持 if (is_dir(VENDOR_PATH . ‘composer’)) { if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . ‘composer’ . DS . ‘autoload_static.php’)) { require VENDOR_PATH . ‘composer’ . DS . ‘autoload_static.php’; $declaredClass = get_declared_classes(); $composerClass = array_pop($declaredClass); foreach ([‘prefixLengthsPsr4’, ‘prefixDirsPsr4’, ‘fallbackDirsPsr4’, ‘prefixesPsr0’, ‘fallbackDirsPsr0’, ‘classMap’, ‘files’] as $attr) { if (property_exists($composerClass, $attr)) { self::${$attr} = $composerClass::${$attr}; } } } else { self::registerComposerLoader(); } } …. } ...

February 21, 2019 · 4 min · jiezi

源码分析(二)—入口篇

源码分析—入口篇源码分析应用入口用户发起的请求都会经过应用的入口文件,通常是 ==public/index.php==文件。当然,你也可以更改或者增加新的入口文件。通常入口文件的代码都比较简单,一个普通的入口文件代码如下:// 应用入口文件// 定义项目路径define(‘APP_PATH’, DIR . ‘/../application/’);// 加载框架引导文件require DIR . ‘/../thinkphp/start.php’;一般入口文件以定义一些常量为主,支持的常量请参考后续的内容或者附录部分。通常,我们不建议在应用入口文件中加入过多的代码,尤其是和业务逻辑相关的代码。加载引导文件// ThinkPHP 引导文件// 1. 加载基础文件require DIR . ‘/base.php’;// 2. 执行应用App::run()->send();加载基础文件// DIR . ‘/base.php’文件//定义常量define(‘THINK_VERSION’, ‘5.0.24’);….//常量太多省略了部分// 载入Loader类require CORE_PATH . ‘Loader.php’;// 加载环境变量配置文件if (is_file(ROOT_PATH . ‘.env’)) { $env = parse_ini_file(ROOT_PATH . ‘.env’, true); foreach ($env as $key => $val) { $name = ENV_PREFIX . strtoupper($key); if (is_array($val)) { foreach ($val as $k => $v) { $item = $name . ‘_’ . strtoupper($k); putenv("$item=$v"); } } else { putenv("$name=$val"); } }}// 注册自动加载\think\Loader::register();// 注册错误和异常处理机制\think\Error::register();// 加载惯例配置文件\think\Config::set(include THINK_PATH . ‘convention’ . EXT);该部分主要是定义一些系统常量,关键点是引入了自动加载类并且注册了自动加载,使得框架可以自动引入类文件,业务层只要直接use对应命名空间的类即可进行实例化,注册错误及异常处理机制, 加载默认配置等操作。最后就是应用启动,App::run()->send(); ...

February 21, 2019 · 1 min · jiezi

后端_PHP

<!DOCTYPE html><html lang=“en”><head><meta charset=“UTF-8”><title>TPHP7.30</title></head><body> <h3>变量</h3> <p>变量是一个唯一值,用于储存值的.声明的变量都会储存在服务器的内存里.变量名的命名规则必须已字母或下划线“_“开头且区别大小写。 变量有几种数据类型:字符串类型,整型,浮点型,数组 PHP支持八种数据类型,包括四种标量类型,两种符合类型和两种特殊类型。 布尔类型(boolean):只有两个值,一个True,另一个是False,不区分大小写. 整型:可以用十进制,八进制,十六进制指定, 浮点型:小数,使用科学计数法可以使用小写e. 字符串是由一系列字符组成,可以使用单引号形式,双引号形式,Heredoc结构形式.在双引号中包含变量时,变量会与双引号中的内容链接在一起.在单引号时,变量会被当做字符串输出. 资源是由专门的函数来建立和使用的,可以对资源进行操作. NULL是空类型,对大小写不敏感,NULL类型只有一个值,表示一个变量没有值,当被赋值为NULL,或者尚未被赋值,或者被unset(),这三种情况被认为NULL.</p><h3>常量</h3> <p>常量是定义之后不可改变的量,分为两种,自定义define()和系统常量.自定义的格式define(name,value,true/false).常见的系统常量有: FILE 获取当前文件在服务器的物理位置 LINE 查看当前代码在第几行 PHP_VERSION 解析解析器的版本号 PHP_OS 查看系统的名称</p><h3>运算符</h3> <p>算术运算符,赋值运算符,比较运算符,逻辑运算符,三元运算符,字符串连接运算符,错误控制运算符,算术运算符. 算术运算符: + - * / % 比较运算符: == === != <> !== < > <== >== 三元运算符: ? : 逻辑运算符: and or xor ! && || 连接运算符: . .= 错误控制运算符: @</p> <h3>结构语句</h3> <p>所有的程序都是有条件结构,循环结构,顺序结构组成.</p> <p> if(条件) {}else{} if(条件){} elseif{} if(条件){}else if(条件二){}else{} switch(条件){break;} switch(条件) { case1: ; case2: ;} while(条件) {} do {}while(条件) for(){}</p> <h3>数组</h3> <p>PHP的数组是一个关键字和值的集合,PHP的数组有两种,索引数组和关联数组.索引数组是数组的键是整数的组,顺序是从0开始.关联数组是数组的键是字符串的数组.</p> <h3>类与面向对象</h3> <p>类是一类东西的结构描述,对象是一类东西的一个具体实例.在类中定义的变量称之为属性. public:公开的 protected:受保护的 private:私有的 方法就是function 在面向过程的程序设计中function叫做函数 在面向对象中function则被称为方法 使用_construct()定义一个构造函数 静态属性与方法可以不在实例化类的情况下调用。直接使用类名::方法名的方式进行调用 _set _get _isset _unset来分别实现对不存在属性的赋值,读取,判断属性是否设置,销毁属性。</p> <h3>正则表达式</h3> <p>正则表达式是对字符串进行操作的一种逻辑表达式,使用一些特殊的字符组成一个规则的字符串,称之为正则表达式。</p> <h3>会话控制</h3> <p>Cookie是储存在客户端浏览器中的数据,一般情况下,Cookie通过HTTP headers从服务器返回到客户端,Cookie具有有效期,结束之后自动删除。 PHP设置Cookie最常用的方法就是setcookie函数,setcookie具有七个可选参数。name(cookie名)可以通过$_COOKIE[’name’]进行访问 value(cookie值) expire(过期时间) path(有效路径) domain(有效域)默认整个域名都有效。 Session是将用户的会话数据存储到服务端,没有大小限制,通过一个session_id进行用户识别。</p> <h3>文件系统</h3> <P>PHP文件系统之读取文件内容,判断文件是否存在,取得文件的修改时间,取得文件的大小,写入内容到文件,删除文件。 $content = file_get_content(’.text); $contentb = ‘//text.text’; if (file_exits($filename)) { echo file_get_contents($filename); } fileowner:获得文件的所有者 filectime; 获取文件的创建时间 filemtime; 获得文件的修改时间 filetime; 获取文件的访问时间 unlink函数删除文件</P> <h3>PHP异常处理</h3> <p>PHP代码产生的异常可被throw语句抛出并被catch语句捕获, Exception是处理所有异常的基本类: message 异常消息内容 code 异常代码 file 抛出异常的文件名 line 抛出异常在该文件的行数 常用的方法: getTrace获取异常追踪消息 gteTraceAsStrig 获取异常追踪信息的字符串 getMessage 获取出错信息</p><h3>数据库操作</h3> <p>PHP通过安装相应的扩展来实现数据库操作,链接,退出,增加,删除,改,查。查询语句: $res = mysql_query(‘select * from user limit 1’);插入语句: $sql = “insert into user (name,age,class) values (’$name’,’$age’,’$class’)”;</p></body></html> ...

February 19, 2019 · 1 min · jiezi

后端_ThinkPHP5

<p>学习路径:零基础入门到BBS留言板到商城实战到微博登录到支付宝支付到VIP会员</p></p>ThinkPHP是一个免费开源的,面向对象的轻量级PHP开发框架,运行环境要求PHP6+,Git安装:git clone https://github.com/top-think/think 再 clone https://github.com/top-think/framework, ThinkPHP5.0应用基于MVC(模型-视图-控制器)的方式来组织.</p> <p>命名规范:目录使用小写+下划线,类库,函数文件统一以.php为后缀;类名和文件名保持一致,以骆驼峰命名法(首字母大写).函数的命名使用小写字母和下划线的方式,方法的命名 使用骆驼峰法(首字母小写),属性的命名使用骆驼峰(首字母小写),常量以大写字母和下划命名,配置参数以小写字母和下划线命名 <header> 架构:生命周期,入口文件,URL访问,模块设计,命名空间,自动加载,Traits引入,API友好。 ThinkPHP5.0应用基于MVC(模型-视图-控制器)的方式来组织,MVC模式会强制使应用程序的输入,处理和输出分开.默认开启路由,关闭路由或者没有匹配路由的情况下,基于文件的目录结构:http://localhost/tp5/public/模块/控制器/操作 eg:https://www.youwuu.com/index/index/index (1)应用在ThinkPHP中是一个管理系统架构以及生命周期的对象.一个应用是由多个模块组成,这些应用通常是应用目录下面的子目录,每个模块都有自己的独立配置文件,公共文件,类库文件.每个模块下面拥有MVC类库及配置文件,一个模块都有多个控制器来负责响应请求. (2)控制器主要负责请求的接受,并调用相关的模型处理,最后通过视图输出.注意控制器不应该过多的介入业务逻辑处理. (3)start.php就是系统默认的一个引导文件,加载系统常量定义,加载环境变量定义文件,注册自动加载机制,注册错误和异常处理机制,加载惯例配置文件,执行应用. (4)生命周期:入口文件,引导文件,注册自动加载,注册错误和异常机制,应用初始化,URL访问检测,路由检测,分发请求,响应输出,应用结束. (5)入口文件:所有的应用都有一个入口文件开始,不同的应用的入口文件是类似的.入口文件主要完成定义框架路径,项目路径(可选),定义系统相关常量,载入框架入口文件(必须) (6)URL访问:ThinkPHP5.0在没有启用路由的情况下典型的URl访问规则是: https;//www.baidu.com/index.php/模块/控制器/操作[参数名/参数值]. (7)模块设计: </header> 目录命名: project 应用部署目录 ├─application 应用目录(可设置) │ ├─common 公共模块目录(可更改) │ ├─index 模块目录(可更改) │ │ ├─config.php 模块配置文件 │ │ ├─common.php 模块函数文件 │ │ ├─controller 控制器目录 │ │ ├─model 模型目录 │ │ ├─view 视图目录 │ │ └─ … 更多类库目录 │ ├─command.php 命令行工具配置文件 │ ├─common.php 应用公共(函数)文件 │ ├─config.php 应用(公共)配置文件 │ ├─database.php 数据库配置文件 │ ├─tags.php 应用行为扩展定义文件 │ └─route.php 路由配置文件 ├─extend 扩展类库目录(可定义) ├─public WEB 部署目录(对外访问目录) │ ├─static 静态资源存放目录(css,js,image) │ ├─index.php 应用入口文件 │ ├─router.php 快速测试文件 │ └─.htaccess 用于 apache 的重写 ├─runtime 应用的运行时目录(可写,可设置) ├─vendor 第三方类库目录(Composer) ├─thinkphp 框架系统目录 │ ├─lang 语言包目录 │ ├─library 框架核心类库目录 │ │ ├─think Think 类库包目录 │ │ └─traits 系统 Traits 目录 │ ├─tpl 系统模板目录 │ ├─.htaccess 用于 apache 的重写 │ ├─.travis.yml CI 定义文件 │ ├─base.php 基础定义文件 │ ├─composer.json composer 定义文件 │ ├─console.php 控制台入口文件 │ ├─convention.php 惯例配置文件 │ ├─helper.php 助手函数文件(可选) │ ├─LICENSE.txt 授权说明文件 │ ├─phpunit.xml 单元测试配置文件 │ ├─README.md README 文件 │ └─start.php 框架引导文件 ├─build.php 自动生成定义文件(参考) ├─composer.json composer 定义文件 ├─LICENSE.txt 授权说明文件 ├─README.md README 文件 ├─think 命令行入口文件 注意,如果是mac/linux环境下,请确保runtime目录有可写权限,建议public目录作为web目录访问内容. </p> <p>(1)错误和调试模式: ThinkPHP提供调试模式,建议在开发阶段一直开启,正式部署关闭调试模式.‘app_debug’ =>false, 还可以配置.env文件的格式 app_debug = true 但定义之后,配置文件中定义app_debug将无效. 优势在于:开启日志记录,任何错误信息和调试信息都会详细记录,便于调试,详细记录整个执行过程,记录SQL日志,通过Trace功能更好的调试和发现错误. 注意:(1)关闭调试模式还提示错误信息,可以设置 “show_error_msg” => true, (2)在异常捕获中不要使用think\Controller类的error,success和redirect方法. 五种调试:Trace调试,变量调试,性能调试,SQL调试,远程调试和404页面. (1)Trace调试功能是ThinkPHp提供给开发人员的一个用于开发调试的辅助工具,显示当前页面的操作的请求信息,运行情况,错误提示并支持自定义显示.可以设置 ‘app_trace’ => true,可以配置修改显示功能和显示区域. (2)变量调试功能 (3)性能调试 (5)SQL调试功能开启可以在日志文件中看到详细的SQL执行记录以及性能分析.可以监听SQL. (5)远程调试 (6)(2)路由(3)数据库 新版的数据库类拆分为Connection(连接器)/query(查询器)/Builder(SQL生成器),查询语法,闭包查询和闭包事务,链式操作,数据分批处理和数据库SQL执行监听. (1)ThinkPHP内置抽象数据库访问层,把不同的数据库封装起来,只需要使用公共的Db类进行操作,而无需针对不同的数据库写不同的代码和底层实现. (2)ThinkPHP5.0的数据查询由低到高分三个层次:数据库原生查询(SQL查询),数据库链式查询(查询构造器),模型的对象化查询; (3)使用数据库必须配置数据库链接信息,有多种方法定义,如配置文件定义(database.php),方法配置,模型类定义. (4)配置链接数据库之后,可以使用数据库运行原生SQL操作,支持query(查询操作)和excute(写入操作)方法并且支持参数绑定. (5)查询构造器: 查询数据,添数据加,更新数据,删除数据,查询方法,查询语法,链式操作,聚合查询,时间查询,高级查询,视图查询,子查询,原生查询. (6)查询数据: </p><p>CREATE TABLE IF NOT EXISTS think_data(id int(8) unsigned NOT NULL AUTO_INCREMENT,name varchar(255) NOT NULL COMMENT ‘名称’,status tinyint(2) NOT NULL DEFAULT ‘0’ COMMENT ‘状态’, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;INSERT INTO think_data(id,name,status) VALUES(1,’thinkphp’,1),(2,‘onethink’,1),(3,’topthink’,1);</p></body></html> ...

February 19, 2019 · 2 min · jiezi

PHP 转 Go,用 Laravel、thinkphp 的用法造了一个 ThinkGo 框架

ThinkGo 是一个轻量级的 Go 语言 MVC 框架,目前支持路由、中间件、控制器、请求、响应、Session、视图、日志等 web 框架应该具备的基本功能,致力于让代码简洁、富于表达力,帮助开发者快速构建一个 Web 应用。安装go get -u github.com/thinkoner/thinkgo用法package mainimport ( “github.com/thinkoner/thinkgo” “fmt” “github.com/thinkoner/thinkgo/router” “github.com/thinkoner/thinkgo/context”)func main() { app := thinkgo.BootStrap() app.RegisterRoute(func(route *router.Route) { route.Get("/", func(req *context.Request) *context.Response { return thinkgo.Text(“Hello ThinkGo !”) }) route.Get("/ping", func(req *context.Request) *context.Response { return thinkgo.Json(map[string]string{ “message”: “pong”, }) }) // Dependency injection route.Get("/user/{name}", func(req *context.Request, name string) *context.Response { return thinkgo.Text(fmt.Sprintf(“Hello %s !”, name)) }) }) // listen and serve on 0.0.0.0:9011 app.Run()}项目地址GitHub: https://github.com/thinkoner/...Gitee: https://gitee.com/thinkgo/thi…大佬们来指点指点,贡献贡献代码。。。 ...

January 29, 2019 · 1 min · jiezi

日志记录方法

导语工作用的是ThinkPHP框架,有时调试需要打印日志,封装了一个,记录下。代码<?php/** * 日志记录 * @param string $data [数据,默认是最后一次执行的sql] * @param string $path [保存路径] */function logInfo($data = ‘sql’, $path = ‘info’){ $filePath = ‘./’ . $path;// 根据需要调整 $content = date(‘Y-m-d H:i:s’) . ’ ————> ‘; if ($data == ‘sql’) { $content .= M()->_sql() . PHP_EOL; file_put_contents($filePath, $content, FILE_APPEND); return; } if (is_array($data)) { $str = htmlspecialchars_decode(dump($data, false)); $str = substr($str, 5);// 去掉<pre> $str = substr($str, 0, -6);// 去掉</pre> $content .= $str. PHP_EOL; } else { $content .= $data . PHP_EOL; } file_put_contents($filePath, $content, FILE_APPEND);} ...

January 9, 2019 · 1 min · jiezi