Models are tasked with providing meaning to otherwise raw and unprocessed data (e.g. user profile). Models expose a consistent and unified API to interact with an underlying datasource (e.g. MongoDB, CouchDB, MySQL) for operations such as querying, saving, updating and deleting data from the persistent storage. Models allow you to interact with your data in two fundamentally different ways: querying, and data mutation (saving/updating/deleting). All query-related operations may be done through the static find() method, along with some additional utility methods provided for convenience. Classes extending this one should, conventionally, be named as Singular, CamelCase and be placed in the app/models directory. i.e. a posts model would be app/model/Post.php. Examples: {{{ Return all 'post' records Post::find('all'); Post::all(); With conditions and a limit Post::find('all', array('conditions' => array('published' => true), 'limit' => 10)); Post::all(array('conditions' => array('published' => true), 'limit' => 10)); Integer count of all 'post' records Post::find('count'); Post::count(); // This is equivalent to the above. With conditions Post::find('count', array('conditions' => array('published' => true))); Post::count(array('published' => true)); }}} The actual objects returned from find() calls will depend on the type of datasource in use. MongoDB, for example, will return results as a Document, while MySQL will return results as a RecordSet. Both of these classes extend a common data\Collection class, and provide the necessary abstraction to make working with either type completely transparent. For data mutation (saving/updating/deleting), the Model class acts as a broker to the proper objects. When creating a new record, for example, a call to Post::create() will return a data\model\Record object, which can then be acted upon. Example: {{{ $post = Post::create(); $post->author = 'Robert'; $post->title = 'Newest Post!'; $post->content = 'Lithium rocks. That is all.'; $post->save(); }}}
또한 보기: lithium\data\entity\Record
또한 보기: lithium\data\entity\Document
또한 보기: lithium\data\collection\RecordSet
또한 보기: lithium\data\collection\DocumentSet
또한 보기: lithium\data\Connections
상속: extends lithium\core\StaticObject
예제 #1
0
 public function testClassInitialization()
 {
     $expected = MockPost::instances();
     MockPost::config();
     $this->assertEqual($expected, MockPost::instances());
     Model::config();
     $this->assertEqual($expected, MockPost::instances());
     $this->assertEqual('mock_posts', MockPost::meta('source'));
     MockPost::config(array('meta' => array('source' => 'post')));
     $this->assertEqual('post', MockPost::meta('source'));
     MockPost::config(array('meta' => array('source' => false)));
     $this->assertIdentical(false, MockPost::meta('source'));
     MockPost::config(array('meta' => array('source' => null)));
     $this->assertIdentical('mock_posts', MockPost::meta('source'));
     MockPost::config();
     $this->assertEqual('mock_posts', MockPost::meta('source'));
     $this->assertTrue(MockPost::meta('connection'));
     MockPost::config(array('meta' => array('source' => 'toreset')));
     MockPost::reset();
     $this->assertEqual('mock_posts', MockPost::meta('source'));
     $this->assertFalse(MockPost::meta('connection'));
     MockPost::config(array('query' => array('with' => array('MockComment'), 'limit' => 10)));
     $expected = array('with' => array('MockComment'), 'limit' => 10, 'conditions' => null, 'fields' => null, 'order' => null, 'page' => null);
     $this->assertEqual($expected, MockPost::query());
     $finder = array('fields' => array('title', 'body'));
     MockPost::finder('myFinder', $finder);
     $result = MockPost::find('myFinder');
     $expected = $finder + array('order' => null, 'limit' => 10, 'conditions' => null, 'page' => null, 'with' => array('MockComment'), 'type' => 'read', 'model' => 'lithium\\tests\\mocks\\data\\MockPost');
     $this->assertEqual($expected, $result['options']);
     $finder = array('fields' => array('id', 'title'));
     MockPost::reset();
     $result = MockPost::finder('myFinder');
     $this->assertNull($result);
 }
예제 #2
0
    public static function __init() {
    /**
	 * The following code will append a library Page model's $_schema and
	 * $validates properites to this Page model. $_schema can never be changed,
	 * only extended. $validates can be changed and extended, but if default
	 * field rules are left out, they will be used from this parent model.
	*/
	$class =  __CLASS__;
	
        /*
        $extended_schema = static::_object()->_schema;
        
	// Loop through and ensure no one forgot to set the form key		
	foreach($extended_schema as $k => $v) {
		$extended_schema[$k] += array('form' => array('position' => 'default'));
	}
	// Append extended schema
	$class::_object()->_schema += $extended_schema;
        */
        
	// Use the library Page model's validation rules combined with the default (but the library gets priority) this way the default rules can be changed, but if left out will still be used (to help make things nicer)
	$class::_object()->validates = static::_object()->validates += $class::_object()->validates;
	// Same for the search schema, the library gets priority, but combine them.
	$class::_object()->search_schema = static::_object()->search_schema += $class::_object()->search_schema;
	
	// Replace any set display name for context
	$class::_object()->display_name = static::_object()->display_name;
	
	// Lock the schema so values that aren't part of it can't be saved to the db.
	self::meta('locked', true);
        
        parent::__init();
    }
예제 #3
0
 public static function __init(array $options = array())
 {
     parent::__init($options);
     $self = static::_instance();
     $self->_finders['count'] = function ($self, $params, $chain) use(&$query, &$classes) {
         $db = Connections::get($self::meta('connection'));
         $records = $db->read('SELECT count(*) as count FROM posts', array('return' => 'array'));
         return $records[0]['count'];
     };
     Post::applyFilter('save', function ($self, $params, $chain) {
         $post = $params['record'];
         if (!$post->id) {
             $post->created = date('Y-m-d H:i:s');
         } else {
             $post->modified = date('Y-m-d H:i:s');
         }
         $params['record'] = $post;
         return $chain->next($self, $params, $chain);
     });
     Validator::add('isUniqueTitle', function ($value, $format, $options) {
         $conditions = array('title' => $value);
         // If editing the post, skip the current psot
         if (isset($options['values']['id'])) {
             $conditions[] = 'id != ' . $options['values']['id'];
         }
         // Lookup for posts with same title
         return !Post::find('first', array('conditions' => $conditions));
     });
 }
예제 #4
0
 /**
  * Override _init to ensure MongoDb indexes
  */
 public static function __init()
 {
     parent::__init();
     $collection = static::connection()->connection->{static::meta('source')};
     $collection->ensureIndex(array('created' => -1, 'username' => 1));
     $collection->ensureIndex(array('tags' => 1));
 }
예제 #5
0
 /**
  * Override _init to ensure MongoDb indexes
  */
 public static function __init()
 {
     parent::__init();
     $collection = static::connection()->connection->{static::meta('source')};
     $collection->ensureIndex(array('index' => 1));
     $collection->ensureIndex(array('app' => 1));
 }
예제 #6
0
 public static function schema($field = null)
 {
     if (is_array($field)) {
         return static::_object()->_schema = $field;
     }
     return parent::schema($field);
 }
예제 #7
0
 public static function schema($field = null)
 {
     $result = parent::schema($field);
     if (is_object($result) && get_class($result) === 'lithium\\data\\Schema') {
         return new Schema(array('fields' => $result->fields(), 'meta' => $result->meta()));
     }
     return $result;
 }
예제 #8
0
 /**
  * Override _init to ensure MongoDb indexes
  */
 public static function __init()
 {
     parent::__init();
     $collection = static::connection()->connection->{static::meta('source')};
     $collection->ensureIndex(array('path' => 1), array('unique' => true));
     $collection->ensureIndex(array('repo' => 1), array('unique' => true));
     $collection->ensureIndex(array('title' => 1));
 }
예제 #9
0
	public static function __init() {
		static::_isBase(__CLASS__, true);
		parent::__init();
		$class = get_called_class();

		if (!static::_isBase($class) && $behaviors = static::_object()->_actsAs) {
			Behaviors::apply($class, $behaviors);
		}
	}
예제 #10
0
 public static function __init()
 {
     parent::__init();
     static::applyFilter('create', function ($self, $params, $chain) {
         if (empty($params['data']['id'])) {
             $params['data']['id'] = String::uuid();
         }
         return $chain->next($self, $params, $chain);
     });
 }
예제 #11
0
 public static function __init()
 {
     parent::__init();
     $class = __CLASS__;
     Validator::add('modelIsSet', function ($value, $format, $options) use($class) {
         if (isset($options['model']) && ($options['model'] = $class)) {
             return true;
         }
         return false;
     });
 }
예제 #12
0
파일: TestModel.php 프로젝트: alkemann/AL13
 public static function __init($options = array())
 {
     $self = static::_instance();
     if (!isset($self->_meta['source'])) {
         $model = get_class($self);
         $tmp = explode('\\', $model);
         $modelName = end($tmp);
         $self->_meta['source'] = \lithium\util\Inflector::tableize($modelName);
     }
     parent::__init($options);
 }
예제 #13
0
 public static function &connection()
 {
     $self = static::_object();
     if ($self->_useRealConnection) {
         return parent::connection();
     }
     if (!$self->_connection) {
         $self->_connection = new MongoDb(array('autoConnect' => false));
     }
     return $self->_connection;
 }
예제 #14
0
 public static function __init(array $options = array())
 {
     parent::__init($options);
     $self = static::_object();
     #		$self = static::_instance(__CLASS__);
     #var_dump($self);
     $self->_finders['count'] = function ($self, $params, $chain) use(&$query, &$classes) {
         $db = Connections::get($self::meta('connection'));
         $records = $db->read('SELECT count(*) as count FROM posts', array('return' => 'array'));
         return $records[0]['count'];
     };
 }
예제 #15
0
 /**
  * Override _init to ensure MongoDb indexes
  */
 public static function __init()
 {
     parent::__init();
     static::finder('slug', function ($self, $params, $chain) {
         $params['options']['conditions'] = array('slug' => $params['options']['conditions']['_id']);
         $data = $chain->next($self, $params, $chain);
         $data = is_object($data) ? $data->rewind() : $data;
         return $data ?: null;
     });
     $collection = static::connection()->connection->{static::meta('source')};
     $collection->ensureIndex(array('title' => 1));
 }
예제 #16
0
 public static function __init()
 {
     $class = __CLASS__;
     // Note: If any of the following properties are not set in any extended model,
     // they will be picked up from this base model.
     $class::_object()->search_schema = static::_object()->search_schema += $class::_object()->search_schema;
     $class::_object()->url_field = static::_object()->url_field;
     $class::_object()->url_separator = static::_object()->url_separator;
     // Future compatibility.
     if (method_exists('\\lithium\\data\\Model', '__init')) {
         parent::__init();
     }
 }
예제 #17
0
 public function testClassInitialization()
 {
     $expected = MockPost::instances();
     MockPost::__init();
     $this->assertEqual($expected, MockPost::instances());
     Model::__init();
     $this->assertEqual($expected, MockPost::instances());
     $this->assertEqual('mock_posts', \lithium\tests\mocks\data\MockPost::meta('source'));
     MockPost::__init(array('source' => 'post'));
     $this->assertEqual('post', MockPost::meta('source'));
     MockPost::__init(array('source' => false));
     $this->assertIdentical(false, MockPost::meta('source'));
     MockPost::__init(array('source' => null));
     $this->assertIdentical('mock_posts', MockPost::meta('source'));
 }
예제 #18
0
 public static function __init(array $options = array())
 {
     parent::__init($options);
     $self = static::_instance();
     Comment::applyFilter('save', function ($self, $params, $chain) {
         $comment = $params['record'];
         if (!$comment->id) {
             $comment->created = date('Y-m-d h:i:s');
         } else {
             $comment->modified = date('Y-m-d h:i:s');
         }
         $params['record'] = $comment;
         return $chain->next($self, $params, $chain);
     });
     Validator::add('validName', '/^[A-Za-z0-9\'\\s]+$/');
 }
예제 #19
0
 public function testClassInitialization()
 {
     $expected = MockPost::instances();
     MockPost::config();
     $this->assertEqual($expected, MockPost::instances());
     Model::config();
     $this->assertEqual($expected, MockPost::instances());
     $this->assertEqual('mock_posts', MockPost::meta('source'));
     MockPost::config(array('source' => 'post'));
     $this->assertEqual('post', MockPost::meta('source'));
     MockPost::config(array('source' => false));
     $this->assertIdentical(false, MockPost::meta('source'));
     MockPost::config(array('source' => null));
     $this->assertIdentical('mock_posts', MockPost::meta('source'));
     MockPost::config();
     $this->assertEqual('mock_posts', MockPost::meta('source'));
     $this->assertEqual('mock-source', MockPost::meta('connection'));
 }
예제 #20
0
 public function addAction()
 {
     $success = false;
     $errors = array();
     if (!self::$_install && $this->request->data) {
         Model::connection()->read(self::$_sql);
         if (!($success = UsersController::addUser($this->request->data['user'], $this->request->data['password'], $errors))) {
             $errors['User'] = "******";
         }
         if ($success && !($success = PostsController::addPost("Post example", self::$_lorem, $errors))) {
             $errors['Post'] = "Post can't be created.";
         }
         if ($success) {
             self::$_install = true;
         }
     }
     return compact('success', 'errors');
 }
예제 #21
0
파일: Model.php 프로젝트: rich97/li3_tree
	/**
	 * init
	 * 
	 * init Tree Callback Methods
	 */
	public static function __init() {
		parent::__init();
		
		$class = get_called_class();
		static::$_tree_config[$class] = array_merge(static::$_tree_defaults, static::$_tree_config);
		
		static::applyFilter('save', function($self,$params,$chain){
        	if($self::beforeSave($self,$params)){
	        	$chain->next($self,$params,$chain);
        	}
        });
        
        static::applyFilter('delete', function($self,$params,$chain){
        	if($self::beforeDelete($self,$params)){
	        	$chain->next($self,$params,$chain);
        	}
        });
	}
예제 #22
0
 /**
  * Catches all context method calls and, if it's proper to call,
  * starts the API request process. Otherwise invokes the method.
  *
  * @access public
  * @param string $method
  * @param array $params
  * @return mixed
  */
 public static function __callStatic($method, $params)
 {
     switch ($method) {
         case 'authenticate':
         case 'ping':
         case 'send':
         case 'query':
         case 'startbatch':
         case 'senditem':
         case 'quicksend':
         case 'endbatch':
         case 'send_bulk':
             $self = static::_object();
             $conn = $self::connection();
             return $conn->invokeMethod($method, $params);
             // forward
             break;
     }
     return parent::__callStatic($method, $params);
     // ignore
 }
예제 #23
0
 public static function __init() {
     self::$fields += static::$fields;
     self::$validate += static::$validate;
     
     parent::__init();
 }
예제 #24
0
	/**
	 * Check related model for validation errors
	 *
	 * @param \lihtuim\data\Entity $entity
	 * @return boolean
	 */
	public function validates($entity, array $options = array()) {
		$success = parent::validates($entity, $options);
		$model = $entity->model();
		foreach ($model::relations() as $related => $relationship) {
			if (!empty($entity->{$related}) && is_object($entity->{$related})) {
				switch ($relationship->type()) {
					case 'hasOne' :
					case 'belongsTo' :
						$success = $entity->{$related}->validates() && $success;
						break;
					case 'hasMany' :
						foreach ($entity->{$related} as $relatedEntity) {
							$success = $relatedEntity->validates() && $success;
						}
						break;
				}
			}
		}
		return $success;
	}
예제 #25
0
 /**
  * Configures this model and the `Service` class.
  *
  * @see lithium\data\Model::config()
  * @param array $config
  * @return void
  */
 public static function config(array $config = array())
 {
     $defaults = array('meta' => array('service' => array('host' => 'en.gravatar.com')));
     $config = array_merge_recursive($defaults, $config);
     parent::config($config);
 }
예제 #26
0
 public static function schema($field = null)
 {
     $schema = parent::schema();
     $schema->append(array('_id' => array('type' => 'id'), 'foo' => array('type' => 'object'), 'foo.bar' => array('type' => 'int')));
     return $schema;
 }
예제 #27
0
 /**
  * Returns a list of models related to `Model`, or a list of models related
  * to this model, but of a certain type. Overwritten to return all/original/alternate relations
  *
  * @param string $name A type of model relation.
  * @param string $type Specify all, original, alternate
  * @return array An array of relation types.
  */
 public static function relations($name = null, $type = 'original')
 {
     if ($type == 'all' || $type == 'alternate') {
         $self = static::_object();
         if ($type == 'all') {
             $relations = array_merge($self->_relations, $self->_alternateRelations);
         } else {
             $relations = $self->_alternateRelations;
         }
         if (!$name) {
             return $relations;
         }
         if (isset($relations[$name])) {
             return $relations[$name];
         }
         if (isset($self->_relationTypes[$name])) {
             return array_keys(array_filter($relations, function ($i) use($name) {
                 return $i->data('type') == $name;
             }));
         }
     }
     return parent::relations($name);
 }
예제 #28
0
 public static function __init()
 {
     static::_isBase(__CLASS__, true);
     parent::__init();
 }
예제 #29
0
 /**
  * Exports an array of custom finders which use the filter system to wrap around `find()`.
  *
  * @return void
  */
 protected static function _findFilters()
 {
     $self = static::_object();
     $_query = $self->_query;
     $default = parent::_findFilters();
     $custom = array('list' => function ($self, $params, $chain) {
         $result = array();
         $meta = $self::meta();
         $name = $meta['key'];
         $options =& $params['options'];
         if (isset($options['field'])) {
             $options['fields'] = (array) $options['field'];
         }
         if ($options['fields'] === null || empty($options['fields'])) {
             list($name, $value) = array($self::meta('key'), null);
         } elseif (count($options['fields']) > 2) {
             list($name, $value) = array_slice($options['fields'], 0, 2);
         } elseif (count($options['fields']) > 1) {
             list($name, $value) = array_slice($options['fields'], 0, 2);
         } elseif (count($options['fields']) == 1) {
             $name = $meta['key'];
             $value = is_array($options['fields']) ? $options['fields'][0] : $options['fields'];
         }
         foreach ($chain->next($self, $params, $chain) as $entity) {
             $key = $entity->{$name};
             $key = is_scalar($key) ? $key : (string) $key;
             $result[$key] = is_null($value) ? $entity->title() : $entity->{$value};
         }
         return $result;
     }, 'random' => function ($self, $params, $chain) {
         $amount = (int) $self::find('count', $params['options']);
         $offset = rand(0, $amount - 1);
         $params['options']['offset'] = $offset;
         return $self::find('first', $params['options']);
     });
     return array_merge($default, $custom);
 }