prisma-client-php 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -834,48 +834,90 @@ final class PPHPUtility
834
834
  public static function processRelation(
835
835
  string $modelName,
836
836
  string $relatedFieldName,
837
- array $fieldData,
838
- PDO $pdo,
837
+ array $fieldData,
838
+ PDO $pdo,
839
839
  string $dbType,
840
- bool $requestOption = true,
840
+ bool $requestOption = true,
841
841
  ): array {
842
+ $modelClassName = "Lib\\Prisma\\Classes\\{$modelName}";
843
+ $modelClass = (new ReflectionClass($modelClassName))->newInstance($pdo);
842
844
 
843
- $modelClassName = "Lib\\Prisma\\Classes\\" . $modelName;
844
- $modelReflection = new ReflectionClass($modelClassName);
845
- $modelClass = $modelReflection->newInstance($pdo);
846
845
  $modelFieldsRelatedWithKeys = $modelClass->_fieldsRelatedWithKeys[$relatedFieldName];
847
- $modelRelatedFromFields = $modelFieldsRelatedWithKeys['relationFromFields'];
848
- $modelRelatedToFields = $modelFieldsRelatedWithKeys['relationToFields'];
849
- $modelRelatedField = $modelClass->_fields[$relatedFieldName];
846
+ $modelRelatedFromFields = $modelFieldsRelatedWithKeys['relationFromFields'];
847
+ $modelRelatedToFields = $modelFieldsRelatedWithKeys['relationToFields'];
848
+
849
+ $modelRelatedField = $modelClass->_fields[$relatedFieldName];
850
850
  $modelRelatedFieldIsList = $modelRelatedField['isList'] ?? false;
851
- $modelRelatedFieldType = $modelRelatedField['type'];
852
- $relatedClassName = "Lib\\Prisma\\Classes\\" . $modelRelatedFieldType;
853
- $relatedReflection = new ReflectionClass($relatedClassName);
854
- $relatedClass = $relatedReflection->newInstance($pdo);
851
+ $modelRelatedFieldType = $modelRelatedField['type'];
852
+
853
+ $relatedClassName = "Lib\\Prisma\\Classes\\{$modelRelatedFieldType}";
854
+ $relatedClass = (new ReflectionClass($relatedClassName))->newInstance($pdo);
855
+
856
+ $inverseInfo = null;
857
+ $childFkFields = [];
858
+ foreach ($relatedClass->_fieldsRelatedWithKeys as $childField => $info) {
859
+ $infoType = $info['type'] ?? ($relatedClass->_fields[$childField]['type'] ?? null);
860
+ if ($infoType === $modelName && !empty($info['relationFromFields'])) {
861
+ $inverseInfo = $info;
862
+ $childFkFields = $info['relationFromFields'];
863
+ break;
864
+ }
865
+ }
866
+ $isExplicitOneToMany = $modelRelatedFieldIsList && $inverseInfo !== null;
855
867
 
856
868
  $relatedResult = null;
869
+
857
870
  foreach ($fieldData as $action => $actionData) {
858
871
  $operations = isset($actionData[0]) ? $actionData : [$actionData];
859
872
 
860
873
  foreach ($operations as $op) {
861
874
  switch ($action) {
862
875
  case 'connect':
863
- if (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
876
+ if ($isExplicitOneToMany) {
877
+ $parentId = $op[$childFkFields[0]]
878
+ ?? throw new Exception("Missing parent id while connecting '{$relatedFieldName}'.");
879
+
880
+ $where = array_diff_key($op, array_flip($childFkFields));
881
+ if (!$where) {
882
+ throw new Exception("A unique selector (e.g. 'code') is required inside 'connect' for '{$relatedFieldName}'.");
883
+ }
884
+ $fkUpdate = array_fill_keys($childFkFields, $parentId);
885
+ $relatedResult = $relatedClass->update([
886
+ 'where' => $where,
887
+ 'data' => $fkUpdate,
888
+ ]);
889
+ } elseif (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
864
890
  $relatedFieldData = $op[$modelRelatedFieldType];
865
- $modelFieldData = $op[$modelName];
891
+ $modelFieldData = $op[$modelName];
892
+
893
+ if (!isset($relatedFieldData[$relatedClass->_primaryKey])) {
894
+ $existing = $relatedClass->findUnique(['where' => $relatedFieldData]);
895
+ if (!$existing) {
896
+ throw new Exception("Cannot connect '{$relatedFieldName}': related record not found.");
897
+ }
898
+ $relatedFieldData[$relatedClass->_primaryKey] = $existing->{$relatedClass->_primaryKey};
899
+ }
900
+
901
+ if (!isset($modelFieldData[$modelClass->_primaryKey])) {
902
+ $existingParent = $modelClass->findUnique(['where' => $modelFieldData]);
903
+ if (!$existingParent) {
904
+ throw new Exception("Cannot connect '{$relatedFieldName}': parent record not found.");
905
+ }
906
+ $modelFieldData[$modelClass->_primaryKey] = $existingParent->{$modelClass->_primaryKey};
907
+ }
908
+
866
909
  $relatedResult = self::handleImplicitRelationInsert(
867
910
  $modelName,
868
911
  $modelRelatedFieldType,
869
912
  $dbType,
870
913
  $pdo,
871
- $modelFieldData[$modelClass->_primaryKey],
872
914
  $relatedFieldData[$relatedClass->_primaryKey],
915
+ $modelFieldData[$modelClass->_primaryKey],
873
916
  );
874
917
  } else {
875
918
  if (!$modelRelatedFieldIsList && count($operations) > 1) {
876
- throw new Exception("Cannot connect multiple records for a non-list relation '$relatedFieldName'.");
919
+ throw new Exception("Cannot connect multiple records for a non-list relation '{$relatedFieldName}'.");
877
920
  }
878
-
879
921
  $relatedResult = $relatedClass->findUnique(['where' => $op]);
880
922
  }
881
923
  break;
@@ -940,23 +982,52 @@ final class PPHPUtility
940
982
  $relatedResult = $relatedClass->delete(['where' => $whereCondition]);
941
983
  break;
942
984
  case 'disconnect':
943
- if (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
944
- $relatedFieldData = $op[$modelRelatedFieldType];
945
- $modelFieldData = $op[$modelName];
985
+ if ($isExplicitOneToMany) {
986
+ foreach ($operations as $opDisc) {
987
+ $where = array_diff_key($opDisc, array_flip($childFkFields));
988
+ $relatedClass->update([
989
+ 'where' => $where,
990
+ 'data' => array_fill_keys($childFkFields, null),
991
+ ]);
992
+ }
993
+ $relatedResult = true;
994
+ } elseif (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
995
+ $rData = $op[$modelRelatedFieldType];
996
+ $mData = $op[$modelName];
946
997
  $relatedResult = self::handleImplicitRelationDelete(
947
998
  $modelName,
948
999
  $modelRelatedFieldType,
949
1000
  $dbType,
950
1001
  $pdo,
951
- $modelFieldData[$modelClass->_primaryKey],
952
- $relatedFieldData[$relatedClass->_primaryKey]
1002
+ $mData[$modelClass->_primaryKey],
1003
+ $rData[$relatedClass->_primaryKey]
953
1004
  );
954
1005
  } else {
955
1006
  $relatedResult = $relatedClass->delete(['where' => $op]);
956
1007
  }
957
1008
  break;
958
1009
  case 'set':
959
- if (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
1010
+ if ($isExplicitOneToMany) {
1011
+ $parentId = $operations[0][$childFkFields[0]]
1012
+ ?? throw new Exception("Missing parent id in 'set' for '{$relatedFieldName}'.");
1013
+
1014
+ $relatedClass->updateMany([
1015
+ 'where' => [$childFkFields[0] => $parentId],
1016
+ 'data' => array_fill_keys($childFkFields, null),
1017
+ ]);
1018
+
1019
+ $newIds = [];
1020
+ foreach ($operations as $opSet) {
1021
+ $where = array_diff_key($opSet, array_flip($childFkFields));
1022
+ $fkUpdate = array_fill_keys($childFkFields, $parentId);
1023
+ $updateRes = $relatedClass->update(['where' => $where, 'data' => $fkUpdate]);
1024
+ $newIds[] = $updateRes->{$relatedClass->_primaryKey};
1025
+ }
1026
+
1027
+ $relatedResult = $relatedClass->findMany([
1028
+ 'where' => [$relatedClass->_primaryKey => ['in' => $newIds]],
1029
+ ]);
1030
+ } elseif (empty($modelRelatedFromFields) && empty($modelRelatedToFields)) {
960
1031
  $newRelatedIds = [];
961
1032
  $primaryId = null;
962
1033
  foreach ($operations as $opSet) {
@@ -1018,26 +1089,23 @@ final class PPHPUtility
1018
1089
  }
1019
1090
  }
1020
1091
 
1021
- $relatedResult = (array) $relatedResult;
1092
+ $relatedResult = (array)$relatedResult;
1022
1093
 
1023
1094
  if (!$requestOption) {
1024
1095
  return $relatedResult;
1025
1096
  }
1026
-
1027
1097
  if (!$relatedResult) {
1028
- throw new Exception("Failed to process related record for '$relatedFieldName'.");
1098
+ throw new Exception("Failed to process related record for '{$relatedFieldName}'.");
1029
1099
  }
1030
1100
 
1031
1101
  $bindings = [];
1032
- foreach ($modelRelatedFromFields as $index => $fromField) {
1033
- $toField = $modelRelatedToFields[$index];
1102
+ foreach ($modelRelatedFromFields as $i => $fromField) {
1103
+ $toField = $modelRelatedToFields[$i];
1034
1104
  if (!isset($relatedResult[$toField])) {
1035
- throw new Exception("The field '$toField' is missing in the related data for '$relatedFieldName'.");
1105
+ throw new Exception("The field '{$toField}' is missing in the related data for '{$relatedFieldName}'.");
1036
1106
  }
1037
-
1038
1107
  $bindings[$fromField] = $relatedResult[$toField];
1039
1108
  }
1040
-
1041
1109
  return $bindings;
1042
1110
  }
1043
1111
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "prisma-client-php",
3
3
  "description": "Prisma Client PHP is an auto-generated query builder that enables type-safe database access in PHP.",
4
- "version": "2.0.0",
4
+ "version": "2.0.2",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {