当前位置:Gxlcms > 数据库问题 > Database ORM

Database ORM

时间:2021-07-01 10:21:17 帮助过:7人阅读

Note that we did not tell ORM which table to use for our User model. The lower-case, plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, ORM will assume the User model stores records in the users table. You may specify a custom table by defining a table property on your model:

    class User extends \Database\ORM\Model {

        protected $table = ‘my_users‘;

    }

Note: ORM will also assume that each table has a primary key column named id. You may define a primaryKey property to override this convention. Likewise, you may define a connection property to override the name of the database connection that should be used when utilizing the model.

Once a model is defined, you are ready to start retrieving and creating records in your table. Note that you will need to place updated_at and created_at columns on your table by default. If you do not wish to have these columns automatically maintained, set the $timestamps property on your model to false.

Retrieving All Models

    $users = User::all();

Retrieving A Record By Primary Key

    $user = User::find(1);

    var_dump($user->name);

Note: All methods available on the QueryBuilder are also available when querying ORM models.

Retrieving A Model By Primary Key Or Throw An Exception

Sometimes you may wish to throw an exception if a model is not found, allowing you to catch the exceptions using an App::error handler and display a 404 page.

    $model = User::findOrFail(1);

    $model = User::where(‘votes‘, ‘>‘, 100)->firstOrFail();

To register the error handler, listen for the ModelNotFoundException

    use Illuminate\Database\ORM\ModelNotFoundException;

    App::error(function(ModelNotFoundException $e)
    {
        return Response::make(‘Not Found‘, 404);
    });

Querying Using ORM Models

    $users = User::where(‘votes‘, ‘>‘, 100)->take(10)->get();

    foreach ($users as $user)
    {
        var_dump($user->name);
    }

ORM Aggregates

Of course, you may also use the query builder aggregate functions.

    $count = User::where(‘votes‘, ‘>‘, 100)->count();

If you are unable to generate the query you need via the fluent interface, feel free to use whereRaw:

    $users = User::whereRaw(‘age > ? and votes = 100‘, array(25))->get();

Chunking Results

If you need to process a lot (thousands) of ORM records, using the chunk command will allow you to do without eating all of your RAM:

    User::chunk(200, function($users)
    {
        foreach ($users as $user)
        {
            //
        }
    });

The first argument passed to the method is the number of records you wish to receive per "chunk". The Closure passed as the second argument will be called for each chunk that is pulled from the database.

Specifying The Query Connection

You may also specify which database connection should be used when running an ORM query. Simply use the on method:

    $user = User::on(‘connection-name‘)->find(1);

Mass Assignment

When creating a new model, you pass an array of attributes to the model constructor. These attributes are then assigned to the model via mass-assignment. This is convenient; however, can be a serious security concern when blindly passing user input into a model. If user input is blindly passed into a model, the user is free to modify any and all of the model‘s attributes. For this reason, all ORM models protect against mass-assignment by default.

To get started, set the fillable or guarded properties on your model.

Defining Fillable Attributes On A Model

The fillable property specifies which attributes should be mass-assignable. This can be set at the class or instance level.

    class User extends \Database\ORM\Model {

        protected $fillable = array(‘first_name‘, ‘last_name‘, ‘email‘);

    }

In this example, only the three listed attributes will be mass-assignable.

Defining Guarded Attributes On A Model

The inverse of fillable is guarded, and serves as a "black-list" instead of a "white-list":

    class User extends \Database\ORM\Model {

        protected $guarded = array(‘id‘, ‘password‘);

    }

Note: When using guarded, you should still never pass Input::get() or any raw array of user controlled input into a save or update method, as any column that is not guarded may be updated.

Blocking All Attributes From Mass Assignment

In the example above, the id and password attributes may not be mass assigned. All other attributes will be mass assignable. You may also block all attributes from mass assignment using the guard property:

    protected $guarded = array(‘*‘);

Insert, Update, Delete

To create a new record in the database from a model, simply create a new model instance and call the save method.

Saving A New Model

    $user = new User;

    $user->name = ‘John‘;

    $user->save();

Note: Typically, your ORM models will have auto-incrementing keys. However, if you wish to specify your own keys, set the incrementing property on your model to false.

You may also use the create method to save a new model in a single line. The inserted model instance will be returned to you from the method. However, before doing so, you will need to specify either a fillable or guarded attribute on the model, as all ORM models protect against mass-assignment.

After saving or creating a new model that uses auto-incrementing IDs, you may retrieve the ID by accessing the object‘s id attribute:

    $insertedId = $user->id;

Setting The Guarded Attributes On The Model

    class User extends \Database\ORM\Model {

        protected $guarded = array(‘id‘, ‘account_id‘);

    }

Using The Model Create Method

    // Create a new user in the database...
    $user = User::create(array(‘name‘ => ‘John‘));

    // Retrieve the user by the attributes, or create it if it doesn‘t exist...
    $user = User::firstOrCreate(array(‘name‘ => ‘John‘));

    // Retrieve the user by the attributes, or instantiate a new instance...
    $user = User::firstOrNew(array(‘name‘ => ‘John‘));

Updating A Retrieved Model

To update a model, you may retrieve it, change an attribute, and use the save method:

    $user = User::find(1);

    $user->email = ‘john@foo.com‘;

    $user->save();

Saving A Model And Relationships

Sometimes you may wish to save not only a model, but also all of its relationships. To do so, you may use the push method:

    $user->push();

You may also run updates as queries against a set of models:

    $affectedRows = User::where(‘votes‘, ‘>‘, 100)->update(array(‘status‘ => 2));

Deleting An Existing Model

To delete a model, simply call the delete method on the instance:

    $user = User::find(1);

    $user->delete();

Deleting An Existing Model By Key

    User::destroy(1);

    User::destroy(array(1, 2, 3));

    User::destroy(1, 2, 3);

Of course, you may also run a delete query on a set of models:

    $affectedRows = User::where(‘votes‘, ‘>‘, 100)->delete();

Updating Only The Model‘s Timestamps

If you wish to simply update the timestamps on a model, you may use the touch method:

    $user->touch();

Soft Deleting

When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at timestamp is set on the record. To enable soft deletes for a model, specify the softDelete property on the model:

    class User extends \Database\ORM\Model {

        protected $softDelete = true;

    }

To add a deleted_at column to your table, you may use the softDeletes method from a migration:

    $table->softDeletes();

Now, when you call the delete method on the model, the deleted_at column will be set to the current timestamp. When querying a model that uses soft deletes, the "deleted" models will not be included in query results.

Forcing Soft Deleted Models Into Results

To force soft deleted models to appear in a result set, use the withTrashed method on the query:

    $users = User::withTrashed()->where(‘account_id‘, 1)->get();

The withTrashed method may be used on a defined relationship:

    $user->posts()->withTrashed()->get();

If you wish to only receive soft deleted models in your results, you may use the onlyTrashed method:

    $users = User::onlyTrashed()->where(‘account_id‘, 1)->get();

To restore a soft deleted model into an active state, use the restore method:

    $user->restore();

You may also use the restore method on a query:

    User::withTrashed()->where(‘account_id‘, 1)->restore();

Like with withTrashed, the restore method may also be used on relationships:

    $user->posts()->restore();

If you wish to truly remove a model from the database, you may use the forceDelete method:

    $user->forceDelete();

The forceDelete method also works on relationships:

    $user->posts()->forceDelete();

To determine if a given model instance has been soft deleted, you may use the trashed method:

    if ($user->trashed())
    {
        //
    }

Timestamps

By default, ORM will maintain the created_at and updated_at columns on your database table automatically. Simply add these timestamp columns to your table and ORM will take care of the rest. If you do not wish for ORM to maintain these columns, add the following property to your model:

Disabling Auto Timestamps

    class User extends \Database\ORM\Model {

        protected $table = ‘users‘;

        public $timestamps = false;

    }

Providing A Custom Timestamp Format

If you wish to customize the format of your timestamps, you may override the getDateFormat method in your model:

    class User extends \Database\ORM\Model {

        protected function getDateFormat()
        {
            return ‘U‘;
        }

    }

Query Scopes

Defining A Query Scope

Scopes allow you to easily re-use query logic in your models. To define a scope, simply prefix a model method with scope:

    class User extends \Database\ORM\Model {

        public function scopePopular($query)
        {
            return $query->where(‘votes‘, ‘>‘, 100);
        }

        public function scopeWomen($query)
        {
            return $query->whereGender(‘W‘);
        }

    }

Utilizing A Query Scope

    $users = User::popular()->women()->orderBy(‘created_at‘)->get();

Dynamic Scopes

Sometimes You may wish to define a scope that accepts parameters. Just add your parameters to your scope function:

    class User extends \Database\ORM\Model {

        public function scopeOfType($query, $type)
        {
            return $query->whereType($type);
        }

    }

Then pass the parameter into the scope call:

    $users = User::ofType(‘member‘)->get();

Relationships

Of course, your database tables are probably related to one another. For example, a blog post may have many comments, or an order could be related to the user who placed it. ORM makes managing and working with these relationships easy. Nova Framework supports many types of relationships:

  • One To One
  • One To Many
  • Many To Many
  • Has Many Through
  • Polymorphic Relations
  • Many To Many Polymorphic Relations

One To One

Defining A One To One Relation

A one-to-one relationship is a very basic relation. For example, a User model might have one Phone. We can define this relation in ORM:

    class User extends \Database\ORM\Model {

        public function phone()
        {
            return $this->hasOne(‘Phone‘);
        }

    }

The first argument passed to the hasOne method is the name of the related model. Once the relationship is defined, we may retrieve it using ORM‘s dynamic properties:

    $phone = User::find(1)->phone;

The SQL performed by this statement will be as follows:

    select * from users where id = 1

    select * from phones where user_id = 1

Take note that ORM assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:

    return $this->hasOne(‘Phone‘, ‘foreign_key‘);

    return $this->hasOne(‘Phone‘, ‘foreign_key‘, ‘local_key‘);

Defining The Inverse Of A Relation

To define the inverse of the relationship on the Phone model, we use the belongsTo method:

    class Phone extends \Database\ORM\Model {

        public function user()
        {
            return $this->belongsTo(‘User‘);
        }

    }

In the example above, ORM will look for a user_id column on the phones table. If you would like to define a different foreign key column, you may pass it as the second argument to the belongsTo method:

    class Phone extends \Database\ORM\Model {

        public function user()
        {
            return $this->belongsTo(‘User‘, ‘local_key‘);
        }

    }

Additionally, you pass a third parameter which specifies the name of the associated column on the parent table:

    class Phone extends \Database\ORM\Model {

        public function user()
        {
            return $this->belongsTo(‘User‘, ‘local_key‘, ‘parent_key‘);
        }

    }

One To Many

An example of a one-to-many relation is a blog post that "has many" comments. We can model this relation like so:

    class Post extends \Database\ORM\Model {

        public function comments()
        {
            return $this->hasMany(‘Comment‘);
        }

    }

Now we can access the post‘s comments through the dynamic property:

    $comments = Post::find(1)->comments;

If you need to add further constraints to which comments are retrieved, you may call the comments method and continue chaining conditions:

    $comments = Post::find(1)->comments()->where(‘title‘, ‘=‘, ‘foo‘)->first();

Again, you may override the conventional foreign key by passing a second argument to the hasMany method. And, like the hasOne relation, the local column may also be specified:

    return $this->hasMany(‘Comment‘, ‘foreign_key‘);

    return $this->hasMany(‘Comment‘, ‘foreign_key‘, ‘local_key‘);

Defining The Inverse Of A Relation

To define the inverse of the relationship on the Comment model, we use the belongsTo method:

    class Comment extends \Database\ORM\Model {

        public function post()
        {
            return $this->belongsTo(‘Post‘);
        }

    }

Many To Many

Many-to-many relations are a more complicated relationship type. An example of such a relationship is a user with many roles, where the roles are also shared by other users. For example, many users may have the role of "Admin". Three database tables are needed for this relationship: users, roles, and role_user. The role_user table is derived from the alphabetical order of the related model names, and should have user_id and role_id columns.

We can define a many-to-many relation using the belongsToMany method:

    class User extends \Database\ORM\Model {

        public function roles()
        {
            return $this->belongsToMany(‘Role‘);
        }

    }

Now, we can retrieve the roles through the User model:

    $roles = User::find(1)->roles;

If you would like to use an unconventional table name for your pivot table, you may pass it as the second argument to the belongsToMany method:

    return $this->belongsToMany(‘Role‘, ‘user_roles‘);

You may also override the conventional associated keys:

    return $this->belongsToMany(‘Role‘, ‘user_roles‘, ‘user_id‘, ‘foo_id‘);

Of course, you may also define the inverse of the relationship on the Role model:

    class Role extends \Database\ORM\Model {

        public function users()
        {
            return $this->belongsToMany(‘User‘);
        }

    }

Has Many Through

The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a Country model might have many Posts through a Users model. The tables for this relationship would look like this:

    countries
        id - integer
        name - string

    users
        id - integer
        country_id - integer
        name - string

    posts
        id - integer
        user_id - integer
        title - string

Even though the posts table does not contain a country_id column, the hasManyThrough relation will allow us to access a country‘s posts via $country->posts. Let‘s define the relationship:

    class Country extends \Database\ORM\Model {

        public function posts()
        {
            return $this->hasManyThrough(‘Post‘, ‘User‘);
        }

    }

If you would like to manually specify the keys of the relationship, you may pass them as the third and fourth arguments to the method:

    class Country extends \Database\ORM\Model {

        public function posts()
        {
            return $this->hasManyThrough(‘Post‘, ‘User‘, ‘country_id‘, ‘user_id‘);
        }

    }

Polymorphic Relations

Polymorphic relations allow a model to belong to more than one

人气教程排行