@@ -30,8 +30,22 @@ public function output(Tree $tree): array
30
30
return $ this ->output ;
31
31
}
32
32
33
+ private function pivotColumns (array $ columns , array $ relationships ): array
34
+ {
35
+ // TODO: ideally restrict to only "belongsTo" columns used for pivot relationship
36
+ return collect ($ columns )
37
+ ->map (fn ($ column ) => $ column ->name ())
38
+ ->reject (fn ($ column ) => in_array ($ column , ['created_at ' , 'updated_at ' ]) || in_array ($ column , $ relationships ['belongsTo ' ] ?? []))
39
+ ->all ();
40
+ }
41
+
33
42
protected function populateStub (string $ stub , Model $ model )
34
43
{
44
+ if ($ model ->isPivot ()) {
45
+ $ stub = str_replace ('class {{ class }} extends Model ' , 'class {{ class }} extends Pivot ' , $ stub );
46
+ $ stub = str_replace ('use Illuminate \\Database \\Eloquent \\Model; ' , 'use Illuminate \\Database \\Eloquent \\Relations \\Pivot; ' , $ stub );
47
+ }
48
+
35
49
$ stub = str_replace ('{{ namespace }} ' , $ model ->fullyQualifiedNamespace (), $ stub );
36
50
$ stub = str_replace (PHP_EOL . 'class {{ class }} ' , $ this ->buildClassPhpDoc ($ model ) . PHP_EOL . 'class {{ class }} ' , $ stub );
37
51
$ stub = str_replace ('{{ class }} ' , $ model ->name (), $ stub );
@@ -103,34 +117,42 @@ protected function buildClassPhpDoc(Model $model)
103
117
104
118
protected function buildProperties (Model $ model )
105
119
{
106
- $ properties = '' ;
120
+ $ properties = [];
121
+
122
+ if ($ model ->usesCustomTableName () || $ model ->isPivot ()) {
123
+ $ properties [] = str_replace ('{{ name }} ' , $ model ->tableName (), $ this ->filesystem ->stub ('model.table.stub ' ));
124
+ }
107
125
108
126
if (!$ model ->usesTimestamps ()) {
109
- $ properties .= $ this ->filesystem ->stub ('model.timestamps.stub ' );
127
+ $ properties [] = $ this ->filesystem ->stub ('model.timestamps.stub ' );
128
+ }
129
+
130
+ if ($ model ->isPivot () && $ model ->usesPrimaryKey ()) {
131
+ $ properties [] = $ this ->filesystem ->stub ('model.incrementing.stub ' );
110
132
}
111
133
112
134
if (config ('blueprint.use_guarded ' )) {
113
- $ properties . = $ this ->filesystem ->stub ('model.guarded.stub ' );
135
+ $ properties[] = $ this ->filesystem ->stub ('model.guarded.stub ' );
114
136
} else {
115
137
$ columns = $ this ->fillableColumns ($ model ->columns ());
116
138
if (!empty ($ columns )) {
117
- $ properties .= PHP_EOL . str_replace ('[] ' , $ this ->pretty_print_array ($ columns , false ), $ this ->filesystem ->stub ('model.fillable.stub ' ));
139
+ $ properties[] = str_replace ('[] ' , $ this ->pretty_print_array ($ columns , false ), $ this ->filesystem ->stub ('model.fillable.stub ' ));
118
140
} else {
119
- $ properties . = $ this ->filesystem ->stub ('model.fillable.stub ' );
141
+ $ properties[] = $ this ->filesystem ->stub ('model.fillable.stub ' );
120
142
}
121
143
}
122
144
123
145
$ columns = $ this ->hiddenColumns ($ model ->columns ());
124
146
if (!empty ($ columns )) {
125
- $ properties .= PHP_EOL . str_replace ('[] ' , $ this ->pretty_print_array ($ columns , false ), $ this ->filesystem ->stub ('model.hidden.stub ' ));
147
+ $ properties[] = str_replace ('[] ' , $ this ->pretty_print_array ($ columns , false ), $ this ->filesystem ->stub ('model.hidden.stub ' ));
126
148
}
127
149
128
150
$ columns = $ this ->castableColumns ($ model ->columns ());
129
151
if (!empty ($ columns )) {
130
- $ properties .= PHP_EOL . str_replace ('[] ' , $ this ->pretty_print_array ($ columns ), $ this ->filesystem ->stub ('model.casts.stub ' ));
152
+ $ properties[] = str_replace ('[] ' , $ this ->pretty_print_array ($ columns ), $ this ->filesystem ->stub ('model.casts.stub ' ));
131
153
}
132
154
133
- return trim ($ properties );
155
+ return trim (implode ( PHP_EOL , array_filter ( $ properties, fn ( $ property ) => ! empty ( trim ( $ property )))) );
134
156
}
135
157
136
158
protected function buildRelationships (Model $ model )
@@ -146,6 +168,7 @@ protected function buildRelationships(Model $model)
146
168
foreach ($ model ->relationships () as $ type => $ references ) {
147
169
foreach ($ references as $ reference ) {
148
170
$ is_model_fqn = Str::startsWith ($ reference , '\\' );
171
+ $ is_pivot = false ;
149
172
150
173
$ custom_template = $ template ;
151
174
$ key = null ;
@@ -157,7 +180,13 @@ protected function buildRelationships(Model $model)
157
180
if (Str::contains ($ reference , ': ' )) {
158
181
[$ foreign_reference , $ column_name ] = explode (': ' , $ reference );
159
182
160
- $ method_name = Str::beforeLast ($ column_name , '_id ' );
183
+ if (Str::startsWith ($ column_name , '& ' )) {
184
+ $ is_pivot = true ;
185
+ $ column_name = Str::after ($ column_name , '& ' );
186
+ $ method_name = $ column_name ;
187
+ } else {
188
+ $ method_name = Str::beforeLast ($ column_name , '_id ' );
189
+ }
161
190
162
191
if (Str::contains ($ foreign_reference , '. ' )) {
163
192
[$ class , $ key ] = explode ('. ' , $ foreign_reference );
@@ -192,7 +221,22 @@ protected function buildRelationships(Model $model)
192
221
} elseif (!is_null ($ key )) {
193
222
$ relationship = sprintf ('$this->%s(%s::class, \'%s \', \'%s \') ' , $ type , $ fqcn , $ column_name , $ key );
194
223
} elseif (!is_null ($ class ) && $ type === 'belongsToMany ' ) {
195
- $ relationship = sprintf ('$this->%s(%s::class, \'%s \') ' , $ type , $ fqcn , $ column_name );
224
+ if ($ is_pivot ) {
225
+ $ relationship = sprintf ('$this->%s(%s::class) ' , $ type , $ fqcn );
226
+ $ relationship .= sprintf ('%s->using(%s::class) ' , PHP_EOL . str_pad (' ' , 12 ), $ column_name );
227
+ $ relationship .= sprintf ('%s->as( \'%s \') ' , PHP_EOL . str_pad (' ' , 12 ), Str::snake ($ column_name ));
228
+
229
+ $ foreign = $ this ->tree ->modelForContext ($ column_name );
230
+ $ columns = $ this ->pivotColumns ($ foreign ->columns (), $ foreign ->relationships ());
231
+ if ($ columns ) {
232
+ $ relationship .= sprintf ('%s->withPivot( \'%s \') ' , PHP_EOL . str_pad (' ' , 12 ), implode ("', ' " , $ columns ));
233
+ }
234
+ if ($ foreign ->usesTimestamps ()) {
235
+ $ relationship .= sprintf ('%s->withTimestamps() ' , PHP_EOL . str_pad (' ' , 12 ));
236
+ }
237
+ } else {
238
+ $ relationship = sprintf ('$this->%s(%s::class, \'%s \') ' , $ type , $ fqcn , $ column_name );
239
+ }
196
240
$ column_name = $ class ;
197
241
} else {
198
242
$ relationship = sprintf ('$this->%s(%s::class) ' , $ type , $ fqcn );
0 commit comments