Skip to content
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

Model extending #1661

Merged
merged 145 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 105 commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
e4f076e
wip
glennjacobs Dec 21, 2023
11b0756
chore: fix code style
glennjacobs Dec 21, 2023
c7b38d5
Tidy up a bit
glennjacobs Dec 21, 2023
6651c2c
Merge branch 'feature/model-extending' of https://github.com/lunarphp…
glennjacobs Dec 21, 2023
dc462ce
wip
glennjacobs Dec 21, 2023
156167d
chore: fix code style
glennjacobs Dec 21, 2023
8664348
Update Product.php
glennjacobs Dec 21, 2023
70a60db
Merge branch 'feature/model-extending' of https://github.com/lunarphp…
glennjacobs Dec 21, 2023
ef4a4c0
Update packages/admin/src/Support/Resources/BaseResource.php
glennjacobs Dec 21, 2023
2b449a6
Auto-discover core models
glennjacobs Dec 21, 2023
6ccae35
chore: fix code style
glennjacobs Dec 21, 2023
026147a
Merge branch '1.x' into feature/model-extending
glennjacobs Dec 21, 2023
7495d0b
Update composer.json
glennjacobs Dec 21, 2023
bd2a96e
Merge branch '1.x' into feature/model-extending
glennjacobs Dec 21, 2023
d2674e5
Add contracts
glennjacobs Dec 21, 2023
e860ee8
Update ActivityLogFeed.php
glennjacobs Dec 22, 2023
f5bbf3f
chore: fix code style
glennjacobs Dec 22, 2023
276c142
Merge branch '1.x' into feature/model-extending
alecritson Mar 15, 2024
ddadef1
chore: fix code style
alecritson Mar 15, 2024
fc6246a
contracts
alecritson Mar 15, 2024
c463ea6
Merge branch 'feature/model-extending' into feat/model-extending-ar
alecritson Mar 15, 2024
db7ca52
Contracts
alecritson Mar 15, 2024
b4084a9
chore: fix code style
alecritson Mar 15, 2024
94e96ea
Relationships
alecritson Mar 18, 2024
19ce85b
Start factory tweaks
alecritson Mar 18, 2024
37dd1e4
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Mar 18, 2024
af3f341
Tweaks
alecritson Mar 18, 2024
227f756
chore: fix code style
alecritson Mar 18, 2024
e8e5b34
Use BaseFactory
alecritson Mar 18, 2024
bc82a7a
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Mar 18, 2024
cc03568
Fix
alecritson Mar 18, 2024
44d02b5
Test fixes
alecritson Mar 18, 2024
377d026
Test updates
alecritson Mar 18, 2024
b9159a0
Update tests
alecritson Mar 18, 2024
a8d2949
Test fixes
alecritson Mar 18, 2024
d24b062
Test and docs fixes
alecritson Mar 18, 2024
61fe272
Fix tests
alecritson Mar 18, 2024
7f31112
Fix tests
alecritson Mar 18, 2024
579d42f
test fixes
alecritson Mar 18, 2024
6078472
Don’t enforce morph map
alecritson Mar 18, 2024
51d2818
Shipping updates
alecritson Mar 19, 2024
40a7569
Tweaks
alecritson Mar 19, 2024
a481749
Observer fixes
alecritson Mar 19, 2024
3b11f62
Omit factory return types
alecritson Mar 19, 2024
d113fa3
Switch to contracts
alecritson Mar 19, 2024
151301f
omit return type
alecritson Mar 19, 2024
8264e7b
Fixes
alecritson Mar 19, 2024
e26a2ee
Docs
alecritson Mar 19, 2024
0b064f8
Add shipping migration
alecritson Mar 19, 2024
4b641ef
Change migration name
alecritson Mar 20, 2024
2ac0fdd
Revert trait
alecritson Mar 20, 2024
cbec221
wip
alecritson Mar 20, 2024
9efc302
Revert mapped attributes tweak
alecritson Mar 20, 2024
03a3b49
Update ModelManifest.php
alecritson Mar 21, 2024
357b20b
Remove left over
alecritson Mar 27, 2024
5e79535
Docs fix
alecritson Mar 27, 2024
f0fa1a8
docs
alecritson Mar 27, 2024
5bb0bcd
Allow morph prefix to be set
alecritson Mar 27, 2024
7acc771
Merge branch '1.x' into feature/model-extending
glennjacobs Mar 27, 2024
4f82452
contracts
alecritson Mar 15, 2024
272f3be
Contracts
alecritson Mar 15, 2024
76dc66a
Relationships
alecritson Mar 18, 2024
3a65461
Start factory tweaks
alecritson Mar 18, 2024
4f0c6ab
chore: fix code style
alecritson Mar 15, 2024
fae8f90
Tweaks
alecritson Mar 18, 2024
430b989
Use BaseFactory
alecritson Mar 18, 2024
b359e33
chore: fix code style
alecritson Mar 18, 2024
d5f166a
Fix
alecritson Mar 18, 2024
4905e59
Test fixes
alecritson Mar 18, 2024
b654072
Test updates
alecritson Mar 18, 2024
95a4988
Update tests
alecritson Mar 18, 2024
dc46d5c
Test fixes
alecritson Mar 18, 2024
b27234f
Test and docs fixes
alecritson Mar 18, 2024
1c4bd02
Fix tests
alecritson Mar 18, 2024
d948fd5
Fix tests
alecritson Mar 18, 2024
debc6e7
test fixes
alecritson Mar 18, 2024
979d7c9
Don’t enforce morph map
alecritson Mar 18, 2024
d863ae4
Shipping updates
alecritson Mar 19, 2024
4c02082
Tweaks
alecritson Mar 19, 2024
237aa7b
Observer fixes
alecritson Mar 19, 2024
36aa33f
Omit factory return types
alecritson Mar 19, 2024
1cf1d7d
Switch to contracts
alecritson Mar 19, 2024
f114d25
omit return type
alecritson Mar 19, 2024
67bb256
Fixes
alecritson Mar 19, 2024
e52eb3e
Docs
alecritson Mar 19, 2024
13f8475
Add shipping migration
alecritson Mar 19, 2024
a16532d
Change migration name
alecritson Mar 20, 2024
ca2e55e
Revert trait
alecritson Mar 20, 2024
031d360
wip
alecritson Mar 20, 2024
b970e19
Revert mapped attributes tweak
alecritson Mar 20, 2024
fb872e8
Update ModelManifest.php
alecritson Mar 21, 2024
61221fd
Remove left over
alecritson Mar 27, 2024
50c48ed
Docs fix
alecritson Mar 27, 2024
b617f30
docs
alecritson Mar 27, 2024
3baf8c2
Allow morph prefix to be set
alecritson Mar 27, 2024
c65e314
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Mar 28, 2024
8b627df
Tweak traits
alecritson Mar 28, 2024
93a655d
Remove attribute mapping from merge
alecritson Mar 28, 2024
906af4e
Merge branch '1.x' into feature/model-extending
alecritson Apr 11, 2024
56ecd07
Merge branch 'feature/model-extending' into feat/model-extending-ar
alecritson Apr 11, 2024
8c2e868
Add `morphKey` method
alecritson Apr 12, 2024
0e1b1f4
Update HasModelExtending.php
alecritson Apr 12, 2024
4bd3adc
Update attribute groups attributable type
alecritson Apr 15, 2024
21d976b
Fixes
alecritson Apr 15, 2024
6265042
Merge branch '1.x' into feat/model-extending-ar
alecritson Apr 17, 2024
1e278cf
Merge branch '1.x' into feat/model-extending-ar
alecritson Apr 24, 2024
9d8d4ef
Update models.md
alecritson Apr 24, 2024
65fc144
Update LunarServiceProvider.php
alecritson Apr 24, 2024
8e28842
Tweak contract import
alecritson Apr 24, 2024
98ce0e4
Update import
alecritson Apr 24, 2024
94d6a87
Update models.md
alecritson Apr 24, 2024
50ca7cf
Update models.md
alecritson Apr 24, 2024
75ddfcf
Merge branch '1.x' into feat/model-extending-ar
alecritson May 23, 2024
811c31f
Merge branch '1.x' into feat/model-extending-ar
alecritson Jun 17, 2024
0ee8585
Remove getTable method
alecritson Jun 18, 2024
426be1f
Update ModelManifestTest.php
alecritson Jun 18, 2024
249ff11
Merge branch '1.x' into feat/model-extending-ar
alecritson Jun 25, 2024
09115ef
Merge branch '1.x' into feat/model-extending-ar
glennjacobs Jun 28, 2024
c43d20e
Merge branch '1.x' into feat/model-extending-ar
alecritson Jul 5, 2024
f511277
chore: fix code style
alecritson Jul 5, 2024
ceb74f6
Merge branch '1.x' into feat/model-extending-ar
alecritson Jul 8, 2024
2b73ef0
WIP
alecritson Jul 8, 2024
94314f3
Update BuyXGetYTest.php
alecritson Jul 8, 2024
ee6be4b
Merge branch '1.x' into feat/model-extending-ar
alecritson Aug 8, 2024
673b456
chore: fix code style
alecritson Aug 8, 2024
b06f959
Update Cart.php
alecritson Aug 8, 2024
c8b67dc
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Aug 8, 2024
c9b2829
Update CartTest.php
alecritson Aug 8, 2024
57f3f49
chore: fix code style
alecritson Aug 8, 2024
24f29fb
Merge branch '1.x' into feat/model-extending-ar
alecritson Aug 14, 2024
3d4776f
Merge branch '1.x' into feat/model-extending-ar
alecritson Aug 22, 2024
e16f8df
chore: fix code style
alecritson Aug 22, 2024
5bd6e19
Merge branch '1.x' into feat/model-extending-ar
alecritson Aug 23, 2024
0dc543a
Test fixes
alecritson Aug 23, 2024
dc4d8c3
Handle morph model check
alecritson Aug 23, 2024
958dfaf
Fix relation managers
alecritson Aug 23, 2024
8950ceb
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Aug 23, 2024
fa8a4db
chore: fix code style
alecritson Aug 23, 2024
31f942f
Refactor attribute type to morph name
alecritson Aug 23, 2024
7b6235e
chore: fix code style
alecritson Aug 23, 2024
c5acf77
Test fixes
alecritson Aug 23, 2024
cf98e3c
Merge branch 'feat/model-extending-ar' of github.com:lunarphp/lunar i…
alecritson Aug 23, 2024
91e1fcf
chore: fix code style
alecritson Aug 23, 2024
abd4127
Update upgrading.md
glennjacobs Aug 28, 2024
be47a0d
Update upgrading.md
glennjacobs Aug 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"spatie/laravel-blink": "^1.7",
"spatie/laravel-medialibrary": "^11.0.0",
"spatie/laravel-permission": "^6.4",
"spatie/php-structure-discoverer": "^2.0",
"stripe/stripe-php": "^7.114",
"technikermathe/blade-lucide-icons": "^v3.0"
},
Expand Down
251 changes: 64 additions & 187 deletions docs/core/extending/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,233 +8,125 @@ Lunar provides a number of Eloquent Models and quite often in custom application
We highly suggest using your own Eloquent Models to add additional data, rather than trying to change fields on the core Lunar models.
:::

## Extendable Models
All Lunar models are now extendable.
This means you can now add your own functionality or change out existing core model behaviour using your own model implementations.
## Replaceable Models
All Lunar models are replaceable, this means you can instruct Lunar to use your own custom model, throughout the ecosystem, using dependency injection.


### Registration:
alecritson marked this conversation as resolved.
Show resolved Hide resolved
We recommend registering your own models for your application within the boot method of your Service Provider.
When registering your models, you will need to set the Lunar core model as the key and then your own model implementation as the value.

Here is an example below where we are extending 10 core models from your main AppServiceProvider:
When registering your models, you will need to set the Lunar model's contract as the first argument then your own model implementation for the second.

```php
use Lunar\Models\Product;
use Lunar\Models\ProductVariant;
use Lunar\Models\ProductOption;
use Lunar\Models\ProductOptionValue;
use Lunar\Models\Collection;
use Lunar\Models\Customer;
use Lunar\Models\Cart;
use Lunar\Models\CartLine;
use Lunar\Models\Order;
use Lunar\Models\OrderLine;

```php
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$models = collect([
Product::class => \App\Models\Product::class,
ProductVariant::class => \App\Models\ProductVariant::class,
ProductOption::class => \App\Models\ProductOption::class,
ProductOptionValue::class => \App\Models\ProductOptionValue::class,
Collection::class => \App\Models\Collection::class,
Customer::class => \App\Models\Customer::class,
Cart::class => \App\Models\Cart::class,
CartLine::class => \App\Models\CartLine::class,
Order::class => \App\Models\Order::class,
OrderLine::class => \App\Models\OrderLine::class,
]);

ModelManifest::register($models);
\Lunar\Facades\ModelManifest::replace(
\Lunar\Models\Contracts\Product::class,
\App\Model\Product::class,
);
}
```

### Swap Implementation
You can override the model implementation at any time by calling the swap method on the core model.
When you call the swap method this will update the key value pair for the registered model. If you need to go back to the previous implementation then simply call the swap method again passing through your registered implementation.
#### Registering multiple Lunar models.

```php
namespace App\Models;

use Lunar\Models\ProductVariant;
If you have multiple models you want to replace, instead of manually replacing them one by one, you can specify a directory for Lunar to look in for Lunar models to use.
This assumes that each model extends its counterpart model i.e. `App\Models\Product` extends `Lunar\Models\Product`.

class ProductSwapModel extends \Lunar\Models\Product
```php
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
/**
* This will return the default variant for the product.
*
* @return bool
*/
public function defaultVariant(): ProductVariant
{
return $this->variants->first();
}
\Lunar\Facades\ModelManifest::addDirectory(
__DIR__.'/../Models'
);
}
```

```php
$product = \Lunar\Models\Product::find(1);

// This will swap out the registered implementation.
$product->swap(\App\Models\ProductSwapModel::class);
### Route binding

// You can now call this new method
$default = $product->defaultVariant();
Route binding is supported for your own routes and simply requires the relevant contract class to be injected.

// Swap again to go back to your original implementation or perhaps define a new one.
$product->swap(\App\Models\Product::class);
```php
Route::get('products/{id}', function (\Lunar\Models\Contracts\Product $product) {
$product; // App\Models\Product
});
```

### Examples
Here are some example simple use cases of extending the core models.
You are required to extend the core model `Lunar\Models\[Model]` in order for the relationships to function correctly.
### Relationship support

#### Example 1 - Adding static method (ProductOption Model)
If you replace a model which is used in a relationship, you can easily get your own model back via relationship methods. Assuming we want to use our own instance of `App\Models\ProductVariant`.

```php
namespace App\Models;

use Illuminate\Support\Collection;

class ProductOption extends \Lunar\Models\ProductOption
// In our service provider.
public function boot()
{
public static function getSizes(): Collection
{
return static::whereHandle('size')->first()->values;
}
\Lunar\Facades\ModelManifest::replace(
\Lunar\Models\Contracts\ProductVariant::class,
\App\Model\ProductVariant::class,
);
}
```
In this example you can access the static method via `\Lunar\Models\ProductOption::getSizes()`
Note: Static methods will not allow you to jump to the function declaration.
As a workaround simply add @see inline docblock:

```php
`/** @see \App\Models\ProductOption::getSizesStatic() */`
$newStaticMethod = \Lunar\Models\ProductOption::getSizesStatic();
```

#### Example 2 - Overriding trait method (Product Model)
// Somewhere else in your code...

```php
namespace App\Models;
$product = \Lunar\Models\Product::first();
$product->variants->first(); // App\Models\ProductVariant
```

use App\Concerns\SearchableTrait
### Static call forwarding

class Product extends \Lunar\Models\Product
{
use SearchableTrait;
}
```
Note: shouldBeSearchable could also be overridden by adding directly to the Product class above.
In this example we are showing you how the core model can be made aware of your own model and trait methods.
If you have custom methods in your on model, you can call those functions directly from the Lunar model instance.
alecritson marked this conversation as resolved.
Show resolved Hide resolved

What this also means now the core model can forward call to your extended methods.
Scout in this case will also be made aware that shouldBeSearchable will return false.
Assuming we want to provide a new function to a product variant model.

```php
namespace App\Concerns;
<?php

trait SearchableTrait
namespace App\Models;

class ProductVariant extends \Lunar\Models\ProductVariant
{
/**
* Determine if the model should be searchable.
* @see \Laravel\Scout\Searchable::shouldBeSearchable()
*
* @return bool
*/
public function shouldBeSearchable()
public function someCustomMethod()
{
return false;
return 'Hello!';
}
}
```
#### Example 3 - Overriding cart address functionality (Cart Model)

```php
namespace App\Models;

use App\Concerns\HasAddresses;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Casts\AsCollection;

/**
* Class Cart
*
* @property \Illuminate\Support\Collection $billingAddress
* @property \Illuminate\Support\Collection $shippingAddress
*
*/
class Cart extends \Lunar\Models\Cart
// In your service provider.
public function boot()
{
use HasAddresses;

/**
* {@inheritDoc}
*/
protected $casts = [
'completed_at' => 'datetime',
'meta' => AsArrayObject::class,
'shipping_data' => AsCollection::class,
];
\Lunar\Facades\ModelManifest::replace(
\Lunar\Models\Contracts\ProductVariant::class,
\App\Model\ProductVariant::class,
);
}
```
Note: You can override the casts in a model for example useful when adding new json fields.
In this example we are setting shipping_data cast to store as json. (You will of course need to create your migration)

The trait below demonstrates how to fully extend the cart model functionality.
Somewhere else in your app...

```php
namespace App\Concerns;

trait HasAddresses
{
/**
* Return the address relationships.
*
* @return \Illuminate\Support\Collection
*/
public function addresses(): Collection
{
return ! $this->isSameAddress()
? $this->billingAddress->merge($this->shippingAddress)
: $this->billingAddress;
}
\Lunar\Models\ProductVariant::someCustomMethod(); // Hello!
\App\Models\ProductVariant::someCustomMethod(); // Hello!
```

/**
* Return the shipping address relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function shippingAddress()
{
return $this->belongsTo(Address::class, 'shipping_address_id');
}
### Observers

/**
* Return the billing address relationship.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function billingAddress()
{
return $this->belongsTo(Address::class, 'billing_address_id');
}
If you have observers in your app which call `observe` on the Lunar model, these will still work as intended when you replace any of the models, this means if you
want to add your own custom observers, you can just reference the Lunar model and everything will be forwarded to the appropriate class.

/**
* Compare the shipping and billing address to see if they are the same.
*
* @return bool
*/
protected function isSameAddress(): bool
{
return $this->billingAddress->first()->id === $this->shippingAddress->first()->id;
}
}
```php
\Lunar\Models\Product::observe(/** .. */);
```

## Dynamic Eloquent Relationships
glennjacobs marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -253,18 +145,3 @@ Order::resolveRelationUsing('ticket', function ($orderModel) {
```

See [https://laravel.com/docs/eloquent-relationships#dynamic-relationships](https://laravel.com/docs/eloquent-relationships#dynamic-relationships) for more information.


## Macroable

All Lunar models have been made macroable. This is a Laravel technique to allow a developer to dynamically add methods to an existing class. This is ideal for adding helpful functions for your application.

Here is an example...

```php
use Lunar\Models\Product;

Product::macro('isDraft', function () {
return $this->status === 'draft';
});
```
7 changes: 4 additions & 3 deletions docs/core/reference/carts.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,19 @@ Lunar\Models\CartLine
|:-----------------|:---------------------------------------------|
| id | |
| cart_id | |
| purchasable_type | e.g. `Lunar\Models\ProductVariant`. |
| purchasable_type | e.g. `product_variant` |
| purchasable_id | |
| quantity | |
| created_at | |
| updated_at | |
| meta | JSON data for saving any custom information. |

```php
$purchasable = \Lunar\Models\ProductVariant::create([/** ... */]);
$cartLine = new \Lunar\Models\CartLine([
'cart_id' => 1,
'purchasable_type' => ProductVariant::class,
'purchasable_id' => 123,
'purchasable_type' => $purchasable->getMorphClass(),
'purchasable_id' => $purchasable->id,
'quantity' => 2,
'meta' => [
'personalization' => 'Love you mum xxx',
Expand Down
2 changes: 1 addition & 1 deletion docs/core/reference/discounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Lunar\Models\DiscountPurchasable
|:-------------------|:------------------------|:------------------------------|
| `id` | | |
| `discount_id` | | |
| `purchasable_type` | | `Lunar\Models\ProductVariant`
| `purchasable_type` | | `product_variant`
| `type` | `condition` or `reward` |
| `created_at` | | |
| `updated_at` | | |
Expand Down
Loading
Loading