page view count LARAVEL - php

i am still new to laravel and i want to implement visitors/view counter to my page, i looked everywhere and found a way but when i tried it it doesn't seem to work properly the views are always 0 .
this is the table where the views are stored :
Schema::create('views', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->morphs('viewable');
$table->timestamps();
});
and this is the views Model :
class views extends Model
{
protected $table = 'views';
protected $guarded = ['id'];
}
and these are the functions i added to the model i want to count its visitors :
public function views()
{
return $this->morphMany(
\App\Models\views::class,
'viewable'
);
}
public function getViewsCount()
{
return $this->views()->count();
}
public function getViewsCountSince($sinceDateTime)
{
return $this->views()->where('created_at', '>', $sinceDateTime)->count();
}
public function getViewsCountUpto($uptoDateTime)
{
return $this->views()->where('created_at', '<', $uptoDateTime)->count();
}
i called the function in my blade like this :
<i class="fa fa-eye"></i> {{$details->getViewsCount()}} Views
and i'm getting 0 views, i don't know if this is working or i am doing something wrong .. any ideas please !

The problem that I can see is the relationship.
The View model contains the viewable_id and viewable_type so the relationship should be a MorphTo.
And then for example if the Post model could have views then this would have the MorphMany relationship.
You are creating a one to many polymorphic relationship documented here https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-polymorphic-relations.
Additionally, look into the withCount method, https://laravel.com/docs/8.x/eloquent-relationships#counting-related-models might be a better fit for what you want. So you can do something as follows:
Post::withCount('views');
Or if you need to filter the count based on when the view was done.
Post::withCount([
'views' => function ($query) {
$query->where('created_at', >=, $someDate)
}
]);
And then you can access it like $posts[0]->views_count.
Edit:
I would also add to make sure that if you are adding data manually the viewable_type value would need to look like this App\Models\View or in laravel versions 7 or below the default location of the file would be App\View, but this depends on the location of your models.

Related

I'm getting an error when trying to save a new model with 2 fields referencing different ids in the same table

I'm new to laravel, and I've picked up the basic workflow of creating, updating and deleting database entries using migrations, models and controllers. But now I'm trying to do the same with a subscriptions table that has a subscriberId and a followeeId in it. Both of these fields reference different ids of the same table (users). This kind of task seem to require some finetuning. And I'm stuck.
Here's my code with some comments.
Subscriptions Table
Schema::create('subscriptions', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('subscriberId');
$table->unsignedBigInteger('followeeId');
$table->foreign('subscriberId')->references('id')->on('users');
$table->foreign('followeeId')->references('id')->on('users');
});
Previously, I've used another approach to foreign ids, namely the one with the $table->foreignId('user_id')->constrained() pattern, but in this particular case I need to make sure that the two foreign ids reference different users, so I went for a more verbose option.
User Model
public function subscriptions()
{
return $this->hasMany(Subscription::class, 'subscriberId');
}
Here I've added the second parameter. This seems to work.
Subscription Model
class Subscription extends Model
{
use HasFactory;
protected $fillable = [
'subscriberId',
'followeeId'
];
public function subscriberId()
{
return $this->belongsTo(User::class, 'id', 'subscriberId');
}
public function followeeId()
{
return $this->belongsTo(User::class, 'id', 'followeeId');
}
}
Here I pass additional parameters, too, although in this case I'm not so sure if these are the correct ones. But this is my best guess. If I'm not mistaken, the second parameter of the belongsTo relation is inferred from the model that is being passed in, not the model of the parent class as is the case with the hasMany relation. So in this case that would be 'id' of the users table, which would be the default here anyway, but I need the third parameter, so I explicitly state the second parameter as well. Again, I'm not sure about this combination, but that's what I was able to make of the docs. I've also used other combinations of additional parameters, and even tried getting rid of these two public functions altogether, but that won't work either.
Now, here's the controller. If I do this:
$user->subscriptions()->get();
I do get the subscriptions I want. But if I do this instead:
$user->subscriptions()->create([
'subscriberId' => 1,
'followeeId' => 2
]);
I get the 500 error. I've also tried another approach:
$newSub = new Subscription;
$newSub->subscriberId = 1;
$newSub->followeeId = 2;
$newSub->save();
return $newSub;
But still no success. I still get the 500 error when I try to save()
Please help me out.
Solution
I should have used
public $timestamps = false
in the Subscription model, and I also misunderstood the docs. The correct combo is
User Model
public function subscriptions()
{
return $this->hasMany(Subscription::class, 'subscriberId');
}
and
Subscription Model
public function subscriberId()
{
return $this->belongsTo(User::class, 'subscriberId');
}
public function followeeId()
{
return $this->belongsTo(User::class, 'followeeId');
}

How get data having relationships between tables using Laravel

I have an API with Laravel, and I have decided to use relations between tables, I have related them using these functions in all migrations:
// Migration file: 2020_05_26_185555_create_customers_table.php on line 27
$table->foreign('user_id')->references('id')->on('users');
And then I've implemented functions like the following:
(which get the records it's related to):
// Model app\User.php on line 80
public function customers()
{
return $this->hasMany(Customer::class);
}
On Customers controller, How can I use the function to show above to list all the clients of that user** , that is, replace the following code:
// Controller Customer\CustomerController.php on line 17
public function index()
{
$user_id = Auth::id();
$customers = Customer::where('user_id', $user_id)->get();
return $this->showAll($customers, 200, $filters);
}
For something like the following (Just an example, it doesn't work, but it's the idea of ​​what I mean):
// Controller Customer\CustomerController.php on line 17
public function index()
{
$customers = User::customers(); // Ejemplo
return $this->showAll($customers, 200, $filters);
}
My goal is to create relationship between relevant table, example, a user's clients** , without using a condition, like my current implementation of code.
Can someone help me with this?
You can use the dynamic property for the relationship to access it (and have it loaded):
public function index()
{
$user = Auth::user();
$customers = $user->customers;
...
}
Laravel 7.x Docs - Eloquent - Relationships - Relationship Methods vs Dynamic Properties

Copying Data from table to another table and applying one to many relationship

This is my Report Model
protected $fillable = [
'site_url',
'reciepients',
'monthly_email_date'
];
public function site()
{
return $this->belongsTo('App\Site');
}
This is my Site Model
public function report()
{
return $this->hasMany('App\Report');
}
This is my ReportController
public function showSpecificSite($site_name)
{
$records = DB::table('reports')
->select('email_date','url','recipient')
->whereHas('sites', function($query){
$query->where('site_name',$site_name);
})
->get();
return view('newsite')->with('records',$records)
->with('site_name',$site_name);
}
My Controller is not yet working as well.
The thing is I would like to copy all the three files from sites table to reports table.
Is it possible in insertInto ?
My code on ReportController shows you that I'm selecting data from reports table but I am the one who puts data to reports table to see the output but it is not yet working because of the it cant reach out the value of site_name even though I already put a relationship between the two tables.
You're not actually using Eloquent in your controller you're just using the Query Builder (DB). This will mean that you don't have access to anything from your Eloquent models.
Try:
$records = \App\Report::whereHas('site', function($query) use($site_name) {
$query->where('site_name', $site_name);
})->get(['id', 'email_date', 'url', 'recipient']);
I've added id to the list of columns as I'm pretty sure you'll need that to use whereHas.
NB to use a variable from the parent scope inside a closure you need to pass it in using use().

laravel eloquent relations doesn't work

I am new to laravel. I am trying to build a relationship between two tables.
my database tables
comments table
$table->increments('id');
$table->text('comment');
$table->string('shop_name','80');
$table->bigInteger('product_id');
$table->timestamps();
comments_images table
$table->increments('id');
$table->bigInteger('comment_id');
$table->string('images','255');
$table->string('shop_name','80');
$table->timestamps();
=========================
Comment model
public function images()
{
return $this->hasMany(Comments_images::class,'comment_id');
}
Comments_images model
public function comments()
{
return $this->belongsTo(Comment::class);
}
I tried to return related data like this
return Comments_images::find(439)->comments()->get();
return Comment::find(880)->images()->get();
return (new Comment())->images()->get();
None of them work!
What should I do?
Are you utilizing the namespace correctly? For example, 'App\Comments_images'.. Also, models are best left singular- for example, 'Comment' or 'Comment_Image'. I bring that up because you aren't being consistent, which may be causing the error. The last thing is to use a string of the class, not returning an actual class. See the below examples, and notice capitalization and that I don't put an 's' on some things..
// in Comment model
public function images()
{
return $this->hasMany('App\Comments_Image','comment_id');
}
// in Comments_Image model
public function comment()
{
return $this->belongsTo('App\Comment', 'id', 'comment_id');
}
Edit: Feel free to use Comment::class instead of the string 'App\Comment' - It resolves to the same thing and works better with editor navigation, autocomplete, and other helpful things.

use relationship in model accessor in laravel

Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.

Categories