We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

# $model->save(); saves not the entire model, return "xy is required" Good evening, I got some columns in my table that must not be null: CREATE TABLE articles ( aid int(11) NOT NULL AUTO_INCREMENT, sysartno int(11) NOT NULL, sku varchar(20) COLLATE utf8_bin NOT NULL, localartno int(11) NOT NULL, articlename varchar(255) COLLATE utf8_bin DEFAULT NULL, shortdesc varchar(255) COLLATE utf8_bin DEFAULT NULL, desc text COLLATE utf8_bin, brand int(11) DEFAULT NULL, HAN varchar(45) COLLATE utf8_bin DEFAULT NULL, priceNetto double DEFAULT NULL, tax double DEFAULT NULL, priceBrutto double DEFAULT NULL, searchTerms varchar(255) COLLATE utf8_bin DEFAULT NULL, metaKeywords varchar(255) COLLATE utf8_bin DEFAULT NULL, metaTitle varchar(255) COLLATE utf8_bin DEFAULT NULL, metaDesc text COLLATE utf8_bin, gid int(11) NOT NULL, sid int(11) NOT NULL, PRIMARY KEY (aid), UNIQUE KEY sysartno_UNIQUE (sysartno), UNIQUE KEY localartno_UNIQUE (localartno), KEY grundFK_idx (gid), KEY statusFK_idx (sid), KEY brandFK_idx (brand), CONSTRAINT grundFK FOREIGN KEY (gid) REFERENCES irrelevanttable1 (gid) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT markeFK FOREIGN KEY (brand) REFERENCES irrelevanttable2 (mid) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT statusFK FOREIGN KEY (sid) REFERENCES irrelevanttable3 (sid) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; The model file created on top of this is from the webtools.php; the initalize(): public function initialize() {$this->setSource("articles");
$this->hasMany('aid', 'irrelevanttable4', 'aid', ['alias' => 'irrelevanttable4']);$this->hasMany('aid', 'irrelevanttable5', 'aid', ['alias' => 'irrelevanttable5']);
$this->hasMany('aid', 'irrelevanttable6', 'aid', ['alias' => 'irrelevanttable6']);$this->belongsTo('gid', '\irrelevanttable1', 'gid', ['alias' => 'irrelevanttable1']);
$this->belongsTo('brand', '\irrelevanttable2', 'mid', ['alias' => 'irrelevanttable2']);$this->belongsTo('sid', '\irrelevanttable3', 'sid', ['alias' => 'irrelevanttable3']);
}

Now, I populate a new instance of the model with the data:

$article = new articles();$article->setSysartno($art->sysartno);$article->setSku($art->sku);$article->setLocalartno($art->localartno);$article->setArticlename($art->articlename); ... (all the fields get populated) Now, when I$article->save(); the model, I get a error message "Articlename is required". My first thought was "oh no, not THAT again" (see this, might be related: https://forum.phalcon.io/discussion/20567/query-tells-field-is-required-but-is-set)

Then I checked the values of $article BEFORE the save(), and it shows me all fields well populated, just like the data provided in$art (which is always populated by the way, so no random null values from there).

Then I made NULL values in articlename possible (just for testing). This way, the query sent from the save() looks like this:

INSERT INTO articles (all the field names) VALUES (105144, 'DE-105144', 105144, null, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, 9, 1)

If I now check $article AFTER the save(), all values except the first four (aid, sysartno, sku, localartno) and the last two (gid, sid) are set to null (the last two fields contain hardcoded values). So the data seems to get lost inside the save()-call. Also:$tmp = $article; var_dump($tmp); // fine
var_dump($article); // fine echo$article->getArticlename(); // fine
echo $tmp->getArticlename(); // fine$tmp->save(); // Articlename required

This will probably work with raw SQL, but I want to make use of the foreign keys from the model, so this isn't really an option. I do know this problem with "xy is required" has been asked some times on this forum, but none of the solutions helped me. Hard coding the "problematic values" doesn't change anything, too.

Oh and another thing; why does the output of var_dump($modelInstance) contain ALL the application data, like metaDataCache, configiguration values, paths, or in short: EVERYTHING thats inside the DI? 125.7k Do you have custom validation set on your model? I don't know if webtools creates the validation() method. As for the other thing: Models extend a bunch of stuff that has access to all those things mentioned, which makes dumping them pretty much useless. However, dumping toArray() works great: var_dump($Model->toArray());

Personally, I use this custom function that automatically calls toArray() if an object has it defined:

function dump($passed,$use_vardump = FALSE,$backtrace_offset = 0) {$is_cli = (php_sapi_name() == 'cli');
$newline = ($is_cli) ? "\n" : '<br />';
$backtrace = debug_backtrace();$file = $backtrace[$backtrace_offset]['file'];
$line =$backtrace[$backtrace_offset]['line']; if(!$is_cli){
echo '<pre>';
}
echo "File: $file$newline";
echo "Line: $line$newline";

if($use_vardump){ var_dump($passed);
}
else{
if(is_array($passed)){ print_r($passed);
}
else if(is_object($passed)){ if(method_exists($passed, 'toArray')){
print_r($passed->toArray()); } else{ print_r($passed);
}
}
else{
echo $passed; } } if(!$is_cli){
echo '</pre>';
}

if(count(ob_get_status()) != 0){
ob_flush();
}
}
dump($Model); It also outputs where it was called, so I never have to hunt through my code trying to find debugging statements. 4.0k Webtools only generates validators for fields like "email", which returns the correct EmailValidator then (obviously). I don't have any custom validators set. I felt free to use your dump function with surprising results. ... (all the setters get called) echo$article->getArticlename();
$this->dump($article);
$this->dump($article, true);
echo $article->getArticlename(); Output: (the correct articlename gets displayed) File: D:\path\to\app\controllers\SomeController.php Line: 173 Array ( [aid] => [sysartno] => 105144 [sku] => 105144 [localartno] => 105144 [articlename] => [shortdesc] => [desc] => [brand] => [HAN] => [priceNetto] => [tax] => [priceBrutto] => [searchTerms] => [metaKeywords] => [metaTitle] => [metaDesc] => [gid] => 9 [sid] => 1 ) File: D:\path\to\app\controllers\SomeController.php Line: 174 D:\path\to\app\controllers\ControllerBase.php:63: object(articles)[191] protected 'aid' => null (gets filled in by the database) protected 'sysartno' => int 105144 (correct value) protected 'sku' => int 105144 (correct value) protected 'localartno' => int 105144 (correct value) protected 'articlename' => (correct value) protected 'shortDesc' => (correct value) protected 'desc' => (correct value) protected 'brand' => (correct value) protected 'hAN' => (correct value) protected 'priceNetto' => (correct value) protected 'tax' => (correct value) protected 'priceBrutto' => (correct value) protected 'searchTerms' => (correct value) protected 'metaKeywords' => null (correct value) protected 'metaTitle' => null (correct value) protected 'metaDesc' => null (correct value) protected 'gid' => int 9 (correct value) protected 'sid' => int 1 (correct value) (the correct articlename gets displayed) 125.7k It looks like the article name doesn't get displayed when calling print_r, but it does when calling var_dump? So just to recap - you've got a model with a property articleName that defaults to NULL. Even when setting articleName to a string, you get a validation error? Not a permanent solution, but what if you just bypassed validation by writing your own validation method? That could at least get the query sent to the database, so you can see exactly what values it's dealing with. public function validation(){ return TRUE; } 4.0k It looks like the article name doesn't get displayed when calling print_r, but it does when calling var_dump? This. So just to recap - you've got a model with a property articleName that defaults to NULL. Even when setting articleName to a string, you get a validation error? It doesn't default to null, it sets to null (atleast for print_r and save()). See the table definition and the query above; the fields that have default null also get this default value in the query, instead of their real values. So for the recap: If I set the value to a string (as desired), save() and print_r treat it as null. Not a permanent solution, but what if you just bypassed validation by writing your own validation method? That could at least get the query sent to the database, so you can see exactly what values it's dealing with. public function validation(){ return TRUE; } Still yields Articlename is required, with no query sent. 125.7k Can you post the entirety of your model? I'll see if I can reproduce. Are you using Phalcon v4 or v3.4? 4.0k 4.0.6 on Windows 10 with PHP 7.4.4., MySQL 5.7.11. I have the same problem with another model, but it behaves exactly like the article model. I opened a Github issue about it (before your first answer), so I suggest you use the (much smaller) model in the issue: https://github.com/phalcon/cphalcon/issues/15061 CREATE TABLE barcodes ( cid int(11) NOT NULL AUTO_INCREMENT, aid int(11) NOT NULL, Barcode varchar(20) COLLATE utf8_bin NOT NULL, PRIMARY KEY (cid), KEY articleFK_idx (aid), CONSTRAINT articleFK FOREIGN KEY (aid) REFERENCES articles (aid) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; <?php class barcodes extends \Phalcon\Mvc\Model { protected$cid;
protected $aid; protected$barcode;

public function setCid($cid) {$this->cid = $cid; return$this;
}

public function setAid($aid) {$this->aid = $aid; return$this;
}

public function setBarcode($barcode) {$this->barcode = $barcode; return$this;
}

public function getCid()
{
return $this->cid; } public function getAid() { return$this->aid;
}

public function getBarcode()
{
return $this->barcode; } public function initialize() {$this->setSource("barcodes");
$this->belongsTo('aid', '\articles', 'aid', ['alias' => 'articles']); } public static function find($parameters = null): \Phalcon\Mvc\Model\ResultsetInterface
{
return parent::find($parameters); } public static function findFirst($parameters = null)
{
return parent::findFirst($parameters); } public function columnMap() { return [ 'cid' => 'cid', 'aid' => 'aid', 'Barcode' => 'Barcode' ]; } }$barcodeArray = array('123', '456');

foreach($barcodeArray as$code)
{
$bc = new barcodes();$bc->setAid($aid);$bc->setBarcode($code); var_dump($bc->barcode);
echo $bc->getBarcode()."<br />"; if ($bc->save() == false)
{
foreach ($bc->getMessages() as$message)
echo $message."<br />"; } echo$bc->getBarcode();
}

125.7k
Accepted

Ok, I think I have it figured out. And you're going to kick yourself.

setBarcode() sets $this->barcode, but the model has$this->Barcode defined. Capital B. The model has also explicitly declared protected $barcode, but the column map uses Barcode. So when you're calling setBarcode() and dumping$bc->barcode, yes it's working - it's setting the object's property $barcode. But that property is completely separate from the property that is mapped to a database column - Barcode. By changing$barcode to \$Barcode everywhere, the code worked.

This sounds like a bug in webtools.php rather than Phalcon.

If I were you, I'd go through and normalize all database columns and variables to lowercase, and all class names to capital case.

4.0k

This hurts a bit.

Solution works for articles too, also for the other tables from my post some week ago. I'll make an issue about this in the webtools repo. This is my fault in some ways, but I think webtools should take something like this in account.

Thank you so much for pointing this out, I'd never have seen this. :)

125.7k

Yeah, it totally should. Someone put in an extra strtolower()

The only reason I noticed it is because lowercase classes and capitalized non-objects go against my personal coding style, so it stood out.