peacq/picorm

轻量级ORM

0.0.7 2015-10-31 09:37 UTC

This package is not auto-updated.

Last update: 2024-09-15 01:50:48 UTC


README

PicORM

一个轻量级的PHP ORM。

PicORM可以帮助你将MySQL数据库行映射到PHP对象,并在它们之间创建关系。
PicORM是一个易于安装和使用的Active Record模式实现。

Build Status Latest Stable Version Total Downloads

你需要知道的一些事情

  • 目前还不能有多个主键
  • 目前还不能使用与关系表中数据的多对多关系
  • 鼓励Fork和提交pull request!

安装

通过composer

使用curl -sS https://getcomposer.org/installer | php在www文件夹中安装composer

创建一个composer.json文件

{
    "require": {
        "picorm/picorm": "0.0.6"
    }
}

使用php composer.phar install安装PicORM

从源码
克隆https://github.com/iNem0o/PicORM仓库,并使用以下方式包含PicORM自动加载:

    require('path/to/PicORM/src/autoload.inc.php');

加载和配置PicORM
在开始使用PicORM之前,你必须进行配置。datasource是唯一必需的参数,必须是一个PDO实例

\PicORM\PicORM::configure(array(
	'datasource' => new PDO('mysql:dbname=DBNAME;host=HOST', 'DBLOGIN', 'DBPASSWD')
));

模型

实现一个模型
首先,你必须创建一个表,该模型将被映射到该表

    CREATE TABLE `brands` (
      `idBrand` int(11) NOT NULL AUTO_INCREMENT,
      `nameBrand` varchar(100) NOT NULL,
      `noteBrand` float DEFAULT 0,
      PRIMARY KEY (`idBrand`)
    ) ENGINE=MyISAM;

然后创建一个继承自\PicORM\Model的类。你必须实现一些静态参数来描述你的MySQL表模式,如果你忘记了其中任何一个,\PicORM\Exception将会提醒你

必需的
protected static $_tableName MySQL表名
protected static $_primaryKey 表主键字段名
protected static $_tableFields 不包括主键的所有mysql表字段名的数组

可选的
protected static $_databaseName 如果与数据源主DB不同,则为数据库的名称

然后,为表字段添加一个公共属性,使用public $fieldName

品牌模型声明

    class Brand extends \PicORM\Model
    {
        protected static $_tableName = 'brands';
        protected static $_primaryKey = 'idBrand';

        protected static $_tableFields = array(
            'nameBrand',
            'noteBrand'
        );

        public $idBrand;
        public $nameBrand;
        public $noteBrand;

    }

创建和保存

// creating new model
	$brand = new Brand();

// setting field
	$brand -> nameBrand = 'Peugeot';

// save model
	$brand -> save();

更新和删除

// Criteria with exact value (idBrand=10)
    $brand = Brand :: findOne(array('idBrand' => 10));

// setting model property
	$brand -> nameBrand = 'Audi';

// save model
	$brand -> save();
	
// save model
	$brand -> delete();

find() 和 findOne()

Model的每个子类都继承自静态方法 find()findOne()
这些方法用于从数据库行中填充模型。

/**
 * Find one model from criteria, allowing to order
 * @param array $where - associative
 * @param array $order - associative array
 */
public static function findOne($where = array(), $order = array())

/**
 * Return Collection instance from criteria, allowing to order and limit result
 * @param array $where - associative array
 * @param array $order - associative array
 * @param int $limitStart - int
 * @param int $limitEnd - int
 * @return Collection
 */
public static function find($where = array(),$order = array(), $limitStart = null, $limitEnd = null)

如何使用 $where 参数
此参数是构建WHERE mysql子句的数据

// simple criteria
	$where = array('field' => 1);

// custom operator
	$where = array('field' => array('operator' => '<=',
									'value'    => '20')
					);

// raw sql value (NOT prepared, beware of SQL injection)
	$where = array(
					'field'    => array('IN (5,6,4)'),
					'dateTime' => array('NOW()')
					);

如何使用 $order 参数
此参数是构建ORDER mysql子句的数据

     $order = array(
		'field'=>'ASC',
		'field2' => DESC,
		'RAND() => ''
	 )

集合

PicORM中的集合通过::find()方法创建,在\PicORM\Model的每个子类上静态访问。
一旦你有一个新的\PicORM\Collection实例,数据尚未检索。检索仅在尝试使用以下方式之一访问数据时才进行:

集合的使用

// php array access
	$firstResult = $collection[0];
	
// counting collection
	$nbResults = count($collection);
	
// using getter
	$firstResult = $collection->get(0);
	
// iterate over the collection
	foreach($collection as $model)
	
// or manual fetching / re-fetching
	$collection->fetch();

\PicORM\Collection实例可以在检索数据之前对集合成员执行UPDATE和DELETE查询,这样使用update()delete()方法将仅根据find()限制参数生成一个基于MySQL查询的查询。

// Delete all models in collection
    $collection = Brand::find(array('noteBrand' => 10))
                         -> delete();

// Update and set noteBrand = 5 to collection
    $collection = Brand::find(array('noteBrand' => array('IN(9,10,11)')))
                         -> update(array('noteBrand' => 5));
						 

集合分页

集合的分页基于MySQL的FOUND_ROWS()。记住,集合在您使用之前不会检索数据。当您有一个集合实例时,您可以通过以下方式轻松激活分页:

$carCollection = Car::find();           // grab all car from database
$carCollection->activePagination(50);   // asking for 50 models by page
$carCollection->paginate(1);            // asking for first page

现在您可以访问另外两个方法。

$nbTotalPages = $carCollection -> getTotalPages();
$nbTotalModels = $carCollection -> foundModels();

集合高级查询

您可以在执行之前使用集合上的getQueryHelper()方法更改检索查询。您将获得一个InternalQueryHelper的实例,您可以对其进行操作。完成后,只需使用setQueryHelper($helper)设置集合查询助手即可。

这样,您可以在模型实例中加载自定义数据。

$cars  = Car::find();
$queryBuilder = $cars->getQueryHelper();
$queryBuilder->select("COUNT(idTag) as nbTags");
$queryBuilder->leftJoin('car_has_tag cht', 'cht.idCar = cars.idCar');
$queryBuilder->groupBy("cars.idCar");
$cars->setQueryHelper($queryBuilder);

模型之间的关系

使用关系需要在您的模型子类中添加一个属性和一个方法。
protected static $_relations = array(); 需要实现以存储模型关系,需要实现 protected static function defineRelations() { } 方法来声明你的关系

在子类中重写 defineRelations() 允许你使用以下 3 种方法之一声明你特定的模型关系。

/**
 * Add a OneToOne relation
 * @param $sourceField          - model source field
 * @param $classRelation        - relation model classname
 * @param $targetField          - related model target field
 * @param array $autoGetFields  - field to auto get from relation when loading model
 * @param string $aliasRelation - override relation auto naming className with an alias
 *                                    (ex : for reflexive relation)
 */
protected static function addRelationOneToOne($sourceField, $classRelation, $targetField, $autoGetFields = array(), $aliasRelation = '')

/**
 * Add a OneToMany relation
 * @param $sourceField          - model source field
 * @param $classRelation        - relation model classname
 * @param $targetField          - related model target field
 * @param string $aliasRelation - override relation auto naming className with an alias
 */
protected static function addRelationOneToMany($sourceField, $classRelation, $targetField, $aliasRelation = '')

/**
 * Add a ManyToMany relation
 * @param $sourceField           - model source field
 * @param $classRelation         - relation model name
 * @param $targetField           - related model field
 * @param $relationTable         - mysql table containing the two models ID
 * @param string $aliasRelation  - override relation auto naming className
 */
protected static function addRelationManyToMany($sourceField, $classRelation, $targetField, $relationTable, $aliasRelation = '')

使用关系

此示例将使用以下 MySQL 模式

CREATE TABLE `brands` (
	`idBrand` int(11) NOT NULL AUTO_INCREMENT,
	`nameBrand` varchar(100) NOT NULL,
	`noteBrand` float DEFAULT 0,
PRIMARY KEY (`idBrand`)
) ENGINE=MyISAM;

CREATE TABLE  `cars` (
	`idCar` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`idBrand` INT NOT NULL,
	`nameCar` VARCHAR(100) NOT NULL
) ENGINE = MYISAM ;

CREATE TABLE `car_have_tag` (
	`idCar` INT NOT NULL,
	`idTag` INT NOT NULL,
PRIMARY KEY (`idCar`,`idTag`)
) ENGINE = MYISAM ;

CREATE TABLE `tags` (
	`idTag` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`libTag` VARCHAR(255) NOT NULL
) ENGINE = MYISAM ;

首先,你需要声明你的 3 个模型及其关系

class Brand extends Model
{
	protected static $_tableName = 'brands';
	protected static $_primaryKey = "idBrand";
	protected static $_relations = array();

	protected static $_tableFields = array(
		'nameBrand',
		'noteBrand'
	);

	public $idBrand;
	public $nameBrand;
	public $noteBrand;

	protected static function defineRelations()
	{
		// create a relation between Brand and Car
		// based on this.idBrand = Car.idBrand
		self::addRelationOneToMany('idBrand', 'Car', 'idBrand');
	}
}

class Car extends Model
{
	protected static $_tableName = 'cars';
	protected static $_primaryKey = "idCar";
	protected static $_relations = array();

	protected static $_tableFields = array(
		'idBrand',
		'nameCar'
	);

	public $idCar;
	public $idBrand;
	public $nameCar = '';

	protected static function defineRelations()
	{
		// create a relation between Car and Brand
		// based on this.idBrand = Brand.idBrand
		// nameBrand is added to autoget fields which is automatically fetched
		// when model is loaded
		self::addRelationOneToOne('idBrand', 'Brand', 'idBrand', 'nameBrand');

		// create a relation between Car and Tag using a relation table car_have_tag
		self::addRelationManyToMany("idCar","Tag","idTag","car_have_tag");
	}
}

class Tag extends Model
{
	protected static $_tableName = 'tags';
	protected static $_primaryKey = "idTag";
	protected static $_relations = array();

	protected static $_tableFields = array(
		'libTag',
	);

	public $idTag;
	public $libTag = '';

	protected static function defineRelations()
	{
		// create a relation between Tag and Car using a relation table car_have_tag
		self::addRelationManyToMany('idTag','Car','idCar','car_have_tag');
	}
}

现在你可以开始创建和操作相关模型

// creating a brand
    $brand = new Brand();
    $brand -> nameBrand = "Peugeot";
    $brand -> save();

// creating a car
    $car = new Car();
    $car -> nameCar = "205 GTi";

// setting car's brand
    $car -> setBrand($brand);

// other way to setting car's brand
    $car -> idBrand = $brand -> idBrand;
    $car -> save();

// if we look for our car
    $car = Car :: findOne(array('nameCar' => '205 GTi'));
	
// we can get brand of the car
    $car -> getBrand();

// or we can access brand name directly because it has been added to relation auto get fields
    $car -> nameBrand;
		

由于你声明了从品牌到汽车的单一到多对关系,因此你也可以在另一端使用设置器和获取器

// get all cars from brand
// method return instance of \PicORM\Collection
    foreach($brand -> getCar() as $cars)

// get all cars from brand with custom criteria
// parameters are same as find() method
// method return instance of \PicORM\Collection
    $brand -> getCar($where,$order,$limitStart,$limitStop);

多对多关系也很容易使用

// creating some tags
    $tag = new Tag();
    $tag -> libTag = 'tag 1';
    $tag -> save();

    $tag2 = new Tag();
    $tag2 -> libTag = 'tag 2';
    $tag2 -> save();

    $tag3 = new Tag();
    $tag3 -> libTag = 'tag 3';
    $tag3 -> save();

// setting car's tags
    $car -> setTag(array($tag,$tag2,$tag3));

// getting car's tags (return instance of \PicORM\Collection)
    $car -> getTag();

// getting car's tags with custom criteria
// parameters are same as find() method
// method return instance of \PicORM\Collection
    $car -> getTag($where,$order,$limitStart,$limitStop);

// unset relation between $car and $tag2
    $car -> unsetTag($tag2);

变更日志

不稳定 0.0.1

  • 初始版本

不稳定 0.0.2

  • 错误修复
  • 添加命名空间支持和 pdo 检索模式选择
  • 添加事务支持

BETA 0.0.3

  • 错误修复
  • 重构 MySQL
  • 集合
  • 测试

BETA 0.0.4

  • 重构实体到模型
  • QueryBuilder:SQL 提示和 FoundRows
  • 集合分页
  • 测试

BETA 0.0.5

  • 自定义集合查询构建器
  • 从 SQL_CALC_FOUND_ROWS 移动到 count(*)
  • 修复关系别名名称大小写错误
  • 修复关系获取器中存在 LIMIT 子句的错误
  • 修复多对多获取器中没有 WHERE / ORDER / LIMIT 的错误
  • 重构代码
  • 重构 PHPDoc
  • 重构测试
  • 添加 TravisCI

BETA 0.0.6

  • 添加数据库和表的设置器
  • 错误修复:更新查询未使用 tablename 获取器
  • 错误修复:在多对多获取器中,WHERE 值未以表名前缀
  • 更新 README