alexsasharegan/model-framework

通过使用一些可靠的模型类和数据库抽象,简化数据驱动应用程序的入门。

v3.0.0 2017-11-06 21:47 UTC

README

Latest Stable Version Total Downloads Latest Unstable Version License

一个轻量级的基于PDO和MySQL的数据建模框架,深受Laravel和Underscore/Lodash的启发。

为什么还需要另一个库

这个库是在生产环境中开发的,旨在减轻使用PHP和MySQL的困难。

[LMW]AMP堆栈中开发提供了部署环境的可用性高的好处。不幸的是,这也意味着要处理不稳定的PHP语言API和糟糕的MySQL数据类型到PHP的转换。

这就是model-framework发挥作用的地方。您可以与提供围绕PHP更一致API包装的模型和集合一起工作,并且定义了底层的工作来强制执行模型上数据的类型完整性。

PDO是PHP中与MySQL交互的一种好方法,同时减少注入攻击的潜在可能性。这个库在内部使用预编译查询,以帮助您直接开始使用PDO。使用简单的像Model::removePropsNotInDatabase()这样的方法来查询您的对象表,并移除任何未在表中定义的字段。

不熟悉面向对象的PHP?模型类实现了ArrayAccessTraversable等接口,因此您可以像处理常规关联数组一样与之交互,同时仍然获得所有内部数据类型强制执行。

入门

使用Composer加载库

composer require alexsasharegan/model-framework

这个库使用vlucas/phpdotenv库将模型连接到数据库(已包含)。首先创建一个包含以下数据库连接变量的.env文件

DB_HOST=localhost
DB_DATABASE=sandbox
DB_PORT=3306
DB_CHARSET=utf8
DB_USERNAME=root
DB_PASSWORD=root

现在加载环境

<?php
// in your main entry point file, load the environment
// this technique avoids any global variable pollution
call_user_func( function () {
	// constructed with the directory containing the `.env` file
	$environment = new \Dotenv\Dotenv( __DIR__ );
	$environment->load();
  
  // also a nice place to set things like timezone & session
  date_default_timezone_set('America/Phoenix');
  session_start();
} );

现在扩展抽象的\Framework\Model类以获取所有功能

<?php

use Framework\Model;

class Character extends Model {
	
	/*
	 * This is the name of the database table
	 */
	const TABLE = 'characters';
	
	/*
	 * Calling Model::delete() when this is set to true
	 * will only set the softDeleteFieldName to TRUE and update the db model
	 */
	protected $useSoftDeletes = TRUE;
	
	protected $softDeleteFieldName = 'deleted';
	
	/*
	 * Use this to handle time-stamping model creation
	 * (since MySQL handles updates automatically,
	 *  but not creation automatically)
	 */
	protected $timestamp = TRUE;
	
	protected $timestampFieldName = 'created_at';
	
	protected $casts = [
		'default_value' => self::CAST_TO_INT,
		'deleted'       => self::CAST_TO_BOOL,
		'float'         => self::CAST_TO_FLOAT,
		'price'         => self::CAST_TO_PRICE,
		'special'       => self::CAST_FROM_JSON_TO_ARRAY,
		'specialObject' => self::CAST_FROM_JSON_TO_OBJECT,
	];
}

// Convenient static methods return instances
// this returns a model instance with the data from this id
// already parsed, or an empty model
$character = Character::fetch( 65 );

// Models implement ArrayAccess interface,
// but they still enforce the internal cast instructions
// as well as returning NULL when an index isn't defined
// instead of throwing an exception
$character['special'] = [
	'key'  => [
		'nested' => 'value',
	],
	'prop' => TRUE,
];

echo $character->toJson( JSON_PRETTY_PRINT );

$newCharacter = Character::fetch( 655 );
$newCharacter->mergeData( [
	'first_name' => 'Jamie',
	'last_name'  => 'Lanaster',
	'special'    => [
		'house' => [
			'name'  => 'Lanaster',
			'words' => 'A Lanaster always pays his debts.',
			'sigil' => 'Lion',
		],
	],
	'price'      => 12.3493046,
	'deleted'    => FALSE,
	'fakeField'  => "I'm not in your database...",
] );


// a handy dot notation syntax is available from the model as a __get magic method
echo $newCharacter['special.house.name'];
// Lanaster

// The benefits of the Traversable interface
foreach ( $newCharacter as $key => $value )
{
	$type = gettype( $value );
	echo "Prop: $key ($type): " . print_r( $value, TRUE ) . PHP_EOL;
}

echo PHP_EOL;
// Retrieves the fields from the database,
// then filters the properties on the object
// so you can further prevent injection
// (prepared queries are also used for data binding)
$newCharacter->removePropsNotInDatabase();
foreach ( $newUser as $key => $value )
{
	$type = gettype( $value );
	echo "Prop: $key ($type): " . print_r( $value, TRUE ) . PHP_EOL;
}
echo PHP_EOL;

依赖关系

这个库直接使用以下依赖项