Welcome Guest, Not a member yet? Register   Sign In
How to understand entities, save, hasChanged
#1

I have using entities and having a bit of trouble understanding them. I am importing ski resort data from a geojson file. All of the 300 ski resorts imported nicely. Now I am testing if there is an UPDATE to the geojson import file or there is a new record (INSERT). My understand is that I can use hasChanged and SAVE (save will detect if update or insert) but I cannot get hasChanged to detect a change. Here is my code.

public function update_aa_winter_sports_points_from_file(){

$file = file_get_contents(WRITEPATH.'upload_fs_data/aa_winter_sports_points.geojson');
$aa_winter_sports_points = json_decode($file); // The json_decode() function is used to decode or convert a JSON object to a PHP object.
// to count the number of ski resorts
$i = 0;

echo 'Numnber of ski resorts: '.count($aa_winter_sports_points->features); echo '</br>';

foreach ($aa_winter_sports_points->features as $aa_winter_sports_point ){

$x = array($aa_winter_sports_point->properties);

// Convert stdClass object to associative array in php
// https://stackoverflow.com/questions/3442...ray-in-php
$new_OsmSkiResort = json_decode(json_encode($x[0]), TRUE);

// get the id of the ski resort
$id = ($new_OsmSkiResort['id']);
echo $id.'</br>';

$original_OsmSkiResort = $this->OsmSkiResortModel->find($id);

$OsmSkiResort = new \App\Entities\OsmSkiResortEntity();

$OsmSkiResort->fill($new_OsmSkiResort);

if ($original_OsmSkiResort){

if (!$original_OsmSkiResort->hasChanged()){
echo "no change on record number ".$i.'</br>';
}

} else {
$y = $this->OsmSkiResortModel->save($OsmSkiResort) ;
echo "save: ".$y.'</br>';
}

$i++;
echo '</pre>';
}

}
Reply
#2

1) For one change to Camel Case.
PHP Code:
update_aa_winter_sports_points_from_file()

// Change to Camel Case makes it easier to read.

updateAaWinterSportsPointsFromFile() 

2) You have an extra closing bracket on your if/else statement.
PHP Code:
if (!$original_OsmSkiResort->hasChanged()){
echo 
"no change on record number ".$i.'</br>';
// <-- Extra closing Bracket remove!

} else {
$y $this->OsmSkiResortModel->save($OsmSkiResort) ;
echo 
"save: ".$y.'</br>';

What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#3

Read https://codeigniter.com/user_guide/model...attributes
Reply
#4

(05-25-2024, 08:27 PM)spreaderman Wrote: I have using entities and having a bit of trouble understanding them.  I am importing ski resort data from a geojson file.  All of the 300 ski resorts imported nicely.  Now I am testing if there is an UPDATE to the geojson import file or there is a new record (INSERT).  My understand is that I can use hasChanged and SAVE (save will detect if update or insert) but I cannot get hasChanged to detect a change.  Here is my code.

    public function update_aa_winter_sports_points_from_file(){
   
        $file = file_get_contents(WRITEPATH.'upload_fs_data/aa_winter_sports_points.geojson');
        $aa_winter_sports_points = json_decode($file);  // The json_decode() function is used to decode or convert a JSON object to a PHP object.
        // to count the number of ski resorts
        $i = 0;
   
        echo 'Numnber of ski resorts: '.count($aa_winter_sports_points->features);  echo '</br>';

        foreach ($aa_winter_sports_points->features as $aa_winter_sports_point ){
       
            $x = array($aa_winter_sports_point->properties);

            // Convert stdClass object to associative array in php
            // https://stackoverflow.com/questions/3442...ray-in-php
            $new_OsmSkiResort = json_decode(json_encode($x[0]), TRUE);
           
            // get the id of the ski resort
            $id = ($new_OsmSkiResort['id']);
            echo $id.'</br>';
           
            $original_OsmSkiResort = $this->OsmSkiResortModel->find($id);
           
            $OsmSkiResort = new \App\Entities\OsmSkiResortEntity();
           
            $OsmSkiResort->fill($new_OsmSkiResort);
           
            if ($original_OsmSkiResort){
               
                if (!$original_OsmSkiResort->hasChanged()){
    echo "no change on record number ".$i.'</br>';
                }
               
            } else {
                $y = $this->OsmSkiResortModel->save($OsmSkiResort) ;
    echo "save: ".$y.'</br>';
            }
   
            $i++;
            echo '</pre>';
        }
       
    }

I do not see any extra brace. That would surely throw an error.
Reply
#5

(This post was last modified: 05-26-2024, 02:43 AM by spreaderman.)

(05-25-2024, 10:53 PM)kenjis Wrote: Read https://codeigniter.com/user_guide/model...attributes

Thank you Kenjis. I previously read that. The below code works but I dont understnad why.

In line 3 below, I used find() and it returns a $category entity. Is line 3 required in order for line 5 to work properly? How does hadChanged() understand it changed?
PHP Code:
1    public function category_update($category_id)
2   {
3        $category $this->CategoryModel->find($category_id);
4        if ($this->request->getMethod() === 'post') {
5            $category->fill($this->request->getPost());
6            if (!$category->hasChanged()){
7                return redirect()->back()->with('info''Nothing to update');
8                
9            
}
10            if ($this->CategoryModel->save($category)) {
11                return redirect()->to('/admin/post/categories')
12                                 ->with('info''Success - category name was updated');
13            } else {
14                return redirect()->back()
15                                 ->with('errors'$this->CategoryModel->errors())
16                                 ->with('warning''Invalid Data')
17                                 ->withInput();
18            }
19        } else {
20            $this->data['category'] = $this->CategoryModel->find($category_id);
21            return view('/Admin/Category/category_update'$this->data    );
22        }
23    

going back to my original problem, I am readying a geojson from file. I put it into an associative array. On the first run of the script, everything imports to the db as expected. If I changed something in the geojson text file, I want to just save the updated parts. Unfortunately, the code says every record hasChanged. I have changed around my code to try to understand what is ocurring but I cannot see why also see as hasChanged.


PHP Code:
public function update_aa_winter_sports_points_from_file(){
    
        
$file file_get_contents(WRITEPATH.'upload_fs_data/aa_winter_sports_points.geojson');
        
$aa_winter_sports_points json_decode($file);  // The json_decode() function is used to decode or convert a JSON object to a PHP object.
        // to count the number of ski resorts
        
$i 0;
    
        echo 
'Numnber of ski resorts: '.count($aa_winter_sports_points->features);  echo '</br>';
        
        foreach (
$aa_winter_sports_points->features as $aa_winter_sports_point ){
        
            echo 
'----------------------------------</br>';
            echo 
'File row number '.$i.'</br>';
            
$data = array($aa_winter_sports_point->properties);

            
// Convert stdClass object to associative array in php
            // https://stackoverflow.com/questions/34428702/convert-stdclass-object-to-associative-array-in-php
            
$new_fill json_decode(json_encode($data[0]), TRUE);
       
            
// find() will return an entity $existing_data.  Works also in findAll();
            
$existing_fill $this->OsmSkiResortModel->find($new_fill['id']);
          
            
// (1/4) if not in db but in file, create db entry
            
if(!$existing_fill){
                
$OsmSkiResort = new \App\Entities\OsmSkiResortEntity();
                
$this->OsmSkiResortModel->save($OsmSkiResort->fill($new_fill));
                echo 
"Added New Record</br>";
            };
            
            
// (3/4) if in db and in file but info in file has changed, update db
            
if($existing_fill){
               
                
$OsmSkiResort = new \App\Entities\OsmSkiResortEntity();
                
                
$OsmSkiResort->fill($new_fill);
                if (
$OsmSkiResort->hasChanged()){
                    
                    echo 
'<pre>';
                    echo 
"Data has changed</br>";
                    echo 
"This is what CI says has changed:<br>";
            
print_r($OsmSkiResort->toRawArray(true));
                    
             echo 
"This is what is in the database<br>";
             
$OsmSkiResort $this->OsmSkiResortModel->find($new_fill['id']);
             
print_r($OsmSkiResort);
                 echo 
'</pre>';
            echo 
'<br><br>';
                }
                
    }
                
       
            
$i++;
            
        }
        
    } 

And here is the output:

Numnber of ski resorts: 223
----------------------------------
File row number 0
Data has changed
This is what CI says has changed:
Array
(
[landuse] => winter_sports
[name] => チセヌプリスキー場
[name:en] => Chisennupri
[name:ja] => 蘭越町チセヌプリスキー場
[piste:type] => playground
[sport] => skiing
[type] => multipolygon
[id] => relation/8385428
)
This is what is in the database
App\Entities\OsmSkiResortEntity Object
(
[snip]
Reply
#6

See your code here EXTRA BRACKET on if else statement
PHP Code:
if (!$original_OsmSkiResort->hasChanged()){
    echo "no change on record number ".$i.'</br>';
                // <-- closing if
              
            
} else { // <-- closing if with else
                $y $this->OsmSkiResortModel->save($OsmSkiResort) ;
    echo "save: ".$y.'</br>';
            }

// Should be like this

if (!$original_OsmSkiResort->hasChanged()){
    echo "no change on record number ".$i.'</br>';
} else {
    $y $this->OsmSkiResortModel->save($OsmSkiResort) ;
    echo "save: ".$y.'</br>';

What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#7

(This post was last modified: 05-26-2024, 05:53 PM by kenjis.)

(05-26-2024, 02:12 AM)spreaderman Wrote: In line 3 below, I used find() and it returns a $category entity.  Is line 3 required in order for line 5 to work properly?  How does hadChanged() understand it changed?

Yes, it is required.

The hadChanged() checks if the original data and the current data are the same.
The original data is set when finding the entity from the database.
Reply
#8

(This post was last modified: 05-26-2024, 09:13 PM by spreaderman.)

(05-26-2024, 05:53 PM)kenjis Wrote:
(05-26-2024, 02:12 AM)spreaderman Wrote: In line 3 below, I used find() and it returns a $category entity.  Is line 3 required in order for line 5 to work properly?  How does hadChanged() understand it changed?

Yes, it is required.

The hadChanged() checks if the original data and the current data are the same.
The original data is set when finding the entity from the database.

Thank you Kenjis. Beginning to make sense now. So kind of like below?

PHP Code:
$category $this->CategoryModel->find($category_id);  // so $category contains a category object/entity if found.

$category->fill($this->request->getPost());  // populate $category->fill

$category->hasChanged(); // compares the entity and the category->fill to see if different.

$this->CategoryModel->save($category)); //  will insert or update subject to above. 

I very much appreciate your and everyone's help!
Reply
#9

I think I figured it out. Indeed the data and the new data were different and hasChanged() was of course correct.

I have 25 fields in the databases. Sometimes the input data is 28 fields (some new data I dont need). Anyway to tell the entity to ignore extra fields? I think this is the source of the error. Thank you.
Reply
#10

You can change the fill() method by filtering the array_filter() array of $data and allowing only $attributes from the model
Simple CI 4 project for beginners codeigniter-expenses
Reply




Theme © iAndrew 2016 - Forum software by © MyBB