vanilophp / order

Order Module For Vanilo (Laravel)
https://vanilo.io
MIT License
34 stars 3 forks source link

Address type constraint mismatch #8

Closed xujiongze closed 5 months ago

xujiongze commented 5 months ago

Am using Checkout and Order module, When I submit the checkout data (I think some data format is error, and will redirect back to checkout page) ad appear this error: Vanilo\Order\Models\Billpayer::getBillingAddress(): Return value must be of type Vanilo\Contracts\Address, Konekt\Address\Models\Address returned https://flareapp.io/share/67OXRQJ5

My concord table :

+----+-------------------------------+--------+---------+--------------------+--------------------+
| #  | Name                          | Kind   | Version | Id                 | Namespace          |
+----+-------------------------------+--------+---------+--------------------+--------------------+
| 1. | Vanilo Cart Module            | Module | 3.8.0   | vanilo.cart        | Vanilo\Cart        |
| 2. | Vanilo Checkout Module        | Module | 3.8.2   | vanilo.checkout    | Vanilo\Checkout    |
| 3. | Vanilo Order Module           | Module | 3.8.0   | vanilo.order       | Vanilo\Order       |
| 4. | Konekt Address Module         | Module | 2.8.0   | konekt.address     | Konekt\Address     |
| 5. | Konekt User Module            | Module | 2.8.0   | konekt.user        | Konekt\User        |
| 6. | Vanilo Adjustments Module     | Module | 3.8.2   | vanilo.adjustments | Vanilo\Adjustments |
| 7. | Vanilo Payment Module         | Module | 3.8.0   | vanilo.payment     | Vanilo\Payment     |
| 8. | Braintree Payments for Vanilo | Module | 1.6.0   | vanilo.braintree   | Vanilo\Braintree   |
+----+-------------------------------+--------+---------+--------------------+--------------------+

CheckoutController.php is same like doc

I try to add this code to AppServiceProvider, but still apear this error.

$this->app->bind(
            \Vanilo\Contracts\Address::class,
            \Konekt\Address\Models\Address::class
        );
fulopattila122 commented 5 months ago

The compatible Address model is in the foundation package. To solve this issue, the fastest way is to:

  1. Create an Address.php file, in your app\Models\ folder with this content:
    
    <?php

namespace App\Models;

use Konekt\Address\Models\Address as BaseAddress; use Vanilo\Contracts\Address as AddressContract; use Vanilo\Support\Traits\AddressModel;

class Address extends BaseAddress implements AddressContract { use AddressModel; }


2. Add this line to your `AppServiceProvider` (in place of the code you wrote above):
```php
    $this->app->bind(\Vanilo\Contracts\Address::class, \App\Models\Address::class);

This should do the trick

xujiongze commented 5 months ago

@fulopattila122 Thanks for the quick reply. I added a new Address and bind, but it still has the same error. Where can I install foundation to solve this problem?

I don’t know if it will affect it. Here is the code of CheckoutDataFactory.

    public function register()
    {
        $this->app->bind(
            \Vanilo\Checkout\Contracts\CheckoutDataFactory::class,
            \App\Factories\CheckoutDataFactory::class
        );
        $this->app->bind(\Vanilo\Contracts\Address::class, \App\Models\Address::class);

    }
<?php

namespace App\Factories;

use Konekt\Address\Contracts\Address as AddressContract;
use Konekt\Address\Models\AddressType;
use Vanilo\Checkout\Contracts\CheckoutDataFactory as CheckoutDataFactoryContract;
use Vanilo\Contracts\Address;
use Vanilo\Contracts\Billpayer;
use Vanilo\Order\Contracts\Billpayer as BillpayerContract;

class CheckoutDataFactory implements CheckoutDataFactoryContract
{
    public function createBillpayer(): Billpayer
    {
        $billpayer = app(BillpayerContract::class);

        $address = app(AddressContract::class);
        $address->type = AddressType::BILLING;

        $billpayer->address()->associate($address);

        return $billpayer;
    }

    public function createShippingAddress(): Address
    {
        $address = app(AddressContract::class);
        $address->type = AddressType::SHIPPING;

        return $address;
    }
}
fulopattila122 commented 5 months ago

Foundation can't be installed separately, it is there only if you install the entire framework: https://vanilo.io/docs/3.x/modules-vs-framework - but I don't suggest that in your case.

The code you posted above should work.

Can you search your code to see if it contains other lines like:

?

Also what is the output of this:

dd(concord()->model(Konekt\Address\Contracts\Address))
xujiongze commented 5 months ago
    public function register()
    {
        $this->app->bind(\Vanilo\Contracts\Address::class, \App\Models\Address::class);
        $this->app->bind(
            \Vanilo\Checkout\Contracts\CheckoutDataFactory::class,
            \App\Factories\CheckoutDataFactory::class
        );

    }
dd(concord()->model('Konekt\Address\Contracts\Address'));

returns

"Konekt\Address\Models\Address" // app/Http/Controllers/CheckoutController.php:33

Only 2 binds

fulopattila122 commented 5 months ago

In which class is the public function register() method you showed above?

xujiongze commented 5 months ago

@fulopattila122 Class AppServiceProvider in the app/Providers

fulopattila122 commented 5 months ago

Oh, :hankey: now I see, that we're using the wrong interface to bind to. It needs to be:

$this->app->bind(\Konekt\Address\Contracts\Address::class, \App\Models\Address::class);
xujiongze commented 5 months ago

Sorry for that, the problem still exists.

dd(concord()->model('Konekt\Address\Contracts\Address'));
// => "Konekt\Address\Models\Address" 
fulopattila122 commented 5 months ago

Are you sure that the $this->app->bind(\Konekt\Address\Contracts\Address::class, \App\Models\Address::class); code runs? Do you call dd(concord()... after that call?

xujiongze commented 5 months ago

null return if call dd in the register. post full code:


<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Storage;
use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNAdapter;
use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNClient;
use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNRegion;
use Illuminate\Filesystem\FilesystemAdapter;
use League\Flysystem\Filesystem;
use Illuminate\Database\Eloquent\Relations\Relation;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind(
            \Vanilo\Checkout\Contracts\CheckoutDataFactory::class,
            \App\Factories\CheckoutDataFactory::class
        );

        $this->app->bind(\Konekt\Address\Contracts\Address::class, \App\Models\Address::class);
        dd(concord()->model('Konekt\Address\Contracts\Address'));

    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
        Blade::if('admin', function () {            
            return auth()?->user()?->hasRole('admin') === true;
        });

    }
}
fulopattila122 commented 5 months ago

Well well.. I didn't read your code properly :) To replace models, a simple app()->bind() won't do the job.

The concord()->registerModel() method needs to be called, as described here: https://vanilo.io/docs/3.x/models#using-custom-models

Here's the code you need:

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        parent::register();

        $this->app->concord->registerModel(
            \Konekt\Address\Contracts\Address::class, \App\Models\Address::class
        );

        $this->app->bind(
            \Vanilo\Checkout\Contracts\CheckoutDataFactory::class,
            \App\Factories\CheckoutDataFactory::class
        );
    }
xujiongze commented 5 months ago

Thank you a lot for your job, work well now.

fulopattila122 commented 5 months ago

Awesome! 🎉