martynbiz / php-mongo
PHP ODM for MongoDB.
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: 4.8.*
This package is not auto-updated.
Last update: 2024-12-21 19:26:40 UTC
README
Install with composer
$ composer require martynbiz/php-mongo
Getting started
Create connection
\MartynBiz\Mongo\Connection::getInstance()->init(array( 'db' => 'mydb', 'username' => 'myuser', 'password' => '89dD7HH7di!89', 'classmap' => array( 'users' => '\\App\\Model\\User', ), ));
Create model
Create models by extending the Mongo class, be sure to define $collection and $whitelist:
<?php use MartynBiz\Mongo; class User extends Mongo { // required - collection this model refers to protected static $collection = 'users'; // required - define on the fields that can be saved protected static $whitelist = array( 'name', 'email', 'username', 'password', ); }
Create multiple connections
If only using a single database, this is not neccessary. However, if you need to connect to multiple databases, give a unique name to each connection:
Connection::getInstance('conn1')->init(array( ... )); // also, checking if an instance exists if (! Connection::hasInstance('conn2')) { Connection::getInstance('conn2')->init(array( ... )); }
Also, remember to declare which $conn in the model:
<?php use MartynBiz\Mongo; class User extends mongo { // optional - if using multiple connections/databases protected static $conn = 'conn1'; . . . }
Queries
Find by mongo query
// statically $users = User::find(array( 'status' => 1, )); // dynamically $col = new User(); $users = $col->find(array( 'status' => 1, ));
Find one by mongo query
// statically $user = User::findOne(array( 'email' => 'info@examle.com', )); // dynamically $col = new User(); $user = $col->findOne(array( 'email' => 'info@examle.com', ));
Finding by object
Model instances can also be passed, the find method will convert it to DBRef internally (e.g. 'friend' => $friend will do the same as 'friend' => $friend->getDBRef())
$friend = User::findOne(array( //... )); $user = User::find(array( 'friend' => $friend, ));
Getting and setting values
// setting // on instantiation -- will be filtered against $whitelist $article = new Article(array( 'title' => 'My title', )); $author = User::findOne(array( //... )); // single value properties -- no param filtering $article->status = 2; $article->author = $author; // AND/OR set() method, with Mongo instance -- suited for unit testing, no param filtering $user = User::findOne(array( //... )); $article->set('author', $author); // set value as query result (will be stored as an array of dbrefs) $tags = Tag::find(array( //... )); $article->tags = $tags; // lastly, params can be passed with save() -- will be filtered against $whitelist $article->save(array( 'content' => $text, ))
// getting $article = Article::findOne(array( //... )); // single value properties -- no param filtering echo $article->status; echo $article->author->name; echo $article->tags[0]->name; echo $article->get('author');
Inserting
Save method is used on an instantiated object of the model class. It can be called after assigning values to properties, or by passing name/values as arguments. Note: when passing name/values, values will be whitelisted
$user->name = 'Jim'; $user->save();
$user->save(array( 'name' => 'Jim', ));
Create method doesn't require an instance, by will accept name\values upon which it will insert into the collection. It will return an instance of the created document. Note: when passing name/values, values will be whitelisted
// statically $user = User::create(array( 'name' => 'Jim', )); // dynamically (e.g. service locator pattern, or DI) $col = new User(); $user = $col->create(array( 'name' => 'Jim', ));
Factory method doesn't actually insert, but will generate an instance with values. It can then be altered and inserted with it's save method:
// statically $user = User::factory(array( 'name' => 'Jim', )); // dynamically $col = new User(); $user = $col->factory(array( 'name' => 'Jim', )); $user->save();
Although having multiple methods may seem a little much, it does give the option to keep you code tidy and more flexible for mocking methods during testing.
Push
Note: push with $each is the default behaviour here, although this can be overridden with 'each'=>false in the options array (see below)
// push one object, will convert to DBRef $user->push(array( 'friends' => $friend, )); // push multi object, will convert to DBRef $user->push(array( 'friends' => array( $friend, $friend2, ), )); // push MongoIterator object (from find() call) $user->push(array( 'friends' => $friends, )); // push multiple properties at once $user->push(array( 'friends' => $friends, 'enemies' => $enemies, )); // push without $each setting, will push the whole array as a single element $user->push(array( 'friends' => array( $friend, $friend2, ), ), array('each' => false));
Deleting
An instance can delete itself from the database with the delete method:
$user->delete();
To delete multiple documents from a collection by query, use the remove method:
User::remove(array( 'type' => 'boring', ), $options);
Convert to array
$user->toArray(3); // convert nested 3 deep to array (optional)
Validation
Before saving to the database, the validate method is called. If it returns false, the data will not be saved.
class User extends mongo { . . . public function validate() { $this->resetErrors(); if (empty($this->data['name'])) { $this->setError('Name is missing.'); } return empty( $this->getErrors() ); // true if none } }
The following example uses martynbiz/php-validator library here.
<?php use MartynBiz\Validator; class User extends mongo { . . . public function validate() { $this->resetErrors(); $validator = new Validator($this->data); $validator->check('name') ->isNotEmpty('Name is missing'); $validator->check('email') ->isNotEmpty('Email address is missing') ->isEmail('Invalid email address'); $message = 'Password must contain upper and lower case characters, and have more than 8 characters'; $validator->check('password') ->isNotEmpty($message) ->hasLowerCase($message) ->hasUpperCase($message) ->hasNumber($message) ->isMinimumLength($message, 8); // update the model's errors with the validators $this->setError( $validator->getErrors() ); return empty($this->getErrors()); } }
Custom Getter/ Setter
To automatically convert values when getting, you can define custom methods to automatically convert the value of a property. This may be useful when formatting strings such as dates to human readable.
<?php use MartynBiz\Mongo; class User extends Mongo { . . . public function getCreatedAt($value) { return date('Y-M-d h:i:s', $this->data['created_at']->sec); } public function setPassword($value) { return password_hash($value, PASSWORD_BCRYPT); } }
TODO
- dot syntax support? find(array('model.name' => 'Martyn')), set/get(array(model.name' => 'Martyn'))