克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

这是学习thinkphp5.1的学习笔记

第一章 类的自动加载

  1. 类的自动加载函数 spl_autoload_register()

spl.php 文件中新建类 A 调用 方法找不到类。注册自动加载以后当类找不到的时候会去 找到注册好的自动加载类,运行定义好的方法进行自动加载。

A.php文件

class A
{

    public function say()
    {
        print("in class A say method" . PHP_EOL);
    }
}

spl.php文件

    /**注册类的自动加载 */
    spl_autoload_register('auto_load',true,true);

    function auto_load($class_name){
        echo '没找到的类名为:'.$class_name.PHP_EOL;
        require('./'.$class_name.'.php');
    }

    /**类的自动加载 */
    $tom = new A();
    $tom->say();
  1. get_declared_classes() 获取已经定义的所有的类。(包括当前调用函数的php文件中定义的类。但是后续 通过require 或者 include引入的类 则不会被加载)

dec_test.php

print_r(get_declared_classes());
include('./C.php'); //这一句放在这里 C类不会加载。需要放在调用方法的前面

class A{

}

class B{

}
  1. property_exists()方法会判断当前类中是否存在某一个属性。loader.php文件中通过这个方法,将composer类中所有的已经定义的这些属性加载成当前的实例对象属性。
  2. extend为扩展目录。extend下面定义的类不需要写命名空间,可以直接在模块中去使用(需要注意类名跟文件名要一致,文件名首字母大写)。里面可以创建扩展工具包。放在目录下的包就需要注册命名空间了。

例如:extend/phpmailer/Sms.php

namespace phpmailer;

class Sms{
    
    public static function send(){
        echo 'mail have send to others';
    }
}

调用代码

\phpmailer\Sms::send();
  1. 需要扩展extend目录。就需要在 loader.php文件中添加
self::addAutoLoadDir($rootPath . 'xiaoliu');

第二章 解读配置文件

  1. ArrayAccess接口

如果你的类实现了ArrayAccess接口,那么这个类的对象就可以使用$foo['xxx']这种结构了。 $foo['xxx'] 对应调用offsetGet方法。 $foo['xxx'] = 'yyy' 对应调用offsetSet方法。 isset($foo['xxx']) 对应调用offsetExists方法。 unset($foo['xxx']) 对应调用offsetUnset方法。

class Person implements \ArrayAccess{

    public function offsetExists( $offset ) {
        echo "这里是 offsetExists() 方法 你输入的参数是 {$offset}";
    }

    public function offsetGet( $offset ) {
        echo "这里是 offsetGet() 方法 你输入的参数是 $offset";
    }

    public function offsetSet( $offset, $value ) {
        echo "这里是 offsetSet() 方法 你输入的 {$offset}={$value}";
    }

    public function offsetUnset( $offset ) {
        echo "这里是 offsetUnset() 方法 你输入的参数是 {$offset}";
    }
}

$xiaoming = new Person();
$t = $xiaoming['name'];  //获取值时候 调用offsetGet
$xiaoming['name']="小明";  //获取值时候 offsetSet
isset($xiaoming['name']);  //获取值时候 调用offsetExists
unset($xiaoming['name']);  //获取值时候 调用offsetGet
  1. yaconf高性能配置扩展

如果项目中有很多个配置文件,那么一次次调用配置消耗很大资源。使用yaconf扩展可以一次性的把所有的配置加载到内存中。 1 安装yaconf扩展 可以编译安装,这里使用命令 pecl install yaconf 2 在php.ini文件中指定yaconf需要加载的目录

extension="yaconf.so"
yaconf.directory=/www/wwwroot/my.tp51.com/config

config/abc.ini

title="singwa"

3 调用方式1 程序中直接调用获取

    $config=\YaConf::get('abc');
    $title=\YaConf::get('abc.title');
    print_r($config); //打印数组
    print_r($title); //打印 singwa

4 调用方式2 来自tp官方 https://www.kancloud.cn/top-think/thinkphp-blog/783762 1)common.php 中添加

think\facade\Config::setYaconf('abc');
  1. 调用数据 助手函数yaconf('config_name', 'default_value')
$title = yaconf('title');
print($title); //打印 singwa

第三章 IOC容器类及Facade深度解析

  1. 单例模式
    /**
     * 单利模式
     */
    class Single{
        static $instance=null; //第二步 定义一个静态属性,初始值为null

        private function __construct(){ //第一步 私有化构造方法防止new创建对象
            echo 'class instance .<br>';
        }

       public static function getInstance(){  //第三步 定义一个静态方法,判断对象是否生成并返回该对象
           if(is_null(self::$instance)){
               self::$instance=new self();
           }
           return self::$instance;
       }

       public function abc(){
           return 'abc';
       }
    }

    $ob1 = Single::getInstance(); //只会实例化一次
    $ob2 = Single::getInstance(); 
    $ob3 = Single::getInstance();
    $ob4 = Single::getInstance();
    echo $ob1->abc(); //打印 class instance abc
    echo $ob2->abc(); //打印 abc
    echo $ob3->abc(); //打印 abc
    echo $ob4->abc(); //打印 abc
  1. 注册树模式

一个注册树上有很多个对象,可以设置对象。需要的时候从树上取下来调用相应的方法。

SingwaRegister.php

/**
 * 注册树模式
 */
class SingwaRegister{
    /**注册树池子 */
    protected static  $objects=null;

    /**树上挂载对象 */
    public static function set($key,$object){
        self::$objects[$key]=$object;
    }

    /**获取对象 */
    public static function get($key){
        if(is_null(self::$objects[$key])){
            self::$objects[$key]=new $key;
        }
        return self::$objects[$key];
    }

    /**注销对象 */
    public static function _unset($key){
        unset(self::$objects[$key]);
    }
}

创建测试类 A.php

class A{
    public function abc(){
        return 'abcd';
    }
}

使用时通过注册树调用

$abc=\SingwaRegister::get('A'); //获取到当前模型
dump($abc->abc());
  1. 依赖注入(控制反转)思想 B类中需要调用A类中的方法,就把A类的实例传递给B类。 Car.php类
namespace di;

class Car{
    
    public function run(){
        return '汽车正在路上跑...';
    }
}

Person.php

namespace di;

class Person{

    public function __construct(Car $obj,$a=123)
    {   
        $this->obj=$obj;
        $this->a=$a;
    }

    public function buy(){
        // $bmw=new Car();
        // $bmw=new $obj;
        return $this->a.'|'.$this->obj->run();
    }
}

调用

$bmw=new \di\Car();
$person=new \di\Person($bmw);
var_dump($person->buy());
  1. 反射机制 A.php
class A{
    /**反射测试类 */
    public $a=1;
    private $abc=2;

    public function abc($a,$b){
        return 'abcd';
    }

    public function mf($type=1){
        return 'type:'.$type;
    }

    public function ddd(){
        return "ddddd";
    }
}

方法中调用

    public function rel(){ //反射
        $obj=new \A();
        // var_dump($obj); // 打印 A类 object(A)#34 (2) { ["a"]=> int(1) ["abc":"A":private]=> int(2) }

        $obj2=new \ReflectionClass($obj);
        // var_dump($obj2); // 打印 反射类  object(ReflectionClass)#35 (1) { ["name"]=> string(1) "A" }

        $instance=$obj2->newInstance(); //相当于实例化A类
        // var_dump($instance);  // object(A)#36 (2) { ["a"]=> int(1) ["abc":"A":private]=> int(2) } 

        $methods=$obj2->getMethods(); //获取类中的方法
        // var_dump($methods);die();  // array(3) { [0]=> object(ReflectionMethod)#37 (2) { ["name"]=> string(3) "abc" ["class"]=> string(1) "A" } [1]=> object(ReflectionMethod)#38 (2) { ["name"]=> string(2) "mf" ["class"]=> string(1) "A" } [2]=> object(ReflectionMethod)#39 (2) { ["name"]=> string(3) "ddd" ["class"]=> string(1) "A" } }

        // foreach ($methods as $key => $m) {
        //     var_dump($m->getDocComment()); //获取注释内容
        // }

        $properties=$obj2->getProperties(); //获取类的属性
        var_dump($properties);die(); //  array(2) { [0]=> object(ReflectionProperty)#40 (2) { ["name"]=> string(1) "a" ["class"]=> string(1) "A" } [1]=> object(ReflectionProperty)#41 (2) { ["name"]=> string(3) "abc" ["class"]=> string(1) "A" } }

        //调用方法 方式一
        echo $instance->abc(1,2);
        //调用方法 方式二
        $method=$obj2->getMethod("abc");
        echo $method->invokeArgs($instance,['mmmm','555444a']);
        //调用方法 方式三
        $method=$obj2->getMethod("ddd");
        echo $method->invoke($instance);

        /**判断某个方式是否是公用的 */
        $method=new \ReflectionMethod($obj,"ddd");
        if($method->isPublic()){
            echo '是公用方法';
        }

        $method2=new \ReflectionMethod($obj,"abc");
        dump($method2->getParameters()); //获取参数
        dump($method2->getNumberOfParameters()); //获取参数个数
    }
  1. 玩转自己的容器类 Container.php
namespace di;
class Container{
    
    /**
     * 存放容器的数据
     */
    public $instances=[];

    /**
     * 容器中的对象实例
     */
    protected static $instance;

    private function __construct(){
    }

    public static function getInstance(){ //单例模式获取对象
        if(is_null(static::$instance)){
            static::$instance=new static;
        }
        return static::$instance;
    }

    public function set($key,$value){
        $this->instances[$key]=$value;
    }

    /**
     * 获取容器里的实例 会用到反射机制
     */
    public function get($key){

        if(!empty($this->instances[$key])){
            $key=$this->instances[$key];
        }
        
        $reflect=new \ReflectionClass($key);
        
        $c=$reflect->getConstructor(); //获取类的构造函数
        if(!$c){
            return new $key;
        }
        $params=$c->getParameters(); //返回构造函数参数
        
        if(empty($params)){ //有构造函数,构造函数无参数
            return new $key;
        }
        foreach ($params as $key => $param) {
            $class=$param->getClass();
            if(!$class){
                //todo
            }else{
                $args[]=$this->get($class->name);
            }
            return $reflect->newInstanceArgs($args);
        }
    }
}

容器类中调用

    \di\Container::getInstance()->set('person','\di\Person');
    \di\Container::getInstance()->set('car','\di\Car');

    $obj=\di\Container::getInstance()->get('person');

    var_dump($obj->buy());
  1. Countable类 SingwaCount.php 中实现 Countable接口 并重写count 方法
class SingwaCount implements Countable{

    public function count(){
        return '234';
    }
}

方法中调用

$obj=new \SingwaCount();
// echo $obj->count(); // 返回 234
echo count($obj); // 返回 234
  1. 方法调用方式
    $config = new \Config(); //第一种方式
    dump($config::get('app.')); //获取配置

    $config=Container()::get('config')->get('app.'); //容器类获取
    dump($config);
    
    $config=app('config'); // 第三种方式
    dump($config->get('app.'));
  1. 调用不存在的静态方法会自动去调用魔术方法 __callStatic()
    public static function __callStatic($name, $arguments)
    {
        var_dump($name);
        var_dump($arguments);
    }
  1. static::A();
<?php
class Test{
    public static function A(){
        echo 'A method';
    }
    public function B(){
        return static::A(); //static::A 调用自身的静态方法 A
    }
}
  1. Facade(门面模式)
  • 门面为容器中的类提供一个静态调用的接口。
  • 相比传统的静态方法调用,带来了更好的测试性和扩展性
  • facade 静态方法get-> 容器中的实例 -> 不存在则创建实例放到容器中 在 application\common中创建文件 Singwa.php
<?php
namespace app\common;

class Singwa{

    public function abc(){
        echo 'abcd';
    }
}

调用方式一

    $singwa = new \app\common\Singwa(); //第一种类的调用方式
    $singwa->abc();

调用方式二 facade模式的思想调用 在 application\facade中创建文件 Singwa.php

namespace app\facade;

use \think\Facade;

class Singwa extends Facade{

    protected static function getFacadeClass()
    {
        return '\app\common\Singwa';
    }
}

调用的代码

\app\facade\Singwa::abc(); // 通过门面方式调用类

facade bind方法 在 application\facade中创建文件 Xiaoliu.php

namespace app\facade;

use \think\Facade;

class Xiaoliu extends Facade{

}

如果一个类 application\facade中 Xiaoliu.php 中没有定义 getFacadeClass 方法

namespace app\facade;

use \think\Facade;

class Xiaoliu extends Facade{

}

调用

\think\Facade::bind('app\facade\Xiaoliu','app\common\Xiaoliu');
\app\facade\Xiaoliu::abc();

第四章 框架执行流程

ThinkPHP遵循Apache2开源协议发布,并提供免费使用。 版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn) All rights reserved。 ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。 Apache Licence是著名的非盈利开源组织Apache采用的协议。 该协议和BSD类似,鼓励代码共享和尊重原作者的著作权, 允许代码修改,再作为开源或商业软件发布。需要满足 的条件: 1. 需要给代码的用户一份Apache Licence ; 2. 如果你修改了代码,需要在被修改的文件中说明; 3. 在延伸的代码中(修改和有源代码衍生的代码中)需要 带有原来代码中的协议,商标,专利声明和其他原来作者规 定需要包含的说明; 4. 如果再发布的产品中包含一个Notice文件,则在Notice文 件中需要带有本协议内容。你可以在Notice中增加自己的 许可,但不可以表现为对Apache Licence构成更改。 具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

简介

暂无描述 展开 收起
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化