A model represents the information (data) of the application and the rules to manipulate that data.
Working with models
In the realm of application development, a model serves as an embodiment of valuable information (commonly known as data) and delineates the regulations that govern the manipulation of said data. Models serve a pivotal purpose in administering the protocols for interacting with a designated database table. As a general practice, it is customary for every individual table within your database to align with a solitary model within your application, fostering a seamless correlation between the two entities.
Creating Models
A model is a class that extends from Spotsystem\Model.
<?php namespace Models\Cars; use Spotsystem\Models; class CarParts extends Models { }
By default, the model Models\Cars\CarParts will map to the table car_parts. If you want to manually specify another name for the mapped table, you can use the setSource() method:
<?php namespace Models\Cars; use Spotsystem\Models; class CarParts extends Models { public function init() { $this->setSource('cars_table_new'); } }
The init() method helps with setting up this model with a custom behavior i.e. a different table.
$this->setSource('cars_table_new') will set custom name table for current model
Initialization columns and sets before working with model (methods set need to be include for each columns)
<?php namespace Models\Cars; use Spotsystem\Models; class CarParts extends Models { protected $id; protected $car_id; protected $part_name; public function setId($id) { $this->id = (int)$id; } public function setCarId($car_id) { $this->car_id = (int)$car_id; } public function setPartName($part_name) { $this->part_name = (string)$part_name; } ..... your methods here ..... }
This means that we have three fields in the table with corresponding names id, car_id, part_name
Understanding Records To Objects
You could find a certain record by its primary key and then print its part_name:
<?php use Models\Cars\CarParts; $parts = (new CarParts)->findFirst(5); echo $parts->part_name;
First parameter can be as INT or array parameters for select from selected model, second parameter is optional (if second parameter is true - model will show prepared sql request as string)
Once the record is in memory, you can make modifications to its data and then save changes:
<?php use Models\Cars\CarParts; $parts = (new CarParts)->findFirst(5); $parts->part_name = "body"; $parts->save();
Finding records
Spotsystem\Models also offers several methods for querying records. The following examples will show you how to query one or more records from a model:
<?php use Models\Cars\CarParts; //how many parts? $parts = (new CarParts)->find(); echo count($parts); //how many body parts? $parts = new Users; $data = $parts->find([ 'conditions'=>'part_name = :part_name', 'bind'=>[ 'part_name'=>'body' ] ]); echo count($data); //get records with part name body and id, with order, sort and limit $parts = new Users; $data = $parts->find([ 'columns'=>'id,part_name', 'conditions'=>'part_name = :part_name', 'bind'=>[ 'part_name'=>'body' ] 'order'=>'id', 'sort'=>'desc' ]); foreach($data as $part) { echo $part->name; }
You could also use the findFirst() method to get only the first record matching the given criteria:
<?php use Models\Cars\CarParts; $parts = (new CarParts)->findFirst(1); echo $parts->part_name; $parts = new Users; $data = $parts->findFirst([ 'conditions'=>'part_name = :part_name', 'bind'=>[ 'part_name'=>'body' ] ]); echo $data->part_name;
The available query options are:
'columns' => 'id, name,...' 'conditions' => 'id =:id AND name = :name' (use with binds placeholders) 'bind'=>['id'=>1,'name'=>'some string'] 'order'=>'id' 'sort'=>'asc' 'group'=>'name' 'limit'=>100 'offset'=>10
Some simple example:
$users = new \Models\Users(); $collection = $users->find([ 'columns'=>'id,username', 'condition'=>'active = :active AND is_blocked = :is_blocked', 'bind'=>[ 'active'=>1, 'is_blocked'=>0 ], 'order'=>'username', 'sort'=>'desc' ]); foreach($collection as $user) { echo $user->username; }
Method save(lastinsertid = false, update = false, showSql = false)
$user = new \Models\Users(); $user->username = 'John Doe'; $user->save();
This function will create new record in table Users
Updating records
$user = new \Models\Users(); $user->id = 1; $user->username = 'John Doe'; $user->save(false,true); OR $user->update(); OR $users = (new \Models\Users)->find([ 'condition'=>'active = :active', 'bind => ['active'=>1] ]); foreach($users as $user) { $user->active = 0; $user->save(false, true); //or $user->update(); } OR $model = new \Models\Users; $users = $model->find([ 'condition'=>'active = :active', 'bind => ['active'=>1] ]); foreach($users as $user) { $model->id = $user->id; $model->active = 0; if($model->update() === false) { print_r($model->getMessages()); } }
Insert new record and get last insert id
$user = new \Models\Users(); $user->username = 'John Doe'; $user->save(true); //deprecated $id = $user->getLastInsertId(); OR $user->id
Deleting records
$user = (new \Models\Users)->findFirst(5); $user->delete(); OR $users = (new \Models\Users)->find([ 'condition'=>'active = :active', 'bind => ['active'=>1] ]); foreach($users as $user) { $user->delete(); }
Catching errors when operate with models
if (!$model->save()) { print_r($model->getMessages()); }
Relationships
In your models you can use relationships. Spotsystem\Models has two methods hasOne and hasMany. This params need to initialize if need in model method init()
using hasOne. If you need relationship for your model with finding one record by some column id (as example, if you use this column id as foreign key) - you can use this method, where in response will see finding alias model
Example. In your model you need set needed relationships
<?php namespace Models\Cars; use Spotsystem\Models; class CarParts extends Models { ..... public function init() { $this->hasOne( 'car_id', Cars::class, 'id', [ 'alias' => 'Cars', ] ); } ..... }
And try request data
$model = (new \Models\CarParts())->findFirst(1); print_r($data); //In response you will see stdClass Object ( [id] => 1 [car_id] => 5 [part_name] => "Body" [Cars] => stdClass Object ( [id] => 5 [name] => "Car name" [max_speed] => 230 ..... ) )
Or you cal use hasMany if target column id in request model has more than one records
<?php namespace Models\Cars; use Spotsystem\Models; class Cars extends Models { ..... public function init() { $this->hasMany( 'id', CarParts::class, 'car_id', [ 'alias' => 'CarParts', ] ); } ..... }
In response you will see
$model = (new \Models\Cars())->findFirst(1); print_r($data); //In response you will see stdClass Object ( [id] => 1 [name] => "Car name" [max_speed] => 230 ..... [CarParts] => stdClass Object 0 => ( [id] => 10 [car_id] => 1 [part_name] => Body ..... ), 1 => ( [id] => 11 [car_id] => 1 [part_name] => Hood ), ....... )
Using paramaters in relationships
$this->hasOne( string|array field current model, string|void target class (reference model), string|array filed target class (reference model), array() parameters (options) => [ bool reusable -> optional, if you need cache related data string alias -> required, name for your alias array|int params -> optional, parameter search in reference model ] ) //hasMany parameters the same
Important.
if the model uses parameters protected for column - and you want to use model directly after some query - you need use __set and __get methods for columns
// In your model ... class User extends Model protected id; protected name; public function setId($id) { $this->id = (int) $id; } public function setName($name) { $this->name = (string) $name; } public function getId() { return $this->id; } public function getName() { return $this->name; } .... //After you can use model directly $user = (new Users)->findFirst(1); $user->name = 'New Name'; $user->update(); OR foreach((new Users)->find() as $user) { $user->activity = (new DateTime)->format('Y-m-d'); $user->save(); } //otherwise without methods __set and __get $model = new User; $model->id = 1; $model->name = 'New Name'; $model->update();
Additional methods for models: afterFetch, beforeSave, afterSave
Warning! Methods will be available in future (afterFetch, beforeSave, afterSave)
The afterFetch method will run right after the data populates the model from the database. We can utilize this method to modify or transform the data in the model.
public function afterFetch() { $this->name = json_decode($this->name); } public function beforeSave() { $this->name = json_decode($this->name); } public function afterSave() { $this->name = json_decode($this->name); }
Using methods count, sum, average, maximum, minimum
echo (new Users)->count(); echo (new Users)->count(['columns'=>'failed_attempt']); // will show count all records OR (new Users)->count(['conditions'=>'name like %:name%'])