Closed cameroncollector closed 4 years ago
Hi,
How does your Tenant model look?
Hi,
How does your Tenant model look?
Originally I didn't create a separate Tenant model instead simply used the default set up, then I created the following recently in hopes it'd do the trick to no avail
`
///////Tenant.php file
namespace App;
use Illuminate\Database\Eloquent\Model; use Laravel\Cashier\Billable; class Tenant extends Model { // use Billable;
public function domain(){
return $this->hasOne(Domain::class);
}
public function customer(){
return $this->belongsTo(Customer::class);
}
}`
I have no experience with Cashier and that error message is not really helpful, so I'm not sure how I can help. Maybe sharing the full stack trace, giving more info (when does this happen, what are you doing, how are you doing it) would help.
As it stands I'd like to associate one of the central app's customers with a tenant, then do a simple check via the $model->subscribed() built into cashier. However I can't retrieve the relationship between Tenant and Customer models once I'm in Tenant routes.
Below I attached an image of my routes/tenant.php file while testing both ->customer and ->customer() to try and reference the relationship (by extension once those work I can chain the Cashier functions).
retrieve the relationship between Tenant and Customer models once I'm in Tenant routes.
You can use the Stancl\Tenancy\StorageDrivers\Database\CentralConnection
trait on your models to force them to use the central DB connection even in the tenant app.
Apologies for posting in a closed issue. This has come up for me though, and I think I may have found a solution to using Cashier on the central DB tenants column.
Cashier allows you to set the model that will be the "billable" model. That is usually the User model. However, since the User model should be in the tenant db (in the above described scenario), and Cashier allows you the change the model used, the billable model could theoretically be set to the Tenant model.
I've already modified the DB migration for Cashier to add the customer columns to the tenant migration. But the question is, is there some clean way to update the Tenant model to include the billable trait? Like this:
use Laravel\Cashier\Billable;
class Tenant implements ArrayAccess
{
use Billable;
}
ETA -- would something like this work? Add a model called Tenant into the laravel App:
namespace App;
use Laravel\Cashier\Billable;
class Tenant extends \Stancl\Tenancy\Tenant
{
use Billable;
//
}
Yes, you need to create a custom model and no, the latter would not work, because Stancl\Tenancy\Tenant
is not a model in v2.
Makes complete sense. Any tips on how to create a custom model? I tried this:
namespace App;
use Laravel\Cashier\Billable;
use Illuminate\Database\Eloquent\Model;
use Stancl\Tenancy\Tenant;
class Customer extends Model
{
protected $table = 'tenants';
use Billable;
use Tenant;
//
}
and got this error message.
Symfony\Component\ErrorHandler\Error\FatalError
App\Customer cannot use Stancl\Tenancy\Tenant - it is not a trait
No need to use Tenant
. As long as you're using the model only for subscription management, it should work.
Anyway, v3 will have a dedicated Tenant model for this.
Yep, I have added a custom data column to the Tenant database to track customer_id's from this Customer model. Any suggestions on how to get data from the customer table from within a tenant? I imagine I'll have to switch database connections, is there some way I can do that from the Customer model?
A dedicated Tenant model sounds good. Any idea how far out v3 is?
A few weeks
And no clue how to do the customer_id stuff, haven't used Cashier yet.
Awesome. Looking forward to v3. Should make it easier to integrate with Cashier.
Figured I'd share for anyone that stumbles on this thread (also may help @stancl with putting a dedicated Tenant model together). Here's my Eloquent Tenant model that allows me to use Cashier:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Laravel\Cashier\Billable;
use Illuminate\Database\Eloquent\Builder;
use Stancl\Tenancy\StorageDrivers\Database\CentralConnection;
class Tenant extends Model
{
use Billable;
use CentralConnection;
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope('id', function (Builder $builder) {
$builder->where('id', tenant()->id);
});
}
/**
* Returns us the Eloquent model of the current tenant.
*
* @return Tenant $tenant
*/
public static function current() {
return static::first();
}
}
The table underlying this Model is the tenant table created by the stancl/tenancy package. This model definition uses a global scope to limit only tenants with the matching tenant_id. The current() method returns the first match (there should only be one). Importantly, this Model will always use the central DB connection since it uses the stancl\tenancy CentralConnection class.
Hopefully this helps anyone struggling with the Tenant model.
If someone is coming to this thread looking how to make it work for V3 you just need to add
use \Illuminate\Auth\Authenticatable;
To the Tenant Model.
I hope this helps you.
Why do you need to make them authenticable? Doesn't Cashier simply require the billable trait?
@stancl Previous to add
use \Illuminate\Auth\Authenticatable;
I was getting this error
BadMethodCallException with message 'Call to undefined method App/Tenant::getAuthIdentifier()'
I don't think billable models need to be authenticable. This seems hacky. Exception disappearing doesn't mean this is the right solution.
You are right, how did you make it work with cashier?
@techguydev with version ^2.3.X you should define your own User/Subscriber/Customer/Tenant model and add the billable trait to that. See example above.
@hackerESQ I am using V3.
I may be overlooking something in documentation or have just spun my wheels to the point where I've mentally blocked out the solution but has anyone integrated this with cashier? I originally wanted to set the billable attribute up on a customer table (in the central app) then do a check once tenancy kicks in to verify subscription, bounce to a landing/payment page if not active. I added the custom column to the Tenants table for customer_id then tried to reference it via a relationship once I proceed into tenancy yet I'm getting a null on the relationship. I know the relationships are working fine as I can load the relation via web routes just fine. When I kicked the Billable attribute over to the Tenant model I got the following error going through the basic setting up of a Stripe customer and adding a paymentMethod
`Stripe\Exception\UnexpectedValueException {#1059 ▼
message: "Could not determine which URL to request: Stripe\PaymentMethod instance has invalid ID: "
code: 0
file: "/Applications/MAMP/htdocs/phonesaas/vendor/stripe/stripe-php/lib/ApiResource.php"
line: 99
trace: {▶} }`
Thanks in advance for any input!