I am working on a web programing assignment for University and have hit a snag when trying to make a like and dislike function for a comments area of a guestbook.
Evectively the numbers on the site should update by one once either the dislike or like button is pressed.
My comments display correctly however the liking function is broken and I have no idea how to fix it.
Here is my code
Controller (LikesController.php)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class LikesController extends Controller (It says my Like Controller is never used not sure why this is)
{
public function likepl (Comment, $comment) { (Says that Comment is "Undefined" also not sure why this is)
$comment -> likePlus (); (Method likePlus not found)
return redirect () -> action ('CommentController#index');
}
}
Model (comment.php)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public static function paginate(int $COMMENTS_PER_PAGE)
{
}
public function likePlus()
{
$this -> likes += 1;
$this -> update ();
}
public function dislikePlus()
{
$this -> dislikes += 1;
$this -> update ();
}
}
View Page (comment.comments)
#extends('setup')
#section('content')
<div class="container main-table">
<div class="box">
<h1 class="title">Guest book Comments</h1>
#if (count ($comments) > 5)
<table class="table is-striped is-hoverable">
<thead>
<tr>
<th>User</th>
<th>Comment</th>
<th>Date</th>
<th>Likes</th>
<th>DisLikes</th>
</tr>
</thead>
<tr>
#foreach ($comments as $c)
{{--declaring the comments--}}
<tr>
<td>{{ $c -> user }}</td>
<td>{{ $c -> comments }}</td>
<td>{{ $c -> created_at -> format ('D jS F') }}</td>
<td>{{ $c -> likes }}</td>
<td>{{ $c -> dislikes }}</td>
</tr>
<tr class="icon heart">
<td><a class="button" href="/comment/{{ $c -> id }}/like/"><ion-icon name="md-heart"></ion-icon></a></td>
<td><a class="button" href="/comment/{{ $c -> id }}/dislike/"><ion-icon name="md-heart-empty"></ion-icon></a></td>
</tr>
#endforeach
</table>
{{ $comments -> links() }} {{-- Setting pagination--}}
#else
<div class="notification is-info">
<p>
The Guest book is empty. Why not add a comment?
</p>
</div>
#endif
</div>
</div>
#endsection
I have annotated the code with the visible errors that I get as for better refference.
Here are the Routes that I am using for the comments page.
Route::get('/','CommentController#index');
Route::get('/comment/{comment}/like/', 'LikesController#likePl');
Route::get('/comment/{comment}/dislike/', 'DislikesController#dislikePl');
The update() function does not work the way you are using it. You either update the property and use the save() function, or you pass an array to the update function.
// 1.
$this->likes += 1;
$this->save();
// 2.
$this->update([
'likes' => $this->likes + 1,
]);
Update: Even better would be to use the built-in increment() function:
$this->increment('likes');
This way there is no need to know the number of likes beforehand.
Can we please work on the following first.
LikePl function name should match the name on the router (action#method)
The method inside the controller accept request like so
public function likePl (Request $request) { //code here }
Methods inside the Model are accessed using their namespace like so
App\Comment::likePlus() or you can import the namespace like "use App\Comment" there after inside the method just simply do "Comment::likePlus()".
Please refer here Laravel models for more information.
Fixing this will remove the errors you currently have. Use "dd($request->all())" inside your likePl method to check if you are getting the values you expect.
Hope this help a bit...
Related
I have 2 tables in my db, 1 for Collabs and 1 for Projects
I want when I view a project, to display the collabs based on that project (if i press view on a project for example project with id = 10, to display all Collabs for the project that is id 10).
For Collabs table I have id_project that is wanted to be in relationship with id from Project table, so when I insert a new collab in my Collabs table it takes the id from the project I inserted.
For now, this is how I display the collabs, and i display them all for all projects but I don't want that.
#forelse ($istoric as $istProj)
<div class="mb-3">
<table class='table'>
<tr class="table-row-heads">
<th>Id Proiect</th>
<th>Tip actiune </th>
<th>Colaborator </th>
<th>Suma </th>
<th>Data </th>
</tr>
<tr class="table-row-data">
<td>{{ $istProj->id_proiect }}</td>
<td>{{ $istProj->action_type }}</td>
<td>{{ $istProj->colaborator_id }}</td>
<td>{{ $istProj->suma }}</td>
<td>{{ $istProj->data }}</td>
</tr>
</table>
</div>
#empty
<div class="card-body">
<h2>Nu au fost gasite inregistrari</h2>
</div>
#endforelse
You should really consider reading and watching more videos on how relationships and eloquent works, I hope this below is a good reference for you to get started, please read carefully, and sorry I couldn't translate back to romanian, and to avoid any mistakes, I kept my code in english.
Caloboratori = Colaborators
Istoric Proiecte = Project History
id || auto_increment
project_id || bigInteger()
colaborator_id || bigInteger()
Proiecte = Project
id || auto_increment
Project Model
/* To load the history, we will be using hasMany relationship, because for each
project, we have lots of history, please read more on one-to-many relationships here
https://laravel.com/docs/9.x/eloquent-relationships#one-to-many
Istoric Proiecte = Project History
id || auto_increment
project_id || bigInteger()
colaborator_id || bigInteger()
*/
public function histories() {
return $this->hasMany(ProjectHistory::class);
}
Project History Model
//We will reverse the one-to-many relationship, with belongsTo here. | example: project_id
public function project() {
return $this->belongsTo(Project::class);
}
//We will reverse the one-to-many relationship, with belongsTo here. | example: colaborator_id
public function colaborator() {
return $this->belongsTo(Colaborator::class);
}
Projects Controller:
// Show a list of all projects
public function index() {
//Get all projects
$projects = Project::all();
//Load all of the project relationships that we will be using
$projects->load('histories.colaborator');
return view('projects.index', compact('projects'));
}
// Show a single project
public function show(Project $project) {
//Load all of the project relationships that we will be using
$project->load('histories.colaborator');
//Assign the loaded project history
$histories = $project->histories;
return view('projects.show', compact('project', 'histories'));
}
projects.index Blade: in this blade, you can forloop thru all of your projects model, and assign them as $project, since we loaded the relationships earlier from the controller.
You can easily access the relationships using $project->histories then assign each history model to $history.
Then you can go one step inside of the history relationship and call the inner relationship of colaborator with $history->colaborator
#foreach ($projects as $project)
<p>Project id: {{ $project->id }}
<p>Project name: {{ $project->name }}
<h1>Project History list</h1>
#foreach ($project->histories as $history)
<ul>
<li>ID: {{$history->id}}</li>
<li>Name: {{$history->name}}</li>
<li>Colaborator Name: {{$history->colaborator->name}}</li>
</ul>
#endforeach
#endforeach
projects.show Blade: in this blade, we have a single project, and you can forloop thru all of your history models, since we loaded the relationships from the controller.
We assigned the histories collection as $histories then assign each history model to $history
Then you can go one step inside the history relationship and call the inner relationship of colaborator with $history->colaborator
<p>Project name: {{ $project->name }}
<h1>Project History list</h1>
#foreach ($histories as $history)
<ul>
<li>ID: {{$history->id}}</li>
<li>Name: {{$history->name}}</li>
<li>Colaborator Name: {{$history->colaborator->name}}</li>
</ul>
#endforeach
If you use model Collab, and within you have project relation , than you can use
Collab::query()
->with('project', function ($q) use ($id) {
return $q->where('id', $id);
})
->get();
Or you can use query builder as well
DB::table('collabs')
->select('collabs.*')
->join('projects', 'projects.id', '=', 'collabs.project_id')
->where('projects.id', $id)
->get();
Just adjust it according what you really need.
As the title says with other controller and view I can send the data but I can't with the controller and view I'm gonna post below.
Controller code (Its a resource controller but I'm using a custom function)
<?php
namespace App\Http\Controllers;
use App\Models\Persona;
use Illuminate\Http\Request;
class PersonaController extends Controller
{
public function mostrarMedicos(){
$medicos = Persona::where('idTipoPersona', 4)->get();
return view('gestionMedicos',compact($medicos));
}
}
View Code
#extends('layouts.app')
#section('content')
<h1>Gestión Médicos</h1>
<div class="container">
<table class="table table-bordered table-hover">
<tr class="info">
<th>Nombre</th>
<th>Apellido</th>
<th>Cedula</th>
<th>Email</th>
<th>Teléfono</th>
<th>Dirección</th>
<th>Ciudad Residencia</th>
<th>Fecha de Nacimiento</th>
<th>Género</th>
</tr>
#foreach ($medicos as $medico)
<tr>
<td>{{$medico->nombre}}</td>
<td>{{$medico->apellido}}</td>
<td>{{$medico->cedula}}</td>
<td>{{$medico->email}}</td>
<td>{{$medico->telefono}}</td>
<td>{{$medico->direccion}}</td>
<td>{{$medico->ciudadResi}}</td>
<td>{{$medico->fechaNacimiento}}</td>
<td>{{$medico->genero}}</td>
</tr>
#endforeach
</table>
Route
Route::get('/gestionarMedicos', [PersonaController::class,'mostrarMedicos'])->name('personaMostrarMedicos');
This is the error I'm getting
Undefined variable $medicos (View: D:\xampp\htdocs\SistemaHNF\resources\views\gestionMedicos.blade.php)
Im new on Laravel and I don't understand why I get this error if from what I can understand the controller is supossed to return the view with the $medicos variable that should have the data.
(English is not my main language so sorry for any mistake and also I can post any extra code or explain in more detail something if needed).
You have return query builder and forgotten to call get() or first() and also wrong with compact
public function mostrarMedicos(){
$medicos = Persona::where('idTipoPersona', 4)->get();
return view('gestionMedicos',compact('medicos'));
}
I am having issues understanding the "belongsTo" method in a class I am working with.
I have an "Asset" model which wasn't written by me, but I'd guess it works, and it has this function where I am trying to access the 'name' property of the "AssetMake" table (Which foreign and primary key args look about right):
public function assetMake()
{
return $this->belongsTo(AssetMake::class, 'assetmake_id', 'id');
}
In a blade template that looks something like this, with the $asset variable injected in (and succesfuly already being used on the same page):
#foreach($assets as $asset)
<tr>
<td width="5%" class="filter_id">{{ $asset['unit_id'] }}</td>
<td width="20%" class="filter_type">{{ $asset['TypeName'] }}</td>
<td width="25%">{{ $asset['description'] }}</td>
<td width="20%">{{ $asset->assetMake()->get() }}</td>
</tr>
#endforeach
"AssetMake" looks like this, do I need a corresponding "hasMany" function?:
class AssetMake extends Model
{
use ModelDateSerializeNonISO;
protected $table = 'assetmake';
protected $primaryKey = 'id';
protected $hidden = ['updated', 'created'];
}
I have tried acessing the injected $asset variable in a blade template as such:
<td width="20%">{{ $asset->assetMake->get }}</td>
<td width="20%">{{ $asset->assetMake->get() }}</td>
<td width="20%">{{ $asset->assetMake()->get }}</td>
<td width="20%">{{ $asset->assetMake->name }}</td>
<td width="20%">{{ $asset->assetMake()->name }}</td>
The 'name' property of the assetmake table is what I really need access to here.
Is this some kind of lazy/eager loading problem? I'm just not sure exactly what's happening here, and why I can't access the property. I've checked in various sources, and nothing I've tried works, but I'm sure it's fairly straight forward. Any tips?
The way to access a related model is to call it as you would normally call a property. So something like $asset->assetMake->name should work.
Behind the scenes, I believe Laravel uses PHP's magic methods to create properties on the model based on the method names so that they point to the related model (parent or child).
Similarly, if you have a hasMany relationship like so:
public function children()
{
return $this->hasMany(Child::class, 'child_id',);
}
You can access the children just by calling $parent->children.
And if you need to access the Child query builder from the parent, you have to call the children() method.
E.g
$parent->children()->create($childData)
Ok, I worked it out. It was an issue with the controller. I'm still working this out and the magic in Laravel can be confusing to me. I added the line "->join('assetmake', 'assetmake.id', 'asset.assetmake_id')" to the controller query. And added to the select statement as well 'assetmake.name as AssetMakeName'
$assets = FleetFuel::where('fleet_fuel.customer_id', $user->customer_id)
->where('fleet_fuel.isOrphan', 0)
->where('fleet_fuel.hours', '>=', 0) // -1.00 = first ever record
->where('fleet_fuel.burn', '>=', 0) // -1.00 = first ever record
->join('asset', function($join) {
$join->on('fleet_fuel.unit_id', '=', 'asset.Unit_ID');
$join->on('fleet_fuel.customer_id', '=', 'asset.Customer_ID');
})
->join('assettype', 'assettype.ID', 'asset.assettype_id')
->join('assetmake', 'assetmake.id', 'asset.assetmake_id')
->select('fleet_fuel.unit_id', DB::raw('max(fleet_fuel.delivery) as lastfuel'), 'asset.description', 'asset.Rego', 'assettype.Name as TypeName', 'assetmake.name as AssetMakeName')
->groupBy('fleet_fuel.unit_id')->get();
return view('fleetFuel.assets',
[
'companyName' => $companyName,
'assets' => $assets
]
);
And then accesed it in the blade view:
<td width="20%" class="filter_make">{{ (isset($asset['AssetMakeName'])) ? ($asset['AssetMakeName']) : ("No make available")}}</td>
I'm getting an error undefined variable when I'm trying to get username ($user->name) from User model using id which is foreign key ($feedback->user_id) of Feedback model.
#php
use App\Feedback;
use App\User;
$feedbacks = Feedback::all();
#endphp
<!DOCTYPE html>
<html>
<body>
ADMIN DASHBOARD | LOGOUT<br><br>
<h3>Feedbacks</h3>
<table border="1">
<tr><th>ID</th><th>Left By</th><th>Feedback</th></tr>
#foreach ($feedbacks as $feedback)
<tr>
<td>{{ $feedback->id}}</td>
<td>{{ $user->name }}</td>
<td>{{ $feedback->feedback }}</td>
</tr>
$uid=$feedback->user_id;
$user= User::find($uid);
#endforeach
</table>
</body>
</html>
I would suggest creating a relation between feedback and user (If you don't have one already). Your relation would be put within the Feedback model and look like this:
// Feedback.php
public function user() {
return $this->belongsTo('App\User');
}
This will relate the feedback to the user using the user_id on the feedback table.
After this, when calling feedback within your controller, you can then eager load the user relation with each feedback. This can be done within the following:
$feedbacks = Feedback::with('user')->get();
Finally, within your template, you will able to call the user through each feedback by doing the following:
{{ $feedback->user->name }}
Note: This example assumes name is a field on your user table.
I am trying to implement pagination in laravel and got following error
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$name
Here is my controller function
public function showTags($id)
{
$tag = Tag::find($id)->paginate(5);
// when lazy loading
$tag->load(['posts' => function ($q) {
$q->orderBy('id', 'desc');
}]);
return view('blog.showtags')->withTag($tag);
}
Here is the Tag Model
class Tag extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post');
}
}
The Tag and Post model has belongsToMany Relationship so there are many posts under the specific tag and my aim is to iterate all posts under the specific tags descending order of post and also to implement pagination in that page.
Here is the code for showtags view
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Title</th>
<th>Tags</th>
</tr>
</thead>
<tbody>
<?php $count = 1; ?>
#foreach($tag->posts as $post)
<tr>
<th>{{ $count++ }}</th>
<th>{{ $post->title }}</th>
<th>#foreach($post->tags as $tag)
<span class="label label-default">{{ $tag->name }}</span>
#endforeach
</th>
</tr>
#endforeach
</tbody>
</table>
//Here is the code i used for pagination in view
<div class="text-center">
{!! $tag->posts->links() !!}
</div>
If anybody know how to do this please respond. Thanks in advance.
I solve the problem by using a simple trick. My aim was to paginate all posts under the same tags just like you guys can see in StackOverflow.
The modified controller function is
public function showTags($id)
{
$tag = Tag::find($id);
// when lazy loading
$tag->load(['posts' => function ($q) {
$q->orderBy('id', 'desc')->paginate(10);
}]);
return view('blog.showtags')->withTag($tag);
}
As you guys see that I move the paginate() function from find to load function which I use before for sorting post by descending order.
Now in view instead of using traditional method {!! $tag->links() !!} for making link of pagination
I use {!! $tag->paginate(10) !!}
With this line $tag = Tag::find($id)->paginate(5); You should get only one tag(or null if tag with your id dose not exist), and after that you want paginate it. If you want paginate your tags get all tags and after that paginate it Tag::paginate(5)