I'm new to Laravel and I'm trying to implement a comments system on some posts. I found a package which seems well supported and I thought I could save some time by using it rather than starting from scratch.
The packing is here:
https://github.com/actuallymab/laravel-comment
There are some usage details but they don't seem quite clear enough for someone at my level.
Where I'm at:
Composer done
Migrations done
in my "User" model:
use Actuallymab\LaravelComment\CanComment;
In my "Post" model:
use Actuallymab\LaravelComment\Commentable;
class Posts extends Model {
use Commentable;
protected $canBeRated = true;
//etc
}
In my PostsController I have:
public function comment()
{
$userid = Auth::id();
$postid = "1"; //static post id for testing
$user = User::where('id','=',$userid);
$post = Post::where('id','=',$postid)->first();
$user->comment($post, 'Lorem ipsum ..', 3); // static comment for testing
}
And finally, my posts.blade:
<form action="{{ route('posts.comment') }}" method="POST">
{{ csrf_field() }}
<input type="text" id="commentdata"/> //not using this yet
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Publish" />
<a class="btn btn-primary" href="{{ route('posts.comment') }}">Cancel</a>
</div>
Unfortunately, when I hit by submit button I get:
"Call to undefined method Illuminate\Database\Query\Builder::comment()"
So it seems I need to define a function in my User model? I'm not sure what to do here. I'm hoping some has used this package before.
Update 1:
I'm now using the following PostsController code:
public function comment()
{
$userid = "1"; //static user id for testing
$postid = "1"; //static post id for testing
$user = User::find($userid);
$post = Post::where('id','=',$postid)->first();
$user->comment($post, 'Lorem ipsum ..', 3); // static comment for testing
}
The error remains as "Call to undefined method Illuminate\Database\Query\Builder::comment()"
Call to undefined method Illuminate\Database\Query\Builder
You can be almost certain when you receive this error it's because you've missed out a step: you're calling a method on the query builder not the model. You need to retrieve the model(s) from the query.
Here's your current code:
$user = User::where('id','=',$userid);
You need to retrieve the first model from the results, e.g:
$user = User::where('id','=',$userid)->first();
Although you can improve this by using the find method which accepts a primary key and returns the model, e.g:
$user = User::find($userid);
Then from there you're ready to create the comment:
$user = User::find($userid);
$user->comment($post, 'Lorem ipsum ..', 3);
Example of using the trait:
<?php
namespace App;
use Actuallymab\LaravelComment\CanComment;
class User
{
use CanComment;
}
Related
I am creating ecommerce website in Laravel and I want to hide productdetails id in url. What can I change in code plz need solution.
Web.php
Route::get('/productdetail{id}','ProductDetailController#display_products_details');
controller code:
public function display_products_details($id)
{
$data = DB::select('select * from subcategory inner join product_details on subcategory.sub_id=product_details.sub_id where product_details.sub_id = ?',[$id]);
return view('productdetails',['data'=>$data]);
}
link tag code:
{{ $value->name_of_subcategory }}
path I getting:
localhost:8000/productdetail12
But actually I want Localhost:8000/productdetail
You can do this by having the id as part of the request body so it will not be visible in the URL (it will still be visible to anyone inspecting the request body via their browser developer tools).
You can do this by using a form to send a post request:
Route::post('/productdetail','ProductDetailController#display_products_details');
The link will change to a form:
<form method="POST" action="{{ action('ProductDetailController#display_products_details') }}>
#csrf
<input type="hidden" name="id" value="{{ $value->sub_id }}" />
<button type="submit">{{ $value->name_of_subcategory }}</button>
</form>
You may need to style the button to look like a link.
The controller becomes:
public function display_products_details(Request $request)
{
$request->validate([ 'id' => 'required|int' ]);
$id = $request->input('id');
$data = DB::select('select * from subcategory inner join product_details on subcategory.sub_id=product_details.sub_id where product_details.sub_id = ?',[$id]);
return view('productdetails',['data'=>$data]);
}
Note that while this is theoretically possible it does result in very bad user experience. People can't share product links with others for example
trying to add a comment in my blog , so i got this new error :
Add [body] to fillable property to allow mass assignment on [App\comment].
this is thr controller :
public function store (blog $getid)
{
comment::create([
'body' =>request('body'),
'blog_id'=> $getid->id
]);
return view('blog');
}
and this is the form :
<form method="POST" action="/blog/{{$showme->id}}/store" >
#csrf
<label> Commentaire </label> </br>
<textarea name="body" id="" cols="30" rows="2"></textarea> </br>
<button type="submit"> Ajouter commentaire</button>
</form>
web.php :
Route::post('blog/{getid}/store', 'commentcontroller#store');
To avoid filling in any given property, Laravel has mass asignment protection. The properties you want to be filled should be in the $fillable property on the model.
class Comment {
$fillable = ['body', 'blog_id'];
}
Bonus
For keeping up with standards. You should not name your classes in lower case, it should be Blog and Comment, both in PHP code and in file name.
Id should not be filled but associated, so they will be loaded properly on the model. So imagine your Comment model having the blog relationship.
class Comment {
public function blog() {
return $this->belongsTo(Blog::class);
}
}
You should assign it instead. Where you would get the Blog by using Model binding, therefor you should name the parameter $blog so the binding will work. Additionally using Request dependency injected, is also a good approach.
use Illuminate\Http\Request;
public function store(Request $request, Blog $blog) {
$comment = new Comment(['body' => $request->input('body')]);
$comment->blog()->associate($blog);
$comment->save();
}
I created a model relationship between User and Message. I want to implement a list of messages for the authenticated user but I get the following error.
Method Illuminate\Database\Eloquent\Collection::links does not exist
Controller
public function index()
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('message.index')->with('messages', $user->message);
}
Message provider
class message extends Model
{
public function user() {
return $this->belongsTo('App\User');
}
}
User provider
public function message ()
{
return $this->hasMany('App\Message');
}
index.blade.php
#extends('layouts.app')
#section('content')
<h1>messages</h1>
#if(count($messages)>0)
#foreach ($messages as $message)
<div class="well">
<h3>{{$message->user}}</h3>
<small>Written on {{$message->created_at}} </small>
</div>
#endforeach
{{$messages->links()}}
#else
<p> no post found </p>
#endif
#endsection
Error
"Method Illuminate\Database\Eloquent\Collection::links does not exist.(View: C:\xampp\htdocs\basicwebsite\resources\views\message\index.blade.php)"
Check your view blade, that method (links()) only could be used when your data model is implementing paginate() method.
If you dont use paginate(), remove this part:
{{$messages->links() }}
If you are trying to paginate your data when it gets to the view then you need to add the paginate in your controller before passing the data to the view. Example
return $users = Users::select('id','name')->paginate(10);
with that paginate method in your controller, you can call the links method to paginate your object in view as shown below
{{$users->links()}}
hope it helps you
There are 2 ways to resolve this issue:
Either use paginate function while searching data from database:
$users = DB::table('users')->where('id',$user_id)->paginate(1);
Remove links() function from index.blade.php
{{ $messages->links() }}
Remove {{ $messages->links() }} to in your index.blade.php because {{ $messages->links() }} is supported only when you use paginate
You can do something like this in your controller file.
public function index()
{
$messages = Message::all()->paginate(5);
$user_id = auth()->user()->id;
$user = User::find($user_id);
return view('message.index')->with('messages', $messages, $user->message);
}
i am trying to make a list of locations that you can rent. but to rent the place you need to fill in some information. to fill in this information you excess another page. how do i make it so laravel knows the page belongs to a certain location
this is what ive done now but i keep getting the error:
Call to undefined method App\Reservation::location()
as soon as i have filled in the fields of information
this is the blade file that links to the the create reservation file
#foreach
($locations as $location => $data)
<tr>
<th>{{$data->id}}</th>
<th>{{$data->name}}</th>
<th>{{$data->type}}</th>
<th><a class="btn" href="{{route('Reservation.index', $data->id)}}">rent</a></th>
</tr>
#endforeach
this is the create reservations blade
<form action="{{ route('location.store') }}" method="post">
#csrf
<label>title</label>
<input type="text" class="form-control" name="name"/>
<label>type</label>
<select>
<option value="0">klein</option>
<option value="1">groot</option>
</select>
<button type="submit" class="btn">inschrijven</button>
</form>
this is what the location controller looks like
public function store(Request $request)
{
$location = new Reservation;
$location->name = $request->get('name');
$location->type = $request->get('type');
$location->location()->associate($request->location());
$location->save();
return redirect('/location');
}
and the relationships in my models should also work
class Reservation extends Model
{
public function locations()
{
return $this->belongsTo('Location::class');
}
}
class Location extends Model
{
public function reservations()
{
return $this->hasMany('Registration::class');
}
}
ive been stuck at this all day and i really dont know where to look anymore
The error you are getting is because of the wrong function name, you are calling location, while it is locations.
public function locations(){}
&
$location->location()->associate($request->location());
and you can pass the variable as a query parameter, you'll need to pass this data as an array in your blade file.
Web.php
Route::get('/somewhere/{id?}, function(){
//do something
})->name('test');
Blade
route('test', ['id' => $id]);
Controller Method
public function store(Request $request, $id) //Adding the query parameter for id passed in Route.
{
$location = new Reservation;
$location->name = $request->get('name');
$location->type = $request->get('type');
$location->location()->associate($id);
$location->save();
return redirect('/location');
}
I'm new to this so i have this silly question.I want to make a login form and when the user logs in i want to show all his information in the screen(username attack defence...).The thing is i don't know how to call the specific function i've made because in my controller calls function index() by default and not the function guser().
login view
<h2>Login</h2>
<?php if($error==1){ ?>
<p>Your Username/password did not match </p>
<?php } ?>
<form action="<?=base_url()?>index.php/Users/login" method="post">
<p>Username: <input name="user" type="text" /> </p>
<p>Password: <input name="password" type="password" /> </p>
<p><input type="submit" value="Login" /></p>
</form>
users controller
<?php
class Users Extends CI_Controller{
function __construct(){
parent::__construct();
$this->load->model('User');
}
function index(){
$data['users']=$this->User->get_users();//sto model post tha kalesei tin sinartisi get_posts
$this->load->view('Post_index',$data);
}
function guser($id){
$data['user']=$this->User->get_user($id);
$this->load->view('Post_index',$data);
}
function login(){
$data['error'] = 0; // simenei oti den exei errors
if($_POST){
$user=$this->input->post('user',true);//pairnei to username p edose o xristis(einai idio me to $_POST)
$password=$this->input->post('password',true);//pairnei to password p edose o xristis
//$type=$this->input->post('charact',true);
$user1=$this->User->login($user,$password);//,$type);
if(!$user1){
$data['error']=1;
}else{
$this->session->set_userdata('id',$user1['id']);
$this->session->set_userdata('user',$user1['user']);
$this->session->set_userdata('name',$user1['name']);
$this->session->set_userdata('money',$user1['money']);
$this->session->set_userdata('attack',$user1['attack']);
$this->session->set_userdata('defence',$user1['defence']);
$this->session->set_userdata('level',$user1['level']);
$this->session->set_userdata('xp',$user1['xp']);
redirect(base_url().'index.php/Users');
}
}
$this->load->view('Login',$data);
}
function registerSam(){
if($_POST){
$data=array(
'user'=>$_POST['user'],
'name'=>$_POST['name'],
'password'=>$_POST['password'],
'charact'=>"Samurai",
'money'=>400,
'attack'=>10,
'defence'=>5,
'level'=>0,
'xp'=>0
);
$userid=$this->User->create_user($data);
}
}
function registerKnight(){
if($_POST){
$data=array(
'user'=>$_POST['user'],
'name'=>$_POST['name'],
'password'=>$_POST['password'],
'charact'=>"Knight",
'money'=>400,
'attack'=>5,
'defence'=>10,
'level'=>0,
'xp'=>0
);
$userid=$this->User->create_user($data);
}
}
}
?>
user model
<?php
class User Extends CI_Model{
function create_user($data){
$this->db->insert('unityusers',$data);
}
function login($user,$password){
$where=array(
'user'=>$user,
'password'=>$password,
);
$this->db->select()->from('unityusers')->where($where);
$query=$this->db->get();
return $query->first_row('array');
}
function get_user($id){
$this->db->select()->from('unityusers')->where(array('id'=>$id));
$query=$this->db->get();
return $query->first_row('array');
}
function get_users($num=20,$start=0){// tha paroume 20 posts k tha arxisoume apo to proto
$this->db->select()->from('unityusers')->limit($num,$start);
$query=$this->db->get();
return $query->result_array();
}
}
?>
Although you have accepted the answer I like to point out some basic functionality for you to more improved code.
Different technique to load the data to view from controller:
function index(){
$users = $this->User->get_users();
$this->load->view('Post_index',['users' => $users, 'any_other_data' => $any_other_data ... and so on]);
}
When you get post data in the controller then you should check for a validation first inside your login function. And in login functionality it will be more useful. setting-validation-rules
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required',
Loading a model and it's function. You don't need to use uppercase in this as give below.
$this->load->model('user');
$this->user->get_users();
Your registration Function registerSam you don't need to create an array of post data Codeigniter will provide the functionality to get all your post data at once. To remove unnecessary data from that array use unset.
$your_post_array = $this->input->post();
To call a specific function made, you can access it via a browser using the link
BASE_URL/index.php/ControllerName/MethodName
So, in your case to call the guser method, the url would be
BASE_URL/index.php/users/guser
Hope that helps.
You have an error in guser function on the controller. You don't need to passs any argument to the function. You can get ID of user from the session, which was actually added in session once the user has entered correct credentials.
Also after login, you need to redirect user to guser function instead of users. Because as per your controller users function dosen't exist.
Change From
redirect(base_url().'index.php/Users');
To
redirect(base_url().'index.php/guser');
Please check below for solution.
function guser(){
$data['user']=$this->User->get_user($this->session->userdata('id'));
$this->load->view('Post_index',$data);
}
Let me know if it not works.