Laravel cashier with stripe, error checking subscription status - laravel

I get the following error when checking subscription status with:
$user = User::where('id', '=', \Auth::user()->id)->first();
if ($user->subscribed('main')) <-- error
Error:
ErrorException in Builder.php line 2405: Call to undefined method
Illuminate\Database\Query\Builder::valid() (View: /var/www/html...
in Builder.php line 2405
at Builder->__call('valid', array())
at Builder->valid()
at call_user_func_array(array(object(Builder), 'valid'), array()) in Builder.php line 1426
at Builder->__call('valid', array())
at Builder->valid()
at call_user_func_array(array(object(Builder), 'valid'), array()) in Relation.php line 343
at Relation->__call('valid', array()) in Billable.php line 172
at HasMany->valid() in Billable.php line 172
at User->subscribed('main') in BillingsController.php line 58
at BillingsController->index()
I don't get any problems using the $user->onGenericTrial() and $user->onTrial() methods in the same view.
I've created a new subscription using:
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($creditCardToken);
I'm using Laravel 5.2 and Cashier 6.0 . I followed docs here https://laravel.com/docs/5.2/billing#checking-subscription-status .
In my user model, I use Laravel\Cashier\Billable; and use Billable; and hasMany on my Subscription model. My Subscription model has the belongsTo User relation
User model
<?php namespace App;
use Laravel\Cashier\Billable;
use Carbon\Carbon;
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract {
use Authenticatable, Authorizable, CanResetPassword;
public $incrementing = true;
use SoftDeletes;
use Billable;
protected $dates = ['deleted_at'];
protected $table = 'users';
protected $fillable = [ ... 'stripe_id', 'card_brand', 'card_last_four', 'trial_ends_at'];
public function subscription()
{
return $this->hasMany('App\Subscription');
}
public function getTrialEndsAtAttribute($value)
{
$format = $this->getDateFormat();
return Carbon::createFromFormat($format, $value, 'UTC')->setTimezone(\Helper::getTimezone());
}
This is where the error occurs:
https://github.com/laravel/cashier/blob/6.0/src/Billable.php
public function subscribed($subscription = 'default', $plan = null)
{
$subscription = $this->subscription($subscription);
if (is_null($subscription)) {
return false;
}
if (is_null($plan)) {
return $subscription->valid();
}
return $subscription->valid() &&
$subscription->stripe_plan === $plan;
}
Solution:
Finally found the problem! One must NOT create relationships between User and Subscription models. I had the hasMany relationship on my User model and the belongsTo relationship on the Subscription model. That was the problem.

Can you try and run:
$user->first()->subscribed('main');
See if this throws the same error, The reason im asking this is because the Illuminate query builder can throw undefined method if the full object is not instantiated.
Im not a laravel pro however i have faced this issue myself on several occasions, Let me give you an example of how i overcome a similar issue today.
return $user->payments()->first()->fetchMostRecent($customArrayValues)->first();
Also what does your $user->subscription(); or $user->subscription()->first(); return, does this function return what is expected?
As i said im by no means a pro with laravel however i will try and help out the best i can, I am sure more advanced people on here will also provide a helping hand as the query builder error exceptions can be a pain in the back side!

Related

Event fails when using serialization in laravel 5.4

I have different models, which describe different tables in database.
I use this trait for these classes
trait ApplicationModelTrait
{
protected static $_currentModel = null;
protected $currentModel;
public static function setCurrentModel(ApplicationModel $model) {
static::$_currentModel = $model;
}
public function __construct(array $attributes = [], ApplicationModel $model = null) {
parent::__construct($attributes);
$this->currentModel = $model !== null ? $model : static::$_currentModel;
if($this->currentModel === null) throw new \InvalidArgumentException('No model passed');
}
}
All models are similar. The only difference is what fields exist in database for every model, so I describe these fields in separate config and main model class ApplicationModel has some methods to work with different tables. For example
public function getInstanceTable() {
return 'application_model_instances_' . $this->name;
}
public function getCommentsTable() {
return 'application_model_instance_' . $this->name . '_comments';
}
Where application_model_instances_{name} contains (obviously) instances of this model and application_model_instance_{name}_comments contains comments for instances of this model.
Everything works fine except events.
When I add comment to model instance, I pass as argument current model
$comment = new ApplicationModelInstanceComment([], $this->currentModel);
$comment->text = $request->input('comment');
// etc.
After comment has been saved I want it to be instantly delivered to user browser via websocket
event(new CommentCreated($comment, $this)); // this represents model instance class
And, finally, the event
namespace App\Events;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\Models\Application\ApplicationModelInstanceComment;
use App\Models\Application\ApplicationModelInstance;
class CommentCreated implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public $comment;
public $instance;
public function __construct(ApplicationModelInstanceComment $comment, ApplicationModelInstance $instance)
{
$this->comment = $comment;
$this->instance = $instance;
}
public function broadcastOn() {
$notifiableUsers = $this->instance->getNotifiableUsers(); // this method is used to fetch list of users who must get this comment in their browser
$channels = [];
foreach($notifiableUsers as $user) {
$channels[] = new PrivateChannel('user.' . $user->id);
}
return $channels;
}
}
But when I add comment Laravel my code throws an exception (this is what I see in network tab in Google Chrome because request is done via ajax:
Whoops, looks like something went wrong.
1/1 InvalidArgumentException in ApplicationModelTrait.php line 20: No model passed
in ApplicationModelTrait.php line 20
at ApplicationModelInstanceComment->__construct() in SerializesAndRestoresModelIdentifiers.php line 45
at CommentCreated->getRestoredPropertyValue(object(ModelIdentifier)) in SerializesModels.php line 41
at CommentCreated->__wakeup()
at unserialize('O:38:"Illuminate\\Broadcasting\\BroadcastEvent":4:{s:5:"event";O:25:"App\\Events\\CommentCreated":3:{s:7:"comment";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:54:"App\\Models\\Application\\ApplicationModelInstanceComment";s:2:"id";i:68;}s:8:"instance";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:47:"App\\Models\\Application\\ApplicationModelInstance";s:2:"id";i:11;}s:6:"socket";N;}s:10:"connection";N;s:5:"queue";N;s:5:"delay";N;}') in CallQueuedHandler.php line 95
at CallQueuedHandler->failed(array('commandName' => 'Illuminate\\Broadcasting\\BroadcastEvent', 'command' => 'O:38:"Illuminate\\Broadcasting\\BroadcastEvent":4:{s:5:"event";O:25:"App\\Events\\CommentCreated":3:{s:7:"comment";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:54:"App\\Models\\Application\\ApplicationModelInstanceComment";s:2:"id";i:68;}s:8:"instance";O:45:"Illuminate\\Contracts\\Database\\ModelIdentifier":2:{s:5:"class";s:47:"App\\Models\\Application\\ApplicationModelInstance";s:2:"id";i:11;}s:6:"socket";N;}s:10:"connection";N;s:5:"queue";N;s:5:"delay";N;}'), object(InvalidArgumentException)) in Job.php line 158
at Job->failed(object(InvalidArgumentException)) in FailingJob.php line 33
I've passed model into ApplicationModelInstanceComment upon creation of comment, so everything is fine here. There is some problem with deserialization, but I do not know how to deal with this problem.

Update Foreign Key with softDeletes()

Hi I've been looking for the similar solution but can't find anywhere. I don't even know if there is one. What I am trying to do is perform a softDelete on one of my model and want to update the user_id in the model with the the id of the user performing the action. I have tried using associate(), it doesn't throw any exception but does not work. I mean the delete is working but id is not updating
Here's what I've tried
public function postDelete(Request $request){
$appointment = \App\Models\emp_appointment::findOrFail($request->appid);
$user = $request->user();
$appointment->user()->associate($user);
$appointment->delete();
}
Here's my Appointment Model
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class emp_appointment extends Model{
use SoftDeletes;
protected $dates = ['deleted_at'];
public function employee(){
return $this->belongsTo('App\Models\employee','emp_id');
}
public function user(){
return $this->belongsTo('App\Models\tb_login','userid');
}
}
PS: There are no problems in the models and no errors anywhere. Only the problem is userid doesn't get updated in the appointment table.
Seems like the delete method isn't saving your change (association)
Try saving first then deleting
public function postDelete(Request $request){
$appointment = \App\Models\emp_appointment::findOrFail($request->appid);
$user = $request->user();
$appointment->user()->associate($user);
$appointment->save();
$appointment->delete();
}
EDIT
public function postDelete(Request $request){
$appointment = \App\Models\emp_appointment::findOrFail($request->appid);
$user = $request->user();
$appointment->user()->associate($user);
$appointment->deleted_at= date('Y-m-d H:i:s');
$appointment->save();
}

Trouble getting attribute of relation in Laravel

I'm having a trouble with a relation in Laravel 5. the thing is that I have a table User and that user belongs to a Group for that, in the User model I have this:
public function group(){
return $this->belongsTo('App\models\Group');
}
The model Group have this attributes: name,unity,level, init_date. I also put there a default function to return a group as String, this is the code:
public function __toString(){
return $this->name.' Unity '.$this->unity;
}
So, the thing that in a view a have many users and for each of them I want to display the unity, name,date. When I call $user->group it returns me correctly the name and the unity in a String (because the _toString function) that means that he is really querying the group perfectly, but then, when I want to access a simple attribute as unity,date,or name with $user->group->name Laravel gives me this error:
Trying to get property of non-object
I even tried $user->group()->name then I gets: Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$name
Edited:
The model User:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
protected $table = 'users';
protected $fillable = ['email', 'password','estate','filial_id','perfil_id','rol','cat_teacher'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
public function __toString(){
return $this->email;
}
public function filial(){
return $this->belongsTo('App\models\Filial');
}
public function perfil(){
return $this->belongsTo('App\models\Perfil','perfil_id');
}
public function grupo(){
return $this->belongsTo('App\models\Group','group_id','id');
}
}
The model Group:
class Group extends Model {
protected $table = 'groups';
protected $fillable = ['name','unity','date'];
public function filiales() {
return $this->belongsTo('App\models\Filial');
}
public function teacher(){
return $this->belongsTo('App\models\User','teacher_id');
}
public function users() {
return $this->hasMany('App\models\User');
}
}
Then, in the controller I made a dd($users) and there not appear the relations, appears other relations but not this one. In the view I want to print some of the attributes in a table, for that I have:
<td>{{$user->group}}</td>
<td>{{$user->group->unity}}</td>
The first line works perfectly, and I donĀ“t know why.
The reason you're unable to return your group's name is that ->group() returns an instance of the query builder, and not an eloquent collection/object. Since a user belongs to a single group, modify your code in one of these two ways:
public function group(){
return $this->belongsTo('App\models\Group')->first();
}
And then access the group using one of the following methods:
$user = User::with("group")->where("id", "=", 1)->first();
$group = $user->group;
echo $group->name;
// OR
$user = User::where("id", "=", 1)->first();
$group = $user->group();
echo $group->name;
Or, leave the group() function as it is and access ->group()->first() on your $user object:
$user = User::where("id", "=", 1)->first();
$group = $user->group()->first();
echo $group->name;
Any of the above methods should properly return your group object's name (or other attributes). Check the Eloquent Documentation for detailed explanations on how to access these objects.

Laravel receive information from user

I've got two tables: a user table and a car table. When a user is logged in I want to show his cars, with lots of information. But how do I do this in the controller, including giving the right car information from that user? I have already set the relations but how do I receive the right information in the controller?
I was thinking about this:
$car = car()->user();
return view('cars.index',compact('usercar','car'));
Of course this is wrong, but what's the right way?
EDIT:
This is my controller and this is the index method:
use App\Car;
public function index()
{
$car = Auth::user()->Car;
return view('tickets.index',compact('usercar','car'));
}
This is my user model:
use App\Car;
public function car()
{
return $this->hasMany('App\Car');
}
This is my car model:
use App\User;
public function user()
{
return $this->belongsTo('App\User');
}
And this is my route:
Route::get('/tickets','TicketsController#index');
in Model.php line 893 at FatalErrorException->__construct() in
HandleExceptions.php line 133 at
HandleExceptions->fatalExceptionFromError() in HandleExceptions.php
line 118 at HandleExceptions->handleShutdown() in HandleExceptions.php
line 0 at Model->hasMany() in User.php line 39 at
User->rittenregistratie() in Model.php line 2658 at
Model->getRelationshipFromMethod() in Model.php line 2631 at
Model->getRelationValue() in Model.php line 2573 at
Model->getAttribute() in Model.php line 3291 at Model->__get() in
Controller.php line 30
EDIT:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\User;
class Car extends Model
{
protected $table = 'Car';
protected $fillable = ['beginstand', 'eindstand', 'van','naar','bezoekadres','geredenroute','karakterrit','toelichting','kilomterszakelijk','kilomtersprive'];
public function User()
{
return $this->belongsTo('App\User');
}
}
Assuming your relations are correct you should be able to do this:
$cars = Auth::user()->cars; // cars being the name of the relation method
return view('cars.index', compact('cars'));
Since you said "show his cars" I'm guessing one user can have many cars, so expect $cars to be a collection and not a single model.

Eloquent Relationship in Code Igniter

I have been working on integrating Laravel's Eloquent relationship on my Code Igniter project. So I followed the steps in http://jamieonsoftware.com/post/90299647695/using-eloquent-orm-inside-codeigniter-with-added . Everything is working fine. But When I started mapping relationships, I get error like
Fatal error: Call to undefined method Products::hasMany()
Following is my Product model file
use \Illuminate\Database\Eloquent\Model as Eloquent;
class Product extends Eloquent{
protected $table = "products";
public function getActive(){
return Product::where('status', 1)->get();
}
public function Price(){
return $this->hasMany('Price', 'product_id');
}
}
And this is my Price model
use \Illuminate\Database\Eloquent\Model as Eloquent;
class Price extends Eloquent{
protected $table = "price";
}
How to fix this issue?
you have to call it:
$product = Product::with('price')->get();
or
$product = Product::all();
$productPrice = $product[0]->price;
not
$product = Product::Price();
Some info:
If you have a 1:n relation you can define it better "prices":
public function prices(){
return $this->hasMany('Price', 'product_id');
}
it is better for reading if a product has more then one price:
$product = Product::with('prices')->find(1);

Resources