# tp51_study
**Repository Path**: liiy250/tp51_study
## Basic Information
- **Project Name**: tp51_study
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-05-12
- **Last Updated**: 2024-05-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
##
这是学习thinkphp5.1的学习笔记
### 第一章 类的自动加载
1. ##### 类的自动加载函数 spl_autoload_register()
spl.php 文件中新建类 A 调用 方法找不到类。注册自动加载以后当类找不到的时候会去
找到注册好的自动加载类,运行定义好的方法进行自动加载。
A.php文件
```php
class A
{
public function say()
{
print("in class A say method" . PHP_EOL);
}
}
```
spl.php文件
```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();
```
2. ##### get_declared_classes() 获取已经定义的所有的类。(包括当前调用函数的php文件中定义的类。但是后续 通过require 或者 include引入的类 则不会被加载)
dec_test.php
```php
print_r(get_declared_classes());
include('./C.php'); //这一句放在这里 C类不会加载。需要放在调用方法的前面
class A{
}
class B{
}
```
3. ##### property_exists()方法会判断当前类中是否存在某一个属性。loader.php文件中通过这个方法,将composer类中所有的已经定义的这些属性加载成当前的实例对象属性。
4. ##### extend为扩展目录。extend下面定义的类不需要写命名空间,可以直接在模块中去使用(需要注意类名跟文件名要一致,文件名首字母大写)。里面可以创建扩展工具包。放在目录下的包就需要注册命名空间了。
例如:extend/phpmailer/Sms.php
```php
namespace phpmailer;
class Sms{
public static function send(){
echo 'mail have send to others';
}
}
```
调用代码
```php
\phpmailer\Sms::send();
```
5. ##### 需要扩展extend目录。就需要在 loader.php文件中添加
```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方法。
```php
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
```
2. ##### yaconf高性能配置扩展
如果项目中有很多个配置文件,那么一次次调用配置消耗很大资源。使用yaconf扩展可以一次性的把所有的配置加载到内存中。
1 安装yaconf扩展
可以编译安装,这里使用命令 pecl install yaconf
2 在php.ini文件中指定yaconf需要加载的目录
```ini
extension="yaconf.so"
yaconf.directory=/www/wwwroot/my.tp51.com/config
```
config/abc.ini
```ini
title="singwa"
```
3 调用方式1 程序中直接调用获取
```php
$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 中添加
```php
think\facade\Config::setYaconf('abc');
```
2) 调用数据 助手函数yaconf('config_name', 'default_value')
```php
$title = yaconf('title');
print($title); //打印 singwa
```
### 第三章 IOC容器类及Facade深度解析
1. ##### 单例模式
```php
/**
* 单利模式
*/
class Single{
static $instance=null; //第二步 定义一个静态属性,初始值为null
private function __construct(){ //第一步 私有化构造方法防止new创建对象
echo 'class instance .
';
}
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
```
2. ##### 注册树模式
一个注册树上有很多个对象,可以设置对象。需要的时候从树上取下来调用相应的方法。
SingwaRegister.php
```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
```php
class A{
public function abc(){
return 'abcd';
}
}
```
使用时通过注册树调用
```php
$abc=\SingwaRegister::get('A'); //获取到当前模型
dump($abc->abc());
```
3. 依赖注入(控制反转)思想 B类中需要调用A类中的方法,就把A类的实例传递给B类。
Car.php类
```php
namespace di;
class Car{
public function run(){
return '汽车正在路上跑...';
}
}
```
Person.php
```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();
}
}
```
调用
```php
$bmw=new \di\Car();
$person=new \di\Person($bmw);
var_dump($person->buy());
```
4. 反射机制
A.php
```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";
}
}
```
方法中调用
```php
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()); //获取参数个数
}
```
5. 玩转自己的容器类
Container.php
```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);
}
}
}
```
容器类中调用
```php
\di\Container::getInstance()->set('person','\di\Person');
\di\Container::getInstance()->set('car','\di\Car');
$obj=\di\Container::getInstance()->get('person');
var_dump($obj->buy());
```
6. Countable类
SingwaCount.php 中实现 Countable接口 并重写count 方法
```php
class SingwaCount implements Countable{
public function count(){
return '234';
}
}
```
方法中调用
```php
$obj=new \SingwaCount();
// echo $obj->count(); // 返回 234
echo count($obj); // 返回 234
```
7. 方法调用方式
```php
$config = new \Config(); //第一种方式
dump($config::get('app.')); //获取配置
$config=Container()::get('config')->get('app.'); //容器类获取
dump($config);
$config=app('config'); // 第三种方式
dump($config->get('app.'));
```
8. 调用不存在的静态方法会自动去调用魔术方法 __callStatic()
```php
public static function __callStatic($name, $arguments)
{
var_dump($name);
var_dump($arguments);
}
```
9. static::A();
```php
容器中的实例 -> 不存在则创建实例放到容器中
在 application\common中创建文件 Singwa.php
```php
abc();
```
调用方式二 facade模式的思想调用
在 application\facade中创建文件 Singwa.php
```php
namespace app\facade;
use \think\Facade;
class Singwa extends Facade{
protected static function getFacadeClass()
{
return '\app\common\Singwa';
}
}
```
调用的代码
```php
\app\facade\Singwa::abc(); // 通过门面方式调用类
```
facade bind方法
在 application\facade中创建文件 Xiaoliu.php
```php
namespace app\facade;
use \think\Facade;
class Xiaoliu extends Facade{
}
```
如果一个类 application\facade中 Xiaoliu.php 中没有定义 getFacadeClass 方法
```php
namespace app\facade;
use \think\Facade;
class Xiaoliu extends Facade{
}
```
调用
```php
\think\Facade::bind('app\facade\Xiaoliu','app\common\Xiaoliu');
\app\facade\Xiaoliu::abc();
```
### 第四章 框架执行流程