brandonlamb / spot
适用于 PHP 5.5+ 的 DataMapper ORM
Requires
- php: >=5.5.0
This package is not auto-updated.
Last update: 2024-09-24 02:06:31 UTC
README
适用于关系数据库和 MongoDB
连接到数据库
Spot\Config 对象通过名称存储和引用数据库连接。创建一个新的 Spot\Config 实例,并添加 Spot 之外创建的数据库连接。这是为了允许您的应用程序创建原始 PDO 连接并重新使用它。我一直以来最大的抱怨是,几乎每个 ORM/Model 类都希望为您创建这个,而不是传递这个连接。
// PostgreSQL
$db = new Pdo('pgsql:host=localhost;dbname=jdoe', 'jdoe', 'mypass');
$cfg = \Spot\Config::getInstance();
$adapter = $cfg->addConnection('db', new \Spot\Adapter\Pgsql($db));
$adapter = $cfg->connection('db');
访问 Mapper
由于 Spot 遵循 DataMapper 设计模式,您将需要一个 mapper 实例来处理对象实体和数据库表。
$mapper = new \Spot\Mapper($cfg);
由于您必须在任何使用数据库的地方都能访问到您的 mapper,大多数人会创建一个辅助方法来创建一个 mapper 实例一次,并在需要时再次返回同一个实例。这样的辅助方法可能看起来像这样
function get_mapper() {
static $mapper;
if($mapper === null) {
$mapper = new \Spot\Mapper($cfg);
}
return $mapper;
}
或者如果您在框架中有一个 Registry 类
$registry = Registry::getInstance();
$registry->set('mapper', $mapper);
$mapper = Register::get('mapper');
或者使用依赖注入容器
$di->setShared('mapper', $mapper);
$mapper = $di->getShared('mapper');
创建实体
实体类可以按照您在项目结构中设置的任意名称和命名空间命名。对于以下示例,实体将仅使用 Entity 命名空间作为前缀,以便易于 psr-0 兼容的自动加载。
namespace Entity;
class Post extends \Spot\Entity
{
protected static $datasource = 'posts';
public static function fields()
{
return array(
'id' => array('type' => 'int', 'primary' => true, 'serial' => true),
'title' => array('type' => 'string', 'required' => true),
'body' => array('type' => 'text', 'required' => true),
'status' => array('type' => 'int', 'default' => 0, 'index' => true),
'date_created' => array('type' => 'datetime')
);
}
public static function relations()
{
return array(
// Each post entity 'hasMany' comment entites
'comments' => array(
'type' => 'HasMany',
'entity' => 'Entity_Post_Comment',
'where' => array('post_id' => ':entity.id'),
'order' => array('date_created' => 'ASC')
)
);
}
}
另一个实体示例,一个位于应用程序 Model 命名空间中的模型类。这是最简单的定义,仅定义了模型字段。
<?php
namespace Blog\Model;
use \Spot\Entity;
class Game extends Entity
{
protected static $datasource = 'game';
public static function fields()
{
return array(
'id' => array('type' => 'int', 'primary' => true, 'serial' => true),
'status_id' => array('type' => 'int', 'default' => 0, 'index' => true),
'date_created' => array('type' => 'datetime', 'default' => date('Y-m-d h:m:i'), 'required' => true),
'image_count' => array('type' => 'int', 'default' => 0, 'index' => true),
'name' => array('type' => 'string', 'required' => true),
'slug' => array('type' => 'string', 'required' => true),
);
}
}
内置字段类型
所有基本字段类型都已内置,并提供所有默认功能
字符串整数浮点数/双精度/十进制布尔值文本日期日期时间时间戳年份月份日期
注册自定义字段类型
如果您想在 get/set 上注册具有自定义功能的自定义字段类型,请查看 Spot\Type 命名空间中的类,创建自己的类,并在 Spot\Config 中注册它
$this->setTypeHandler('string', '\Spot\Type\String');
关系类型
实体关系类型包括
HasOneHasManyHasManyThrough
查找器(Mapper)
最常用的查找器是 all,用于返回实体集合,以及 first 或 get,用于返回符合条件的一个实体。
all(entityName, [conditions])
查找所有符合给定条件的 entityName,并返回一个包含加载的 Spot\Entity 对象的 Spot\Entity\Collection。
// Conditions can be the second argument
$posts = $mapper->all('Entity\Post', array('status' => 1));
// Or chained using the returned `Spot\Query` object - results identical to above
$posts = $mapper->all('Entity\Post')->where(array('status' => 1));
// Or building up a query programmatically
$posts = $mapper->all('Entity\Post');
$posts->where(array('date_created :gt', date('Y-m-d'));
... // Do some checks
$posts->limit(10);
由于返回了一个 Spot\Query 对象,因此可以在任何顺序和方式中链接条件和其它语句。查询将在迭代或 count 时懒执行,或者可以通过在链尾调用 execute() 来手动执行。
first(entityName, [conditions])
查找并返回一个符合标准的单个 Spot\Entity 对象。
$post = $mapper->first('Entity\Post', array('title' => "Test Post"));
遍历结果
// Fetch mapper from DI container
$mapper = $di->getShared('mapper');
// Get Query object to add constraints
$posts = $mapper->all('Entity\Posts');
// Find posts where the commenter's user_id is 123
$posts->where(array('user_id :eq', 123));
// Only get 10 results
$limit = (int) $_POST['limit'];
$posts->limit($limit);
// Loop over results
foreach ($posts as $post) {
echo "Title: " . $post->title . "<br>";
echo "Created: " . $post->date_created . "<br>";
}