I have a list of properties for a real estate application and im trying to implement a like/unlike functionality based on each property detail. The idea is to add a like or remove it matching the current property and user. This is my code so far, but it only remove likes so it doesnt work as expected. If anyone can suggest for a better approach ill be appreciated.
//Controller
public function storeLike($id)
{
$like = Like::firstOrNew(array('property_id' => $id));
$user = Auth::id();
try{
$liked = Like::get_like_user($id);
}catch(Exception $ex){
$liked = null;
}
if($liked){
$liked->total_likes -= 1;
$liked->status = false;
$liked->save();
}else{
$like->user_id = $user;
$like->total_likes += 1;
$like->status = true;
$like->save();
}
return Redirect::to('/detalle/propiedad/' . $id);
}
// Model
public static function get_like_user($id)
{
return static::with('property', 'user')->where('property_id', $id)
->where('user_id', Auth::id())->first();
}
// Route
Route::get('store/like/{id}', array('as' => 'store.like', 'uses' => 'LikeController#storeLike'));
#Andrés Da Viá Looks like you are returning object from model. In case there is no data in database, it will still return an object - so far my guessing. Can you do something like below in the if($liked){ code?
Try this instead:
if(isset($liked -> user_id)){
Also try to print $liked variable after try and catch blocks. Use var_dump.
If this still does not work for you then let me know. I will try to create code based on your question.
Fix it by adding a where clause in my model to make the status equal to True ->where('status', 1)->first();
Related
I made code like this in Models Number_npe:
public function nomor_akhir()
{
$query = DB::table('nomor_npe')
->select('*')
->orderBy('id','DESC')
->first();
return $query;
}
Then the Controllers:
public function nomor_npe_store(Request $req)
{
$tanggal_npe = $req->input('tanggal_npe');
$pesan = new Nomor_npe();
$check = $pesan->nomor_akhir();
if($check) {
$nomor_npe = $check->nomor_npe+1;
}else{
$nomor_npe = 1;
}
DB::table('nomor_npe')->insert([
'nomor_npe' => $nomor_npe,
'tanggal_npe' => $tanggal_npe
]);
return redirect('nomor_npe')->with('success','Nomor NPE berhasil ditambahkan');
}
The Add NPE Number display looks like this:
When I click Save, the number_npe has been successfully added automatically.
But I want to make when the year changes, the number_npe restarts automatically from 1 again ... Please help everyone who knows
I have to write this as an answer, but it is not 100% an answer to your code, these are just tips for you to have better code. (So if anyone sees this too, they are aware too)
First of all, avoid 100% writing code in other language than English, as we are following it (we do not speak your language) and we do not understand nearly anything unless we use a Translator...
So, if you are going to use Laravel, try to avoid using DB, when you can just use the Model (hopefully you have created it...).
So your class should look like this:
public function lastNumber()
{
return NomorNpe::orderByDesc('id')->first();
}
Then your controller should be like:
public function store(Request $request, NomorNpe $nomor_npe)
{
NomorNpe::create([
'nomor_npe' => $nomor_npe->lastNumber() ? $nomor_npe->lastNumber()->nomor_npe + 1 : 1,
'tanggal_npe' => $request->input('tanggal_npe')
]);
return redirect('nomor_npe')->with('success', 'Nomor NPE berhasil ditambahkan');
}
See how I reduced everything from 13 lines of code to 5 lines of code and is 100% readable... (Or 9 lines to 2)
Make sure to use what Laravel brings you as "default" for it, use Models not DB::table('xxx'), take advantage of Eloquent.
Use this code for starting the number from 1, when the year changed:
public function nomor_npe_store(Request $req) {
$tanggal_npe = $req->input('tanggal_npe');
//---Current Date
$date = date('Y-m-d', time());
//---NOMOR NPE
$nomor_npe = DB('number_npe')->whereYear('tanggal_npe', $date)->max('normor_npe');
if (!$nomor_npe) {
$nomor_npe = 1;
} else {
$nomor_npe++;
}
DB::table('nomor_npe')->insert([
'nomor_npe' => $nomor_npe,
'tanggal_npe' => $tanggal_npe
]);
return redirect('nomor_npe')->with('success','Nomor NPE berhasil ditambahkan');
}
I want to implement a system in my project that "alerts" users when there is a new comment on one of their posts.
I currently query all comments on the posts from the logged in user and put everything in an array and send it to my view.
Now my goal is to make an alert icon or something when there is a new item in this array. It doesn't have to be live with ajax just on page load is already good :)
So I've made a function in my UsersController where I get the comments here's my code
public function getProfileNotifications()
{
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
//comments
if (!empty($projects)) {
foreach ($projects as $project) {
$comments_collection[] = $project->comments;
}
}
if (!empty($comments_collection)) {
$comments = array_collapse($comments_collection);
foreach($comments as $com)
{
if ($com->from_user != Auth::user()->id) {
$ofdate = $com->created_at;
$commentdate = date("d M", strtotime($ofdate));
$comarr[] = array(
'date' => $ofdate,
$commentdate,User::find($com->from_user)->name,
User::find($com->from_user)->email,
Project::find($com->on_projects)->title,
$com->on_projects,
$com->body,
Project::find($com->on_projects)->file_name,
User::find($com->from_user)->file_name
);
}
}
} else {
$comarr = "";
}
}
Is there a way I can check on page load if there are new items in the array? Like keep a count and then do a new count and subtract the previous count from the new one?
Is this even a good way to apprach this?
Many thanks in advance! Any help is appreciated.
EDIT
so I added a field unread to my table and I try to count the number of unreads in my comments array like this:
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
//comments
if (!empty($projects)) {
foreach ($projects as $project) {
$comments_collection[] = $project->comments;
}
}
$unreads = $comments_collection->where('unread', 1);
dd($unreads->count());
But i get this error:
Call to a member function where() on array
Anyone any idea how I can fix this?
The "standard" way of doing this is to track whether the comment owner has "read" the comment. You can do that fairly easily by adding a "unread" (or something equivalent) flag.
When you build your models, you should define all their relationships so that stuff like this becomes relatively easy.
If you do not have relationships, you need to define something like the following:
In User
public function projects()
{
return $this->hasMany('App\Models\Project');
}
In Project
public function comments()
{
return $this->hasMany('App\Models\Comment');
}
Once you hav ethose relationshipt, you can do the following. Add filtering as you see fit.
$count = $user->projects()
->comments()
->where('unread', true)
->count();
This is then the number you display to the user. When they perform an action you think means they've acknowledged the comment, you dispatch an asynchronous request to mark the comment as read. A REST-ish way to do this might look something like the following:
Javascript, using JQuery:
jQuery.ajax( '/users/{userId}/projects/{projectId}/comments/{commentId}', {
method: 'patch'
dataType: 'json',
data: {
'unread': false
}
})
PHP, in patch method:
$comment = Comment::find($commentId);
$comment->update($patchData);
Keep in mind you can use Laravel's RESTful Resource Controllers to provide this behavior.
try this
$unreads = $project->comments()->where('unread', 1);
dd($unreads->count());
EDIT
My be Has Many Through relation will fit your needs
User.php
public function comments()
{
return $this->hasManyTrough('App\Project', 'App\Comment');
}
Project.php
public function comments()
{
return $this->hasMany('App\Comment');
}
then you can access comments from user directly
$user->comments()->where('unread', 1)->count();
or I recommend you define hasUnreadComments method in User
public function hasUnreadComments()
{
$return (bool) $this->comments()->where('unread', 1)->count();
}
P.S.
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
this code is horrible, this way much better
$projects = Auth::user()->projects;
Here's my function to load submissions created by a user.
public function viewSubs()
{
$user = User::find(Input::get('id'));
$submissions = Submission::find($user)->sortByDesc('created_at');
$submissions->load('user')->load('votes')->load('suggestions.votes');
return view('submissions.index' , compact('submissions'));
}
This returns with an error
Call to a member function load() on null
when there are no records on the submission.
How to handle if there are no submission on the DB?
Just check if its null first using an if statement:
public function viewSubs()
{
$user = User::find(Input::get('id'));
if ($submissions = Submission::find($user)->sortByDesc('created_at')) {
$submissions->load('user')->load('votes')->load('suggestions.votes');
}
return view('submissions.index' , compact('submissions'));
}
Also, depending on your DB structure I'm pretty sure you can cut out a lot of the code by utilising your models' relationships by doing something like this:
$user = User::find(Input::get('id'))
->with(['submissions' => function($query) {
$query->orderBy('created_at', 'asc');
}, 'submissions.votes', 'submissions.suggestions.votes']);
Then pass the $user variable to the view, or:
$submissions = Submission::with('user', 'votes', 'suggestions.votes')
->where('user_id', Input::get('id'))
->sortByDesc('created_at')
->first();
Not entirely sure the code will work perfectly, but I'm sure you can tweak it. The point is your code can be a lot shorter and still/or more readable by using relationships you've already set up.
When I use Query Builder I Always find myself doing something like this:
$item = \DB::table('table')->where('slug',$slug)->first();
if ($item===null)
throw \Exception('Not found');
This could be easly solved if there were a firstOrFail() like Eloquent:
$item = \DB::table('table')->where('slug',$slug)->firstOrFail();
Is Eloquent the only way to use firstOrFail()? Does Query Builder allow something like this?
You can add it yourself to the query builder, via a macro:
DB::query()->macro('firstOrFail', function () {
if ($record = $this->first()) {
return $record;
}
throw new Exception('No records found');
});
Then you can use it the same way you do Eloquent:
$item = DB::table('table')->where('slug', $slug)->firstOrFail();
you are almost there, laravel does provide a way to check something like this
DB::table('table')->where('slug', $slug)->exists()
DB::table('table')->where('slug', $slug)->doesntExist()
it will return boolean, hope this helps
Update:
how i did it in projects was
function checkIfExists($table, $value, $field = 'id'){
return DB::table($table)->where($field, $value)->exists()
}
function getFirst($table, $value, $field = 'id'){
return DB::table($table)->where($field, $value)->first()
}
and then use this function like this
if(checkIfExists('users', 2))
$user = getFirst('users', 2)
else
// throw exception or something
Hope this helps
I am currently writing an adress book and using a framework (CakePHP) an MVC for the first time. Unfortunately I have some trouble.
I want to realize the following:
In case the URL is
/contacts/view/
I want to show all contacts in a list. In case there is an id given after /view/, e.g.
/contacts/view/1
I just want to display the contact with the id 1. (complete different view/design than in the first case)
My ContactsController.php is the following
public function view($id = null){
if(!$this->id){
/*
* Show all users
*/
$this->set('mode', 'all');
$this->set('contacts', $this->Contact->find('all'));
} else {
/*
* Show a specific user
*/
$this->set('mode','single');
if(!$this->Contact->findByid($id)){
throw new NotFoundException(__('User not found'));
} else {
$this->set('contact', $this->Contact->findByid($id));
};
}
}
But "$this->mode" is always set as "all". How can I check whether the id is set or not?
I really want to avoid "ugly" URL-schemes like ?id=1
Thanks in advance!
Your code is only meeting the if part and its not going to else part. Use (!$id)..
$_GET data is retrieved through the URL. In CakePHP this means it's accessed through that method's parameters.
I'm arbitrarily picking names, so please follow! If you're in the guests controller and posting to the register method you'd access it like this
function register($param1, $param2, $param3){
}
Each of these params is the GET data, so the URL would look something like
www.example.com/guests/param1/param2/param3
So now for your question How can I check whether the id is set or not?
There are a couple of possibilities. If you want to check if the ID exists, you can do something like
$this->Model->set = $param1
if (!$this->Model->exists()) {
throw new NotFoundException(__('Invalid user'));
}
else{
//conduct search
}
Or you can just search based on whether or not the parameter is set
if(isset($param1)){ //param1 is set
$search = $this->Model->find('all','conditions=>array('id' => $param1)));
}
else{
$search = $this->Model->find('all');
}
You should only change the conditions not the whole block of code like
public function view($id = null){
$conditions = array();
$mode = 'all';
if($id){
$conditions['Contact.id'] = $id;
$mode = 'single';
}
$contacts = $this->Contact->find('all', array('conditions' => $conditions));
$this->set(compact('contacts', 'mode'));
}