• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Model / Entities relation

#1
Hi guys,

on alpha5, I don't think that the entities object is correctly populated.

If my model return an entity or an object and fill the entity.
No fields are casted
No fileds are datamaped
dates aren't muted to TimeObject

Maybe i don't understand something.

2 cases :
I request my model with an object and fill my entity :
$_options in my entity is ignored.

response from my controller :
Code:
{
   "success": true,
   "message": "",
   "data": {
       "firstname": "Darth",
       "lastname": "Vader",
       "username": null,
       "email": "[email protected]",
       "created_at": "2019-02-08 12:27:42",
       "deleted": "0"
   }
}

If i add setter and getter like that in my entity

PHP Code:
public function setCreatedAt(string $dateString)
 
   {
 
       $this->created_at = new Time($dateString'UTC');

 
       return $this;
 
   }

 
   public function getCreatedAt(string $format 'Y-m-d H:i:s')
 
   {
 
       // Convert to CodeIgniter\I18n\Time object
 
       $this->created_at $this->mutateDate($this->created_at);

 
       $timezone $this->timezone ?? app_timezone();

 
       $this->created_at->setTimezone($timezone);

 
       return $this->created_at->format($format);
 
   

my controller return :

Code:
{
   "success": true,
   "message": "",
   "data": {
       "firstname": "Darth",
       "lastname": "Vader",
       "username": null,
       "email": "[email protected]",
       "created_at": {
           "date": "2019-02-08 12:27:42.000000",
           "timezone_type": 3,
           "timezone": "UTC"
       },
       "deleted": "0"
   }
}

OK : created_at is now muted to TimeObject


I request my model with entity in $returnType :

Only fileds are populated setter and getter are not interpreted and $_options is just ignored.

My files :

Models/UserModel.php
PHP Code:
<?php namespace App\Models;

use 
CodeIgniter\Model;

class 
UserModel extends Model
{

 
   /**
     * Model Configuration
     */
 
   protected $table      'users';
 
   protected $primaryKey 'id';
 
   protected $returnType '\App\Entities\User';
 
   protected $allowedFields = ['firstname''lastname''username''email''password'];

 
   protected $useSoftDeletes true;
 
   protected $dateFormat 'datetime';
 
   protected $useTimestamps true;

 
   protected $skipValidation     false;
 
   protected $validationRules    = [
 
       'firstname'    => 'required|min_length[3]',
 
       'lastname'     => 'required|min_length[3]',
 
       'username'     => 'required|alpha_numeric_space|min_length[3]',
 
       'email'        => 'required|valid_email|is_unique[users.email,id,{id}]',
 
       'password'     => 'required|min_length[8]',
 
       // 'password_confirm' => 'required_with[password]|matches[password]'
 
       // 'password_confirm' => 'matches[password]'
 
   ];

 
   protected $validationMessages = [
 
       'email'        => [
 
           'is_unique' => 'Sorry. That email has already been taken. Please choose another.'
 
       ]
 
   ];

 
   protected $afterDelete = ['updateDeletedAt'];


 
   /**
     * Protected & internals methods
     */

 
   protected function updateDeletedAt(array $data)
 
   {
 
       if (! isset($data['id']) ) return $data;

 
       $this->builder()
 
           ->whereIn('id'$data['id'])
 
           ->set(['deleted_at' => date('Y-m-d H:i:s')])
 
           ->update();

 
       return $data;
 
   }


Entities/User.php

PHP Code:
<?php namespace App\Entities;

use 
CodeIgniter\Entity;

class 
User extends Entity
{
 
   protected $id;
 
   public $firstname;
 
   public $lastname;
 
   public $username;
 
   public $email;
 
   protected $password;
 
   public $created_at;
 
   protected $updated_at;
 
   public $deleted;
 
   protected $deleted_at;

 
   protected $_options = [
 
       'datamap' => [
 
           'full_name' => 'username'
 
       ],
 
       'dates' => ['created_at''updated_at''deleted_at'],
 
       'casts' => [
 
           'deleted' => 'boolean'
 
       ],
 
   ];

 
   public function setPassword(string $pass)
 
   {
 
       $this->password password_hash($passPASSWORD_BCRYPT);
 
       return $this;
 
   }



Controller/Users.php
PHP Code:
<?php
namespace App\Controllers;

use 
CodeIgniter\Controller;
use 
CodeIgniter\API\ResponseTrait;

use 
Restserver\Libraries\Format;

use 
App\Models\UserModel;
use 
App\Entities\User;

class 
Users extends Controller
{

 
   /**
     * Entry point for users listing
     */
 
   public function index()
 
   {
 
       $userModel = new UserModel();
 
       $users $userModel->findAll();

 
       $data = [
 
           'success' => true,
 
           'message' => '',
 
           'data' => $users,
 
       ];

 
       return $this->response->setStatusCode(Format::HTTP_OK)->setJSON($data);
 
   }

 
   /**
     * Entry point for specific user
     */
 
   public function show($id)
 
   {
 
       $userModel = new UserModel();
 
       $user $userModel->find($id);
 
       // $user->myDate = $user->created_at->humanize();

 
       if ($user){
 
           $data = [
 
               'success' => true,
 
               'message' => '',
 
               'data' => $user,
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_OK)->setJSON($data);
 
       }else{
 
           $data = [
 
               'success' => false,
 
               'message' => 'user_not_found',
 
               'data' => []
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_NOT_FOUND)->setJSON($data);
 
       }

 
   }

 
   /**
     * Entry point for user creation
     */
 
   public function create()
 
   {
 
       $data $this->request->getPost();

 
       // var_dump($data);die;

 
       $userModel = new UserModel();
 
       $userEntity = new User();

 
       if ($userEntity->fill($data)){
 
           if ($userModel->save($userEntity) !== false){

 
               $data = [
 
                   'success' => true,
 
                   'message' => 'resources_created',
 
                   'data' => [],
 
               ];

 
               return $this->response->setStatusCode(Format::HTTP_CREATED)->setJSON($data);
 
           }else{
 
               $data = [
 
                   'success' => false,
 
                   'message' => 'resources_not_created',
 
                   'data' => $userModel->errors(),
 
               ];

 
               return $this->response->setStatusCode(Format::HTTP_NOT_ACCEPTABLE)->setJSON($data);
 
           }
 
       }else{
 
           $data = [
 
               'success' => false,
 
               'message' => 'resource_dont_match',
 
               'data' => [],
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_BAD_REQUEST)->setJSON($data);
 
       }

 
   }

 
   /**
     * Entry point for user update
     */
 
   public function update($id)
 
   {
 
       $data $this->request->getRawInput();

 
       $userModel = new UserModel();
 
       $userEntity = new User();

 
       if ($userEntity->fill($data)){

 
           if ($userModel->save($userEntity) !== false){
 
               $data = [
 
                   'success' => true,
 
                   'message' => 'resources_updated',
 
                   'data' => ['id' => $id],
 
               ];

 
               return $this->response->setStatusCode(Format::HTTP_OK)->setJSON($data);
 
           }else{
 
               $data = [
 
                   'success' => false,
 
                   'message' => 'resource_not_updated',
 
                   'data' => $userModel->errors(),
 
               ];

 
               return $this->response->setStatusCode(Format::HTTP_NOT_ACCEPTABLE)->setJSON($data);
 
           }
 
       }else{
 
           $data = [
 
               'success' => false,
 
               'message' => 'resource_dont_match',
 
               'data' => [],
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_BAD_REQUEST)->setJSON($data);
 
       }
 
   }

 
   /**
     * Entry point for user delete
     */
 
   public function delete($id)
 
   {
 
       $userModel = new UserModel();

 
       if ($userModel->delete($id) !== false){
 
           $data = [
 
               'success' => true,
 
               'message' => 'resources_deleted',
 
               'data' => ['id' => $id],
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_OK)->setJSON($data);
 
       }else{
 
           $data = [
 
               'success' => false,
 
               'message' => 'resource_not_deleted',
 
               'data' => [],
 
           ];

 
           return $this->response->setStatusCode(Format::HTTP_NOT_ACCEPTABLE)->setJSON($data);
 
       }
 
   }


 
   //--------------------------------------------------------------------
 
   // End of file Users.php
 
   //--------------------------------------------------------------------

Reply

#2
you need to use the magic setter/getter in your entity to use _options

just change your "public" entity properties to protected.

Docu: "You may have noticed that the User class has all of the properties as protected not public, but you can still access them as if they were public properties. The base class, CodeIgniterEntity, takes care of this for you, as well as providing the ability to check the properties with isset(), or unset() the property."

Note: if you access a public entity properties you ignore mapping, casting and calling custom implementation methods.
Reply

#3
(02-22-2019, 04:10 AM)puschie Wrote: you need to use the magic setter/getter in your entity to use _options

ok, i will give a try, thx for the advise Smile


Edit :

Nope... that doesn't work as wanted...

Entities/User.php

PHP Code:
<?php namespace App\Entities;

use 
CodeIgniter\Entity;
use 
CodeIgniter\I18n\Time;

class 
User extends Entity
{
    protected 
$id;
    protected 
$firstname;
    protected 
$lastname;
    protected 
$username;
    protected 
$email;
    protected 
$password;
    protected 
$created_at;
    protected 
$updated_at;
    protected 
$deleted;
    protected 
$deleted_at;

    protected 
$_options = [
        
'datamap' => [
            
'username' => 'full_name',
        ],
        
'dates'   => [
            
'created_at',
            
'updated_at',
            
'deleted_at',
        ],
        
'casts'   => [
            
'deleted' => 'boolean',
        ],
    ];

    public function 
__get(string $key)
    {
        if (
property_exists($this$key))
        {
            return 
$this->$key;
        }
    }

    public function 
__set(string $key$value NULL)
    {
        if (
property_exists($this$key))
        {
            
$this->$key $value;
        }
    }


result in Json

Code:
{
  "success": true,
  "message": "",
  "data": [
    {},
    {}
  ]
}

So the model find 2 Users, but can't access to property :/
Reply

#4
you override the magic methods of the Entity class in your User entity - try your original version with protected members:
PHP Code:
<?php namespace App\Entities;

use 
CodeIgniter\Entity;

class 
User extends Entity
{
 
   protected $id;
 
   protected $firstname;
 
   protected $lastname;
 
   protected $username;
 
   protected $email;
 
   protected $password;
 
   protected $created_at;
 
   protected $updated_at;
 
   protected $deleted;
 
   protected $deleted_at;

 
   protected $_options = [
 
       'datamap' => [
 
           'full_name' => 'username'
 
       ],
 
       'dates' => ['created_at''updated_at''deleted_at'],
 
       'casts' => [
 
           'deleted' => 'boolean'
 
       ],
 
   ];

 
   public function setPassword(string $pass)
 
   {
 
       $this->password password_hash($passPASSWORD_BCRYPT);
 
       return $this;
 
   }



PS: if this doesnt work pls provide more details about what went wrong. apart your model property visibility everything else looks valid to me
Other Ref: https://github.com/lonnieezell/myth-auth...s/User.php
Reply

#5
Sooooo... I had a difference beetween my $returnType ( returnType = "\App\Entities\User"; ) and lonnieezell User Entity ( returnType = User::class; ) but it makes no difference.

In my controller :

var_dump( var_dump($data['data'][0]->created_at); )
Code:
object(CodeIgniter\I18n\Time)#62 (6) {
  ["timezone":protected]=>
  object(DateTimeZone)#64 (2) {
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(12) "Europe/Paris"
  }
  ["locale":protected]=>
  string(2) "fr"
  ["toStringFormat":protected]=>
  string(19) "yyyy-MM-dd HH:mm:ss"
  ["date"]=>
  string(26) "2019-02-08 12:27:42.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(12) "Europe/Paris"
}
Good things thats work as expected.


print_r( $data )
Code:
Array
(
    [success] => 1
    [message] =>
    [data] => Array
        (
            [0] => App\Entities\User Object
                (
                    [id:protected] => 1
                    [firstname:protected] => Darth
                    [lastname:protected] => Vader
                    [username:protected] =>
                    [email:protected] => [email protected]
                    [password:protected] => 5e884898da28047151d0e56f8dc6292
                    [created_at:protected] => 2019-02-08 12:27:42
                    [updated_at:protected] =>
                    [deleted:protected] => 0
                    [deleted_at:protected] =>
                    [_options:protected] => Array
                        (
                            [datamap] => Array
                                (
                                )

                            [dates] => Array
                                (
                                    [0] => created_at
                                    [1] => updated_at
                                    [2] => deleted_at
                                )

                            [casts] => Array
                                (
                                    [deleted] => boolean
                                )

                        )

                    [_original:protected] => Array
                        (
                            [id] => 1
                            [firstname] => Darth
                            [lastname] => Vader
                            [username] =>
                            [email] => [email protected]
                            [password] => 5e884898da28047151d0e56f8dc6292
                            [created_at] => 2019-02-08 12:27:42
                            [updated_at] =>
                            [deleted] => 0
                            [deleted_at] =>
                        )

                    [_cast:CodeIgniter\Entity:private] => 1
                )

        )

)

but if i do

return $this->response->setStatusCode(200)->setJSON($data);

Code:
{
"success": true,
"message": "",
"data": [
{}
]
}

Data is totally empty. in fact, the problem is not a relation between entities and model. it's more generic... Like : "How to retrieve a correct formated data ?"

here is my controller/model/entity

Controllers/Users.php
PHP Code:
<?php namespace App\Controllers;

use 
CodeIgniter\Controller;
use 
CodeIgniter\API\ResponseTrait;

use 
App\Models\UserModel;
use 
App\Entities\User;

class 
Users extends Controller
{

    public function 
index()
    {
        
$userModel  = new UserModel();
        
$users_data $userModel->findAll();

        if (
$users_data) {
            
$data = [
            
'success' => true,
            
'message' => '',
            
'data'    => $users_data,
            ];

            echo 
'<pre>';
            
print_r($data);
            
// var_dump($data['data'][0]->id);
            
echo '</pre>';

            
// return $this->response->setStatusCode(200)->setJSON($data);
        
}
        else
        {
            
$data = [
            
'success' => false,
            
'message' => 'not_found',
            
'data'    => [],
            ];

            return 
$this->response->setStatusCode(404)->setJSON($data);
        }
    }

    
//--------------------------------------------------------------------
    // End of file Users.php
    //--------------------------------------------------------------------



Entities/User.php

PHP Code:
<?php namespace App\Entities;

use 
CodeIgniter\Entity;

class 
User extends Entity
{
    protected 
$id;
    protected 
$firstname;
    protected 
$lastname;
    protected 
$username;
    protected 
$email;
    protected 
$password;
    protected 
$created_at;
    protected 
$updated_at;
    protected 
$deleted;
    protected 
$deleted_at;

    protected 
$_options = [
        
'datamap' => [],
        
'dates' => [
            
'created_at',
            
'updated_at',
            
'deleted_at'
        
],
        
'casts' => [
            
'deleted' => 'boolean'
        
],
    ];



Models/UserModel.php

PHP Code:
<?php namespace App\Models;

use 
CodeIgniter\Model;
use 
App\Entities\User;

class 
UserModel extends Model
{

    
/**
     * Model Configuration
     */
    
protected $table      'users';
    protected 
$primaryKey 'id';
    protected 
$returnType User::class;
    protected 
$allowedFields = [
        
'id',
        
'firstname',
        
'lastname',
        
'username',
        
'email',
        
'password',
        
'created_at',
        
'updated_at',
        
'deleted',
        
'deleted_at',
    ];

    protected 
$useSoftDeletes true;
    protected 
$dateFormat     'datetime';

    protected 
$skipValidation  false;


Reply

#6
ok, i start to understand how it work.

In a perfect world, i request my database via the model and he give me an object UserEntity. And in a perfect world, i just have to send it as it with all my data formated like i want defined in my entity.

like this :
Code:
{
  "id": 1,
  "firstname": "Darth",
  "lastname": "Vader",
  "created_at": {
    "date": "2019-02-08 12:27:42.000000",
    "timezone": "Europe/Paris",
    "locale": "en"
  },
  "deleted": false
}

but in fact...

i got an object UserEntity with all accessors protected. and a json_encode(Entity) is not a valid json. Because he try ton convert a custom object and not a generic.

What do i need to get my entity and send it formated like he have to be ?

maybe the $this->response->setJSON() have a problem somewhere...
Reply

#7
I will start a new topic.

Models & Entities are not the problem.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


Users browsing this thread:
1 Guest(s)


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2019 MyBB Group.