EloquentRepository.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  1. <?php
  2. namespace Dcat\Admin\Repositories;
  3. use Dcat\Admin\Contracts\TreeRepository;
  4. use Dcat\Admin\Exception\AdminException;
  5. use Dcat\Admin\Exception\RuntimeException;
  6. use Dcat\Admin\Form;
  7. use Dcat\Admin\Grid;
  8. use Dcat\Admin\Show;
  9. use Illuminate\Database\Eloquent\Builder;
  10. use Illuminate\Database\Eloquent\Model as EloquentModel;
  11. use Illuminate\Database\Eloquent\Relations;
  12. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  13. use Illuminate\Database\Eloquent\Relations\HasOne;
  14. use Illuminate\Database\Eloquent\Relations\Relation;
  15. use Illuminate\Database\Eloquent\SoftDeletes;
  16. use Illuminate\Support\Arr;
  17. use Illuminate\Support\Collection;
  18. use Illuminate\Support\Facades\DB;
  19. use Illuminate\Support\Str;
  20. use Spatie\EloquentSortable\Sortable;
  21. class EloquentRepository extends Repository implements TreeRepository
  22. {
  23. /**
  24. * @var string
  25. */
  26. protected $eloquentClass;
  27. /**
  28. * @var EloquentModel
  29. */
  30. protected $model;
  31. /**
  32. * @var Builder
  33. */
  34. protected $queryBuilder;
  35. /**
  36. * @var array
  37. */
  38. protected $relations = [];
  39. /**
  40. * @var \Illuminate\Database\Eloquent\Collection
  41. */
  42. protected $collection;
  43. /**
  44. * EloquentRepository constructor.
  45. *
  46. * @param EloquentModel|array|string $modelOrRelations $modelOrRelations
  47. */
  48. public function __construct($modelOrRelations = [])
  49. {
  50. $this->initModel($modelOrRelations);
  51. }
  52. /**
  53. * 初始化模型.
  54. *
  55. * @param EloquentModel|Builder|array|string $modelOrRelations
  56. */
  57. protected function initModel($modelOrRelations)
  58. {
  59. if (is_string($modelOrRelations) && class_exists($modelOrRelations)) {
  60. $this->eloquentClass = $modelOrRelations;
  61. } elseif ($modelOrRelations instanceof EloquentModel) {
  62. $this->eloquentClass = get_class($modelOrRelations);
  63. $this->model = $modelOrRelations;
  64. } elseif ($modelOrRelations instanceof Builder) {
  65. $this->model = $modelOrRelations->getModel();
  66. $this->eloquentClass = get_class($this->model);
  67. $this->queryBuilder = $modelOrRelations;
  68. } else {
  69. $this->setRelations($modelOrRelations);
  70. }
  71. $this->setKeyName($this->model()->getKeyName());
  72. $this->setIsSoftDeletes(
  73. in_array(SoftDeletes::class, class_uses($this->model()))
  74. );
  75. }
  76. /**
  77. * @return string
  78. */
  79. public function getCreatedAtColumn()
  80. {
  81. return $this->model()->getCreatedAtColumn();
  82. }
  83. /**
  84. * @return string
  85. */
  86. public function getUpdatedAtColumn()
  87. {
  88. return $this->model()->getUpdatedAtColumn();
  89. }
  90. /**
  91. * 获取列表页面查询的字段.
  92. *
  93. * @return array
  94. */
  95. public function getGridColumns()
  96. {
  97. return ['*'];
  98. }
  99. /**
  100. * 获取表单页面查询的字段.
  101. *
  102. * @return array
  103. */
  104. public function getFormColumns()
  105. {
  106. return ['*'];
  107. }
  108. /**
  109. * 获取详情页面查询的字段.
  110. *
  111. * @return array
  112. */
  113. public function getDetailColumns()
  114. {
  115. return ['*'];
  116. }
  117. /**
  118. * 设置关联关系.
  119. *
  120. * @param mixed $relations
  121. *
  122. * @return $this
  123. */
  124. public function setRelations($relations)
  125. {
  126. $this->relations = (array) $relations;
  127. return $this;
  128. }
  129. /**
  130. * 查询Grid表格数据.
  131. *
  132. * @param Grid\Model $model
  133. *
  134. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|Collection|array
  135. */
  136. public function get(Grid\Model $model)
  137. {
  138. $this->setSort($model);
  139. $this->setPaginate($model);
  140. $query = $this->newQuery();
  141. if ($this->relations) {
  142. $query->with($this->relations);
  143. }
  144. $model->getQueries()->unique()->each(function ($value) use (&$query) {
  145. if ($value['method'] === 'paginate') {
  146. $value['arguments'][1] = $this->getGridColumns();
  147. } elseif ($value['method'] === 'get') {
  148. $value['arguments'] = [$this->getGridColumns()];
  149. }
  150. $query = call_user_func_array([$query, $value['method']], $value['arguments'] ?? []);
  151. });
  152. return $query;
  153. }
  154. /**
  155. * 设置表格数据排序.
  156. *
  157. * @param Grid\Model $model
  158. *
  159. * @return void
  160. */
  161. protected function setSort(Grid\Model $model)
  162. {
  163. [$column, $type, $cast] = $model->getSort();
  164. if (empty($column) || empty($type)) {
  165. $orders = $model->findQueryByMethod('orderBy')->merge($model->findQueryByMethod('orderByDesc'));
  166. $model->resetOrderBy();
  167. $orders->each(function ($orderBy) use ($model) {
  168. $column = $orderBy['arguments'][0];
  169. $type = $orderBy['method'] === 'orderByDesc' ? 'desc' : ($orderBy['arguments'][1] ?? 'asc');
  170. $cast = null;
  171. $this->addOrderBy($model, $column, $type, $cast);
  172. });
  173. return;
  174. }
  175. $model->resetOrderBy();
  176. $this->addOrderBy($model, $column, $type, $cast);
  177. }
  178. /**
  179. * @param Grid\Model $model
  180. * @param string $column
  181. * @param string $type
  182. * @param string $cast
  183. *
  184. * @throws \Exception
  185. */
  186. protected function addOrderBy(Grid\Model $model, $column, $type, $cast)
  187. {
  188. $explodedCols = explode('.', $column);
  189. $isRelation = empty($explodedCols[1]) ? false : method_exists($this->model(), $explodedCols[0]);
  190. if (count($explodedCols) > 1 && $isRelation) {
  191. $this->setRelationSort($model, $column, $type, $cast);
  192. return;
  193. }
  194. $this->setOrderBy(
  195. $model,
  196. str_replace('.', '->', $column),
  197. $type,
  198. $cast);
  199. }
  200. /**
  201. * @param Grid\Model $model
  202. * @param $column
  203. * @param $type
  204. *
  205. * @param $cast
  206. */
  207. protected function setOrderBy(Grid\Model $model, $column, $type, $cast)
  208. {
  209. $isJsonColumn = Str::contains($column, '->');
  210. if ($isJsonColumn) {
  211. $explodedCols = explode('->', $column);
  212. // json字段排序
  213. $col = $this->wrapMySqlColumn(array_shift($explodedCols));
  214. $parts = implode('.', $explodedCols);
  215. $column = "JSON_UNQUOTE(JSON_EXTRACT({$col}, '$.{$parts}'))";
  216. }
  217. if (! empty($cast)) {
  218. $column = $this->wrapMySqlColumn($column);
  219. $model->addQuery(
  220. 'orderByRaw',
  221. ["CAST({$column} AS {$cast}) {$type}"]
  222. );
  223. return;
  224. }
  225. if ($isJsonColumn) {
  226. $model->addQuery('orderByRaw', ["{$column} {$type}"]);
  227. } else {
  228. $model->addQuery('orderBy', [$column, $type]);
  229. }
  230. }
  231. /**
  232. * @param string $column
  233. *
  234. * @return string
  235. */
  236. protected function wrapMySqlColumn($column)
  237. {
  238. if (Str::contains($column, '`')) {
  239. return $column;
  240. }
  241. $columns = explode('.', $column);
  242. foreach ($columns as &$column) {
  243. if (! Str::contains($column, '`')) {
  244. $column = "`{$column}`";
  245. }
  246. }
  247. return implode('.', $columns);
  248. }
  249. /**
  250. * 设置关联数据排序.
  251. *
  252. * @param Grid\Model $model
  253. * @param string $column
  254. * @param string $type
  255. * @param string $cast
  256. *
  257. * @throws \Exception
  258. */
  259. protected function setRelationSort(Grid\Model $model, $column, $type, $cast)
  260. {
  261. [$relationName, $relationColumn] = explode('.', $column, 2);
  262. if ($model->getQueries()->contains(function ($query) use ($relationName) {
  263. return $query['method'] == 'with' && in_array($relationName, $query['arguments']);
  264. })) {
  265. $relation = $this->model()->$relationName();
  266. $model->addQuery('select', [$this->model()->getTable().'.*']);
  267. $model->addQuery('join', $this->joinParameters($relation));
  268. $this->setOrderBy(
  269. $model,
  270. $relation->getRelated()->getTable().'.'.str_replace('.', '->', $relationColumn),
  271. $type,
  272. $cast
  273. );
  274. }
  275. }
  276. /**
  277. * 关联模型 join 连接查询.
  278. *
  279. * @param Relation $relation
  280. *
  281. * @throws \Exception
  282. *
  283. * @return array
  284. */
  285. protected function joinParameters(Relation $relation)
  286. {
  287. $relatedTable = $relation->getRelated()->getTable();
  288. if ($relation instanceof BelongsTo) {
  289. $foreignKeyMethod = version_compare(app()->version(), '5.8.0', '<') ? 'getForeignKey' : 'getForeignKeyName';
  290. return [
  291. $relatedTable,
  292. $relation->{$foreignKeyMethod}(),
  293. '=',
  294. $relatedTable.'.'.$relation->getRelated()->getKeyName(),
  295. ];
  296. }
  297. if ($relation instanceof HasOne) {
  298. return [
  299. $relatedTable,
  300. $relation->getQualifiedParentKeyName(),
  301. '=',
  302. $relation->getQualifiedForeignKeyName(),
  303. ];
  304. }
  305. throw new AdminException('Related sortable only support `HasOne` and `BelongsTo` relation.');
  306. }
  307. /**
  308. * 设置分页参数.
  309. *
  310. * @param Grid\Model $model
  311. *
  312. * @return void
  313. */
  314. protected function setPaginate(Grid\Model $model)
  315. {
  316. $paginate = $model->findQueryByMethod('paginate')->first();
  317. $model->rejectQuery(['paginate']);
  318. if (! $model->allowPagination()) {
  319. $model->addQuery('get', [$this->getGridColumns()]);
  320. } else {
  321. $model->addQuery('paginate', $this->resolvePerPage($model, $paginate));
  322. }
  323. }
  324. /**
  325. * 获取分页参数.
  326. *
  327. * @param Grid\Model $model
  328. * @param array|null $paginate
  329. *
  330. * @return array
  331. */
  332. protected function resolvePerPage(Grid\Model $model, $paginate)
  333. {
  334. if ($paginate && is_array($paginate)) {
  335. if ($perPage = request()->input($model->getPerPageName())) {
  336. $paginate['arguments'][0] = (int) $perPage;
  337. }
  338. return $paginate['arguments'];
  339. }
  340. return [
  341. $model->getPerPage(),
  342. $this->getGridColumns(),
  343. $model->getPageName(),
  344. $model->getCurrentPage(),
  345. ];
  346. }
  347. /**
  348. * 查询编辑页面数据.
  349. *
  350. * @param Form $form
  351. *
  352. * @return array|\Illuminate\Contracts\Support\Arrayable
  353. */
  354. public function edit(Form $form)
  355. {
  356. $query = $this->newQuery();
  357. if ($this->isSoftDeletes) {
  358. $query->withTrashed();
  359. }
  360. $this->model = $query
  361. ->with($this->getRelations())
  362. ->findOrFail($form->getKey(), $this->getFormColumns());
  363. return $this->model;
  364. }
  365. /**
  366. * 查询详情页面数据.
  367. *
  368. * @param Show $show
  369. *
  370. * @return array|\Illuminate\Contracts\Support\Arrayable
  371. */
  372. public function detail(Show $show)
  373. {
  374. $query = $this->newQuery();
  375. if ($this->isSoftDeletes) {
  376. $query->withTrashed();
  377. }
  378. $this->model = $query
  379. ->with($this->getRelations())
  380. ->findOrFail($show->getKey(), $this->getDetailColumns());
  381. return $this->model;
  382. }
  383. /**
  384. * 新增记录.
  385. *
  386. * @param Form $form
  387. *
  388. * @return mixed
  389. */
  390. public function store(Form $form)
  391. {
  392. $result = null;
  393. DB::transaction(function () use ($form, &$result) {
  394. $model = $this->model();
  395. $updates = $form->updates();
  396. [$relations, $relationKeyMap] = $this->getRelationInputs($model, $updates);
  397. if ($relations) {
  398. $updates = Arr::except($updates, array_keys($relationKeyMap));
  399. }
  400. foreach ($updates as $column => $value) {
  401. $model->setAttribute($column, $value);
  402. }
  403. $result = $model->save();
  404. $this->updateRelation($form, $model, $relations, $relationKeyMap);
  405. });
  406. return $this->model()->getKey();
  407. }
  408. /**
  409. * 查询更新前的行数据.
  410. *
  411. * @param Form $form
  412. *
  413. * @return array|\Illuminate\Contracts\Support\Arrayable
  414. */
  415. public function updating(Form $form)
  416. {
  417. return $this->edit($form);
  418. }
  419. /**
  420. * 更新数据.
  421. *
  422. * @param Form $form
  423. *
  424. * @return bool
  425. */
  426. public function update(Form $form)
  427. {
  428. /* @var EloquentModel $builder */
  429. $model = $this->model();
  430. if (! $model->getKey()) {
  431. $model->exists = true;
  432. $model->setAttribute($model->getKeyName(), $form->getKey());
  433. }
  434. $result = null;
  435. DB::transaction(function () use ($form, $model, &$result) {
  436. $updates = $form->updates();
  437. [$relations, $relationKeyMap] = $this->getRelationInputs($model, $updates);
  438. if ($relations) {
  439. $updates = Arr::except($updates, array_keys($relationKeyMap));
  440. }
  441. foreach ($updates as $column => $value) {
  442. /* @var EloquentModel $model */
  443. $model->setAttribute($column, $value);
  444. }
  445. $result = $model->update();
  446. $this->updateRelation($form, $model, $relations, $relationKeyMap);
  447. });
  448. return $result;
  449. }
  450. /**
  451. * 数据行排序上移一个单位.
  452. *
  453. * @return bool
  454. */
  455. public function moveOrderUp()
  456. {
  457. $model = $this->model();
  458. if (! $model instanceof Sortable) {
  459. throw new RuntimeException(
  460. sprintf(
  461. 'The model "%s" must be a type of %s.',
  462. get_class($model),
  463. Sortable::class
  464. )
  465. );
  466. }
  467. return $model->moveOrderUp() ? true : false;
  468. }
  469. /**
  470. * 数据行排序下移一个单位.
  471. *
  472. * @return bool
  473. */
  474. public function moveOrderDown()
  475. {
  476. $model = $this->model();
  477. if (! $model instanceof Sortable) {
  478. throw new RuntimeException(
  479. sprintf(
  480. 'The model "%s" must be a type of %s.',
  481. get_class($model),
  482. Sortable::class
  483. )
  484. );
  485. }
  486. return $model->moveOrderDown() ? true : false;
  487. }
  488. /**
  489. * 删除数据.
  490. *
  491. * @param Form $form
  492. * @param array $originalData
  493. *
  494. * @return bool
  495. */
  496. public function delete(Form $form, array $originalData)
  497. {
  498. $models = $this->collection->keyBy($this->getKeyName());
  499. collect(explode(',', $form->getKey()))->filter()->each(function ($id) use ($form, $models) {
  500. $model = $models->get($id);
  501. if (! $model) {
  502. return;
  503. }
  504. $data = $model->toArray();
  505. if ($this->isSoftDeletes && $model->trashed()) {
  506. $form->deleteFiles($data, true);
  507. $model->forceDelete();
  508. return;
  509. } elseif (! $this->isSoftDeletes) {
  510. $form->deleteFiles($data);
  511. }
  512. $model->delete();
  513. });
  514. return true;
  515. }
  516. /**
  517. * 查询删除前的行数据.
  518. *
  519. * @param Form $form
  520. *
  521. * @return array
  522. */
  523. public function deleting(Form $form)
  524. {
  525. $query = $this->newQuery();
  526. if ($this->isSoftDeletes) {
  527. $query->withTrashed();
  528. }
  529. $id = $form->getKey();
  530. $this->collection = $query
  531. ->with($this->getRelations())
  532. ->findOrFail(
  533. collect(explode(',', $id))->filter()->toArray(),
  534. $this->getFormColumns()
  535. );
  536. return $this->collection->toArray();
  537. }
  538. /**
  539. * 获取父级ID字段名称.
  540. *
  541. * @return string
  542. */
  543. public function getParentColumn()
  544. {
  545. $model = $this->model();
  546. if (method_exists($model, 'getParentColumn')) {
  547. return $model->getParentColumn();
  548. }
  549. }
  550. /**
  551. * 获取标题字段名称.
  552. *
  553. * @return string
  554. */
  555. public function getTitleColumn()
  556. {
  557. $model = $this->model();
  558. if (method_exists($model, 'getTitleColumn')) {
  559. return $model->getTitleColumn();
  560. }
  561. }
  562. /**
  563. * 获取排序字段名称.
  564. *
  565. * @return string
  566. */
  567. public function getOrderColumn()
  568. {
  569. $model = $this->model();
  570. if (method_exists($model, 'getOrderColumn')) {
  571. return $model->getOrderColumn();
  572. }
  573. }
  574. /**
  575. * 保存层级数据排序.
  576. *
  577. * @param array $tree
  578. * @param int $parentId
  579. */
  580. public function saveOrder($tree = [], $parentId = 0)
  581. {
  582. $this->model()->saveOrder($tree, $parentId);
  583. }
  584. /**
  585. * 设置数据查询回调.
  586. *
  587. * @param \Closure|null $query
  588. *
  589. * @return $this
  590. */
  591. public function withQuery($queryCallback)
  592. {
  593. $this->model()->withQuery($queryCallback);
  594. return $this;
  595. }
  596. /**
  597. * 获取层级数据.
  598. *
  599. * @return array
  600. */
  601. public function toTree()
  602. {
  603. if ($this->relations) {
  604. $this->withQuery(function ($model) {
  605. return $model->with($this->relations);
  606. });
  607. }
  608. return $this->model()->toTree();
  609. }
  610. /**
  611. * @return Builder
  612. */
  613. protected function newQuery()
  614. {
  615. if ($this->queryBuilder) {
  616. return clone $this->queryBuilder;
  617. }
  618. return $this->model()->newQuery();
  619. }
  620. /**
  621. * 获取model对象.
  622. *
  623. * @return EloquentModel
  624. */
  625. public function model()
  626. {
  627. return $this->model ?: ($this->model = $this->createModel());
  628. }
  629. /**
  630. * @param array $data
  631. *
  632. * @return EloquentModel
  633. */
  634. public function createModel(array $data = [])
  635. {
  636. $model = new $this->eloquentClass();
  637. if ($data) {
  638. $model->setRawAttributes($data);
  639. }
  640. return $model;
  641. }
  642. /**
  643. * @param array $relations
  644. *
  645. * @return $this
  646. */
  647. public static function with($relations = [])
  648. {
  649. return (new static())->setRelations($relations);
  650. }
  651. /**
  652. * 获取模型的所有关联关系.
  653. *
  654. * @return array
  655. */
  656. public function getRelations()
  657. {
  658. return $this->relations;
  659. }
  660. /**
  661. * 获取模型关联关系的表单数据.
  662. *
  663. * @param EloquentModel $model
  664. * @param array $inputs
  665. *
  666. * @return array
  667. */
  668. protected function getRelationInputs($model, $inputs = [])
  669. {
  670. $map = [];
  671. $relations = [];
  672. foreach ($inputs as $column => $value) {
  673. $relationColumn = null;
  674. if (method_exists($model, $column)) {
  675. $relationColumn = $column;
  676. } elseif (method_exists($model, $camelColumn = Str::camel($column))) {
  677. $relationColumn = $camelColumn;
  678. }
  679. if (! $relationColumn) {
  680. continue;
  681. }
  682. $relation = call_user_func([$model, $relationColumn]);
  683. if ($relation instanceof Relations\Relation) {
  684. $relations[$column] = $value;
  685. $map[$column] = $relationColumn;
  686. }
  687. }
  688. return [&$relations, $map];
  689. }
  690. /**
  691. * 更新关联关系数据.
  692. *
  693. * @param Form $form
  694. * @param EloquentModel $model
  695. * @param array $relationsData
  696. * @param array $relationKeyMap
  697. *
  698. * @throws \Exception
  699. */
  700. protected function updateRelation(Form $form, EloquentModel $model, array $relationsData, array $relationKeyMap)
  701. {
  702. foreach ($relationsData as $name => $values) {
  703. $relationName = $relationKeyMap[$name] ?? $name;
  704. if (! method_exists($model, $relationName)) {
  705. continue;
  706. }
  707. $relation = $model->$relationName();
  708. $oneToOneRelation = $relation instanceof Relations\HasOne
  709. || $relation instanceof Relations\MorphOne
  710. || $relation instanceof Relations\BelongsTo;
  711. $prepared = $oneToOneRelation ? $form->prepareUpdate([$name => $values]) : [$name => $values];
  712. if (empty($prepared)) {
  713. continue;
  714. }
  715. switch (true) {
  716. case $relation instanceof Relations\BelongsToMany:
  717. case $relation instanceof Relations\MorphToMany:
  718. if (isset($prepared[$name])) {
  719. $relation->sync($prepared[$name]);
  720. }
  721. break;
  722. case $relation instanceof Relations\HasOne:
  723. $related = $model->$relationName;
  724. // if related is empty
  725. if (is_null($related)) {
  726. $related = $relation->getRelated();
  727. $qualifiedParentKeyName = $relation->getQualifiedParentKeyName();
  728. $localKey = Arr::last(explode('.', $qualifiedParentKeyName));
  729. $related->{$relation->getForeignKeyName()} = $model->{$localKey};
  730. }
  731. foreach ($prepared[$name] as $column => $value) {
  732. $related->setAttribute($column, $value);
  733. }
  734. $related->save();
  735. break;
  736. case $relation instanceof Relations\BelongsTo:
  737. case $relation instanceof Relations\MorphTo:
  738. $parent = $model->$relationName;
  739. // if related is empty
  740. if (is_null($parent)) {
  741. $parent = $relation->getRelated();
  742. }
  743. foreach ($prepared[$name] as $column => $value) {
  744. $parent->setAttribute($column, $value);
  745. }
  746. $parent->save();
  747. // When in creating, associate two models
  748. $foreignKeyMethod = version_compare(app()->version(), '5.8.0', '<') ? 'getForeignKey' : 'getForeignKeyName';
  749. if (! $model->{$relation->{$foreignKeyMethod}()}) {
  750. $model->{$relation->{$foreignKeyMethod}()} = $parent->getKey();
  751. $model->save();
  752. }
  753. break;
  754. case $relation instanceof Relations\MorphOne:
  755. $related = $model->$relationName;
  756. if (is_null($related)) {
  757. $related = $relation->make();
  758. }
  759. foreach ($prepared[$name] as $column => $value) {
  760. $related->setAttribute($column, $value);
  761. }
  762. $related->save();
  763. break;
  764. case $relation instanceof Relations\HasMany:
  765. case $relation instanceof Relations\MorphMany:
  766. foreach ($prepared[$name] as $related) {
  767. /** @var Relations\Relation $relation */
  768. $relation = $model->$relationName();
  769. $keyName = $relation->getRelated()->getKeyName();
  770. $instance = $relation->findOrNew(Arr::get($related, $keyName));
  771. if (Arr::get($related, Form::REMOVE_FLAG_NAME) == 1) {
  772. $instance->delete();
  773. continue;
  774. }
  775. Arr::forget($related, Form::REMOVE_FLAG_NAME);
  776. $key = Arr::get($related, $relation->getModel()->getKeyName());
  777. if ($key === null || $key === '') {
  778. Arr::forget($related, $relation->getModel()->getKeyName());
  779. }
  780. $instance->fill($related);
  781. $instance->save();
  782. }
  783. break;
  784. }
  785. }
  786. }
  787. }