-
keulu
Amazing Member
-
Posts: 82
Threads: 8
Joined: Feb 2015
Reputation:
4
02-20-2019, 02:45 AM
(This post was last modified: 02-20-2019, 02:48 AM by keulu.)
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($pass, PASSWORD_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 //-------------------------------------------------------------------- }
-
puschie
Member
-
Posts: 59
Threads: 10
Joined: May 2017
Reputation:
4
02-22-2019, 03:10 AM
(This post was last modified: 02-22-2019, 03:17 AM by puschie.
Edit Reason: add docu description
)
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.
-
keulu
Amazing Member
-
Posts: 82
Threads: 8
Joined: Feb 2015
Reputation:
4
02-22-2019, 07:09 AM
(This post was last modified: 02-22-2019, 07:16 AM by keulu.)
(02-22-2019, 03: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
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 :/
-
puschie
Member
-
Posts: 59
Threads: 10
Joined: May 2017
Reputation:
4
02-25-2019, 07:17 AM
(This post was last modified: 02-26-2019, 02:35 AM by puschie.)
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($pass, PASSWORD_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
-
keulu
Amazing Member
-
Posts: 82
Threads: 8
Joined: Feb 2015
Reputation:
4
02-26-2019, 11:31 AM
(This post was last modified: 02-26-2019, 11:42 AM by keulu.)
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;
}
-
keulu
Amazing Member
-
Posts: 82
Threads: 8
Joined: Feb 2015
Reputation:
4
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...
|