vanilophp / framework

The truly Laravel E-commerce Framework
https://vanilo.io
MIT License
810 stars 102 forks source link

User model already extended by another class #73

Closed d-cell closed 4 years ago

d-cell commented 4 years ago

Hello! Thank you for a great package! Good to have e-shop, which is native to Laravel.

I have a problem with Vanilo installation along existing application. Documentation says i have to extend User model with \Konekt\AppShell\Models\User, but my User model is already extended by model from another package.

Is there any way to figure it out?

fulopattila122 commented 4 years ago

It can be done, it's not necessary to extend any class. Can you tell me which package are you using for User?

d-cell commented 4 years ago

Wow! @fulopattila122 thank you for quick reply!

I use Laravel Voyager admin panel, so i extended my User model with \TCG\Voyager\Models\User.

fulopattila122 commented 4 years ago

OK, before we proceed to the solution, can you please give me:

Thanks!

d-cell commented 4 years ago

Sorry for delay. I had to try something before answer. In a nutshell i need to use Vanilo along with my existing application. My app has admin panel to manage pages, blog etc.. To manage the shop i would like to use Vanilo`s admin interface

At my very first attempt (for testing purposes) i had try to merge my existing application with Vanilo demo app:

Attempt to login into /admin/customer gives me 403 forbidden.

If i extend User model with \Konekt\AppShell\Models\User i get Call to undefined method App\User::hasPermission() in Voyager panel and still 403 forbidden in /admin/customer.

After fail with merging i erazed everything and restored my app from backup to try install Vanilo in usual way.

Here is what i have and what i do step by step:

  1. I have an application with Voyager admin panel. According to Voyager`s documentation i have to extend my standard user model with \TCG\Voyager\Models\User class.

  2. I successfully installed Vanilo with composer require vanilo/framework command.

  3. Then i published Vanilo's config with php artisan vendor:publish --provider="Konekt\Concord\ConcordServiceProvider" --tag=config and edited config/concord.php as mentioned in docs.

  4. Now is the time to run migrations, but here was a problem, because i already have some tables, which names are coincide with tables, which Vanilo`s migrations are trying to create.

So, at this point, i had to make a tricky (maybe, silly) thing - i collected all migration files from Vanilo package and edited some table names there. After this, migrations passed successfully by running them with --path attribute.

And here is the place where i stuck. Some models from Vanilo obviously require old table names.

**The main questions are:

  1. How can i install Vanilo along with existing application if existing application already has sismilar tables?
  2. How to use User model with Vanilo in case if it is already extended by another class?**

Regards

d-cell commented 4 years ago

Hello @fulopattila122 ! Do i have any chance to solve my issue?:)

fulopattila122 commented 4 years ago

Here's what you can do:

  1. make your App\User class implement the Konekt\User\Contracts\User interface
  2. add the inactivate activate and getProfile methods to your model
  3. register your model with concord (as far as I see that's done already)

Your App\User class should look something like this:

<?php

namespace App;

use Konekt\User\Contracts\Profile;
use Konekt\User\Contracts\User as UserContract;
use TCG\Voyager\Models\User as VoyagerUser;

class User extends VoyagerUser implements UserContract
{
   //...
   //... your existing code
   //...

    public function inactivate()
    {
        $this->is_active = false;
        $this->save();
    }

    public function activate()
    {
        $this->is_active = true;
        $this->save();
    }

    public function getProfile(): ?Profile
    {
        return null;
    }
}

You may also completely leave empty the implementations of the new methods, since you likely won't use them at all anyway.

Let me know if it worked.

fulopattila122 commented 4 years ago

I'm closing this issue since the respective part of the Documentation has been updated to cover the case you've described. Please reopen if you still have issues with this.

See: https://vanilo.io/docs/1.2/installation#step-2-for-both-versions

d-cell commented 4 years ago

Here's what you can do:

1. make your `App\User` class implement the `Konekt\User\Contracts\User` interface

2. add the `inactivate` `activate` and `getProfile` methods to your model

3. register your model with concord (as far as I see that's done already)

Your App\User class should look something like this:

<?php

namespace App;

use Konekt\User\Contracts\Profile;
use Konekt\User\Contracts\User as UserContract;
use TCG\Voyager\Models\User as VoyagerUser;

class User extends VoyagerUser implements UserContract
{
   //...
   //... your existing code
   //...

    public function inactivate()
    {
        $this->is_active = false;
        $this->save();
    }

    public function activate()
    {
        $this->is_active = true;
        $this->save();
    }

    public function getProfile(): ?Profile
    {
        return null;
    }
}

You may also completely leave empty the implementations of the new methods, since you likely won't use them at all anyway.

Let me know if it worked.

I'm sorry for writing in closed issue, couldn`t write before, was away last few days. I confirm - your solution works! Thank you!

daniel-farina commented 4 years ago

Hello @fulopattila122

I tried this but it does not work for me. I'm currently trying to integrate with Laravel Spark.

my model looks like this:

<?php

namespace App;

use Konekt\User\Contracts\Profile;
use Konekt\User\Contracts\User as UserContract;
use Laravel\Spark\User as SparkUser;

class User extends SparkUser implements UserContract
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'image', 'provider', 'provider_id', 'password',
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
        'authy_id',
        'country_code',
        'phone',
        'two_factor_reset_code',
        'card_brand',
        'card_last_four',
        'card_country',
        'billing_address',
        'billing_address_line_2',
        'billing_city',
        'billing_zip',
        'billing_country',
        'extra_billing_information',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'trial_ends_at' => 'datetime',
        'uses_two_factor_auth' => 'boolean',
    ];

    // Vanilo's methods

    // Implement these methods from the required Interface:
    public function inactivate()
    {
        $this->is_active = false;
        $this->save();
    }

    public function activate()
    {
        $this->is_active = true;
        $this->save();
    }

    public function getProfile(): ?Profile
    {
        return null;
    }

}

The first problem is when creating an admin user via the command line:

image

I got around that by manually adding the correct role on the database I added an entry in model_roles image (My user id being 5).

After making these changes I can still login via Spark but the admin still gives me an error 403.

http://site.test/admin/customer image

If I replace my model with

<?php

namespace App;

class User extends \Konekt\AppShell\Models\User
{

    protected $fillable = [
        'name', 'email', 'image', 'provider', 'provider_id', 'password',
    ];
}

I can see the admin without any issues but then Laravel breaks obviously. So I can confirm the issue is only happening with my user's model.

Is there anything else am I missing on getting this correctly setup?

Any advice is appreciated it!

Thanks

fulopattila122 commented 4 years ago

I think adding the HasRoles trait will help:

//...
use Konekt\Acl\Traits\HasRoles;

class User extends SparkUser implements UserContract
{
    use HasRoles;
//...
}
daniel-farina commented 4 years ago

I think adding the HasRoles trait will help:

//...
use Konekt\Acl\Traits\HasRoles;

class User extends SparkUser implements UserContract
{
    use HasRoles;
//...
}

That did it! Thank you

Still not too familia with /Konekt