Documentation Framecore

Documentation on working with FrameCore. Setting up and using classes. Development of applications based on this platform

Models

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%'])






Return Back