CodeIgniter Forums
Help on entities - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: CodeIgniter 4 (https://forum.codeigniter.com/forum-28.html)
+--- Forum: CodeIgniter 4 Support (https://forum.codeigniter.com/forum-30.html)
+--- Thread: Help on entities (/thread-76823.html)



Help on entities - MatheusCastro - 06-24-2020

Hello, everyone.

I am looking to use the entities in CI4. But I have some doubts.

I would add the entities and pass the Model to Repositorie as recommended in the documentation.

For example, I would like to type information directly into Entity, is that possible?

PHP Code:
<?php namespace App\Entities;

use 
CodeIgniter\Entity;

class 
User extends Entity
{
    protected $attributes = [
        'id' => null,
        'name' => null,        // Represents a username
        'email' => null,
        'password' => null,
        'created_at' => null,
        'updated_at' => null,
    ];


Is it only necessary to implement this above to use $user->name for example to help intellisense?

I checked Lonnie's myth-auth user, but it still wasn't clear to me.

I'm a little lost in implementing the entities. If anyone has any interesting material, they would be grateful.


RE: Help on entities - Leo - 06-25-2020

Definitely use 'em! It just make stuff faster\easier to develop. Here's my own stuff with like 90% of fields not included for easy-reading

Example:
PHP Code:
/////////////////stuff in controller
$model = new ProductsModel();
$product $model->find($product_id)

$name $product->name //you can get name like this
$array $product->array_stuff //if you have an array you get an auto converted array here with entities

$product->name 'New name';
$product->array_stuff $newArray //a new array will be auto converted to a string and put in your product
model->save($product//it is updated!!

//or maybe you want something like this (still in controller):

$input = [
'name' => $_POST['name'],
'array_stuff' => $newArray,
'slug' => url_title($_POST['url'])
];

$product = new Product(); //an empty entity object to be filled or worked with
$product->fill($input);
model->save($product//it is updated!!

///////////////////////////////stuff in model
<?php namespace App\Models;

use 
CodeIgniter\Model;
use 
CodeIgniter\Exceptions\PageNotFoundException;

class 
ProductsModel extends Model
{
protected 
$table 'products';
protected 
$returnType 'App\Entities\Product';
protected 
$useSoftDeletes false;
protected 
$allowedFields = [
'id''name''slug''short_description''array_stuff '
];

protected 
$validationRules = [
'name' => ['label' => 'name''rules' => 'required|max_length[30]|is_unique[products.name]'],
'short_description' => ['label' => 'short description''rules' => 'permit_empty|max_length[80]'],
'slug' => ['label' => 'SEO URL''rules' => 'permit_empty|valid_url|is_unique[products.slug]']
];

public function 
productPage($slug)
{
$product $this->where('slug'$slug)->first();
if(empty(
$product)) {
throw 
PageNotFoundException::forPageNotFound();
}
return 
$product;
}
}

//////////////////////////////stuff in Entities
<?php namespace App\Entities;

use 
CodeIgniter\Entity;

class 
Product extends Entity
{
protected 
$casts = [
'name' => 'string',
'short_description' => '?string',
'slug' => '?string',
'array_stuff ' => '?array'
];




RE: Help on entities - vinezof2 - 06-25-2020

$allowedFields is really necessary? i don't got it very well because all attributes where in the entity and this makes me confused


RE: Help on entities - Leo - 06-25-2020

(06-25-2020, 03:14 PM)vinezof2 Wrote: $allowedFields is really necessary? i don't got it very well because all attributes where in the entity and this makes me confused
No, you can set this in your models $protectFields = false;
But, I usually fill them out because regardless if you write entity fields or not, $allowedFields is the one that handles "filtering" of data. Basically if you do this: $product->fill($_POST) - you may get stuff you don't need in there and with $allowedFields it cross-references what is "valid" and what gets left out.

Theres one example on entities I would like to see though.
How to handle business logic of a bunch of fields.
Currenty I do this: $product->fill($input) with $input variable holding an array of processed data I handled elsewhere in my controller.

I know I can do business logic in entities though, which would clean up my code somewhat, but I'm not sure how to go about this.
I want to actually do this: $product->fill($_POST)
And within entities I want to check each $_POST value - if it is '' set it to null, if it has a trailing space in the beginning or end i want to trim() (users tend to press the spacebar inadvertently). And for one of the $_POST fields - the url I want to do this: url_title($_POST['posted_url'])
Anyone got a good example on this?


RE: Help on entities - vinezof2 - 06-26-2020

(06-25-2020, 10:04 PM)Leo Wrote:
(06-25-2020, 03:14 PM)vinezof2 Wrote: $allowedFields is really necessary? i don't got it very well because all attributes where in the entity and this makes me confused
No, you can set this in your models $protectFields = false;
But, I usually fill them out because regardless if you write entity fields or not, $allowedFields is the one that handles "filtering" of data. Basically if you do this: $product->fill($_POST) - you may get stuff you don't need in there and with $allowedFields it cross-references what is "valid" and what gets left out.

Theres one example on entities I would like to see though.
How to handle business logic of a bunch of fields.
Currenty I do this: $product->fill($input) with $input variable holding an array of processed data I handled elsewhere in my controller.

I know I can do business logic in entities though, which would clean up my code somewhat, but I'm not sure how to go about this.
I want to actually do this: $product->fill($_POST)
And within entities I want to check each $_POST value - if it is '' set it to null, if it has a trailing space in the beginning or end i want to trim() (users tend to press the spacebar inadvertently). And for one of the $_POST fields - the url I want to do this: url_title($_POST['posted_url'])
Anyone got a good example on this?

I understand, is that sometimes I have very large tables and too lazy to fill the array.

About what you want to do, just create setter methods in your entity because the codeigniter will always try to find the set method first. example:
PHP Code:
<?php namespace App\Entities;

use \
CodeIgniter\Entity;

class 
MyClass extends Entity
{
    private 
$id;
    private 
$name;
    private 
$posted_url;
    
    public function 
setId(int $id)
    {
        
$this->id $id;
    }
    
    public function 
setName(string $name)
    {
        
$this->name trim($name);
    }
    
    public function 
setPostedUrl(string $posted_url)
    {
        
$this->posted_url url_title($posted_url);
    }


That way even if you make new MyClass($_POST) the set method is called.


RE: Help on entities - Leo - 06-26-2020

I understand, is that sometimes I have very large tables and too lazy to fill the array.

About what you want to do, just create setter methods in your entity because the codeigniter will always try to find the set method first. example:
PHP Code:
<?php namespace App\Entities;

use \
CodeIgniter\Entity;

class 
MyClass extends Entity
{
    private 
$id;
    private 
$name;
    private 
$posted_url;
    
    public function 
setId(int $id)
    {
        
$this->id $id;
    }
    
    public function 
setName(string $name)
    {
        
$this->name trim($name);
    }
    
    public function 
setPostedUrl(string $posted_url)
    {
        
$this->posted_url url_title($posted_url);
    }


That way even if you make new MyClass($_POST) the set method is called.

AHHH see thats the thing! I too have a lot of columns in my table and the way you wrote it just handles one column at a time, but I need a foreach loop or something to trim all the stuff I throw at it with a $product->fill($_POST)
or will
public function setName(string $name) $this->name = trim($name) }
take care of everything, with the $this->name being dynamic? like

Will this function work with fill? Or does it only work like this:
$product->name($name)?
$product->anotherfield($filed1);
$product->andAnotherField($field2);
$product->iHave_Like_40_Columns_In_MyTable_This_Will_BeHuge($and_This_Is_Only_field3);



RE: Help on entities - vinezof2 - 06-26-2020

Quote:AHHH see thats the thing! I too have a lot of columns in my table and the way you wrote it just handles one column at a time, but I need a foreach loop or something to trim all the stuff I throw at it with a $product->fill($_POST)
or will
public function setName(string $name) $this->name = trim($name) }
take care of everything, with the $this->name being dynamic? like

Will this function work with fill? Or does it only work like this:
$product->name($name)?
$product->anotherfield($filed1);
$product->andAnotherField($field2);
$product->iHave_Like_40_Columns_In_MyTable_This_Will_BeHuge($and_This_Is_Only_field3);


para usar você pode usar assim:
PHP Code:
$product->setName($name);
$product->setValue($value); 
OR
PHP Code:
$product->name $name
$product
->value $value 

it will work the same because CodeIgniter's Entity class uses the magic methods of php __set() and __get(), whenever any value is assigned to some object property the function __set() is called and whenever any property is read the function __get() is called. If you don't want to create a get and set method for each property you can modify or override the __set() function and put some logic in it that clears your strings.

like this:
PHP Code:
public function __set(string $key$value null)
    {
        
$key $this->mapProperty($key);

        
// Check if the field should be mutated into a date
        
if (in_array($key$this->dates))
        {
            
$value $this->mutateDate($value);
        }

        
$isNullable false;
        
$castTo     false;

        if (
array_key_exists($key$this->casts))
        {
            
$isNullable strpos($this->casts[$key], '?') === 0;
            
$castTo     $isNullable substr($this->casts[$key], 1) : $this->casts[$key];
        }

        if (! 
$isNullable || ! is_null($value))
        {
            
// Array casting requires that we serialize the value
            // when setting it so that it can easily be stored
            // back to the database.
            
if ($castTo === 'array')
            {
                
$value serialize($value);
            }

            
// JSON casting requires that we JSONize the value
            // when setting it so that it can easily be stored
            // back to the database.
            
if (($castTo === 'json' || $castTo === 'json-array') && function_exists('json_encode'))
            {
                
$value json_encode($value);

                if (
json_last_error() !== JSON_ERROR_NONE)
                {
                    throw 
CastException::forInvalidJsonFormatException(json_last_error());
                }
            }
        }

        
// if a set* method exists for this key,
        // use that method to insert this value.
        // *) should be outside $isNullable check - SO maybe wants to do sth with null value automatically
        
$method 'set' str_replace(' '''ucwords(str_replace(['-''_'], ' '$key)));
        if (
method_exists($this$method))
        {
            
$this->$method($value);

            return 
$this;
        }

        
// Otherwise, just the value.
        // This allows for creation of new class
        // properties that are undefined, though
        // they cannot be saved. Useful for
        // grabbing values through joins,
        // assigning relationships, etc.
                
if (gettype($value) === 'string') {
                   
$this->attributes[$key] = trim($value);
                } else {
                   
$this->attributes[$key] = $value;
                }

        return 
$this;
    } 

this is default __set() method of Entity class of CodeIgniter with a small modification to string values use the trim() function **edit that way you don't need to create set methods for each attribute, just defining logics for a group of attributes


RE: Help on entities - Leo - 06-26-2020

Thanks! Will try.