-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement YOrm dynamic return type extension #408
Conversation
related phpstan upstream issue: phpstan/phpstan#9055 |
ich denke es könnte so funktionieren.. hab aber aktuell kein setup um es zu testen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sehr cool 👍. Soweit ich das einschätzen kann, sieht der Code richtig aus, bis auf die eine Sache.
Ich teste es aber gleich auch noch.
} | ||
$modelClass = rex_yform_manager_dataset::getModelClass($relation['table']); | ||
if ($modelClass === null) { | ||
throw new \RuntimeException('Unable to map table to model: '.$relation['table']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wir setzen konsequent für jede Table eine eigene Model-Class bei yakamara.
Aber man muss das nicht tun. Man kann auch nur mit der Basis-Klasse arbeiten, oder auch teils teils.
Daher sollte denke ich keine Exception kommen, wenn es keine Model-Class für die Tabelle gibt.
Es bleibt dann halt bei der Basis-Dataset-Klasse, wie im yform-code als return-type annotiert.
Das läuft über die phpstan-dba-Extension, richtig? Wenn ich die aktiviere, verschwindet der Fehler. class Product extends rex_yform_manager_dataset
{
public function getCategory(): ProductCategory // auch wenn hier was anderes, falsches steht, kommt trotzdem kein Fehler mehr
{
return $this->getRelatedDataset('category_id');
}
}
class ProductCategory extends rex_yform_manager_dataset
{
}
rex_yform_manager_dataset::setModelClass('rex_data_product', Product::class);
// auch wenn diese Zeile fehlt, kommt trotzdem kein Fehler mehr
rex_yform_manager_dataset::setModelClass('rex_data_product_category', ProductCategory::class); |
Ja
Wo passieren diese Registrierungen? Bei addon boot? Oder sind die irgendwo im code ? Du kannst mit class Product extends rex_yform_manager_dataset
{
public function getCategory(): ProductCategory // auch wenn hier was anderes, falsches steht, kommt trotzdem kein Fehler mehr
{
$x = $this->getRelatedDataset('category_id');
\PHPStan\dumpType($x);
return $x;
}
} |
kannst du mir kurz zusammenschreiben wie ich yform bei mir lokal in einer nackten redaxo version einstellen muss damit ich so einen fall reproduzieren kann? (ich hab es noch nie verwendet) |
In YForm gehe auf "Tableset importieren" und importiere dieses Set: tableset.json.zip Und dann diesen Code verwenden: class Product extends rex_yform_manager_dataset
{
public function getCategory(): ProductCategory
{
$x = $this->getRelatedDataset('category_id');
\PHPStan\dumpType($x);
return $x;
}
}
class ProductCategory extends rex_yform_manager_dataset
{
/** @return rex_yform_manager_collection<Product> */
public function getProducts(): rex_yform_manager_collection
{
$x = $this->getRelatedCollection('products');
\PHPStan\dumpType($x);
return $x;
}
}
rex_yform_manager_dataset::setModelClass('rex_data_product', Product::class);
rex_yform_manager_dataset::setModelClass('rex_data_product_category', ProductCategory::class); |
Frage ist noch, wie es bei In dem Tableset oben habe ich die Kategorie im Produkt als Pflicht gesetzt. Gleichzeitig ist es aber so, dass yform zwar beim Erstellen/Bearbeiten von Produkten die Kategorie zur Pflicht macht, aber nicht an anderen Stellen drauf achtet. Zum Beispiel, wenn man eine Kategorie löscht, dann gibt es doch plötzlich Produkte ohne Kategorie. Also entweder sagen wir, dass es nun mal eigentlich Pflicht ist, und entsprechend löst rexstan als nicht-nullable auf. public function getCategory(): ProductCategory
{
return rex_type::notNull($this->getRelatedDataset('category_id'));
} |
:) muss ich das ZIP entpacken vorher? |
Ja. Github erlaubt keine JSON-Dateiuploads. |
Wobei ich das nicht kapiere. Denn die Klassen müssten doch gar nicht vom Autoloader geladen werden, da sie schon beim Booten verfügbar sind, oder nicht? |
phpstan analysiert code statisch ohne ihn auszuführen. er findet klassen via autoloading zur analyse zeit |
Aber wie kann dann hier in deinem Extension-Code |
in deinem code beispiel aus #408 (comment) sind die |
in einem echten redaxo projekt würde es nur funktionieren wenn die |
lib/extension/YOrmDatasetRelatedDataDynamicReturnTypeExtension.php
Outdated
Show resolved
Hide resolved
Aber ich habe es bei mir doch im boot-path, in der boot.php vom project-Addon. So haben wir das ja auch bei unseren realen Projekten (siehe redaxo.org-Repo). Oder was meinst du mit boot-path? |
wollte dir nur den unterschied erklären zwischen dem was ich getestet habe und dem wie es in einem echten projekt ist. ich denke die extension sollte funktionieren mit ich denke wir reden vom gleichen und der PR funktioniert somit wie gewünscht? |
} | ||
|
||
// @phpstan-ignore-next-line | ||
$datasetObject = call_user_func([$classReflection->getName(), 'create']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aus dieser Zeile bekomme ich nun diesen Fehler aus yform:
Missing $table declaration for model class "Product"
#0 /Users/gharlan/workspace/redaxo/redaxo/src/addons/yform/plugins/manager/lib/yform/manager/dataset.php(51):
rex_yform_manager_dataset::modelToTable()
#1 [internal function]: rex_yform_manager_dataset::create()
#2
/Users/gharlan/workspace/redaxo/redaxo/src/addons/rexstan/lib/extension/YOrmDatasetRelatedDataDynamicReturnTypeExtension.php(74):
call_user_func(Array)
Meine Model-Class-Registrierung aus der project-boot.php scheint also nicht zu greifen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
der grund dass die boot.php der addons nicht eingebunden&berücksichtigt wird ist, dass hier im bootstrapping das includen der packages nicht aktiv ist:
Line 20 in ecc97e9
$REX['LOAD_PAGE'] = false; |
über Lines 50 to 51 in ecc97e9
wird der core und aktive addons vor der analyse gebooted,.. es könnte sein dass phpstan nur statische symbole wie defines von konstanten oder deklarationen von funktionen/klassen wahrnimmt, aber keinen code der ausgeführt wird... hmm |
aber ich hab noch eine idee |
Könnte auch gezielt an anderer Stelle passieren. Beispiel: Der Datensatz hat 20 YForm-Felder, von denen aber in einem bestimmten Kontext (inline-Formular via Feldtyp be_manager_relation ) nur ein Felder-Subset zulässig sein soll. Das kann man lösen, indem es für die Tabelle einen normalen Dataset gibt ( |
@christophboecker Danke für das Beispiel. Ich denke nicht dass solche beispiele mit rexstan unterstützbar sein werden. Aber müsste man am konkreten codebeispiel sehen (bitte in neuem issue nicht hier) |
@gharlan bitte nochmal testen. mit dem neusten change funktioniert es bei mir jetzt lokal (ohne manuelle hacks / |
Jupp der Fall funktioniert nun. 👍 Problematisch ist nun noch, wenn man nur teilweise Model-Classes verwendet, oder gar keine. Hier kommt aus beiden dumps aktuell class Product extends rex_yform_manager_dataset
{
public function getCategory(): rex_yform_manager_dataset
{
$x = $this->getRelatedDataset('category_id');
\PHPStan\dumpType($x);
return $x;
}
}
rex_yform_manager_dataset::setModelClass('rex_data_product', Product::class);
function foo(): void {
$category = rex_yform_manager_dataset::require(1, 'rex_data_product_category');
\PHPStan\dumpType($category->getRelatedCollection('products'));
} Und dann ist noch die Frage, ob der Type nullable sein sollte bei getRelatedDataset: #408 (comment) |
hab die cases nicht 100% verstanden, aber ich vermute der fehlende fix ist committed
ich denke wir sollten |
Ist nun besser, und können wir so lassen, denke ich. 👍 Beim unteren Dump bei meinem Beispielcode kommt nur die allgemeine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Danke!
Released |
closes #407