User Submitted Posts using Laravel - php

I am trying to build an application wich it will contain an admin dashboard where the admin will be able to CRUD Posts but also he will be able just to see User Submitted Posts.
On the other hand the guest will be able to just see the Posts, but he will be able to Create User Submitted Posts.
Until now I have managed to get the Posts functionallity working, but not for the User Submitted Posts.
My Controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Usp;
class AdminUserPostsController extends Controller
{
public function index()
{
$userposts = Usp::orderBy('id', 'desc')->paginate(10);
return view('admin.userposts.archive')->withUsp($userposts);
}
public function show($id)
{
$userpost = Usp::find($id);
return view('admin.userposts.show')->withUsp($userpost);
}
}
My Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Usp extends Model
{
//
}
My Archive View
#extends('admin')
#section('dashboard-content')
<div class="col-md-8 offset-md-2">
<h1>Posts Archive</h1>
<hr>
</div>
#foreach ($userposts as $userpost)
<div class="col-md-6 offset-md-2">
<h3>Title: {{ $userpost->title }}</h3>
<hr>
</div>
#endforeach
#endsection
and My Routes(for the specific controller)
Route::get('/admin/userposts', 'AdminUserPostsController#index')->name('admin.userposts.archive');
Route::get('/admin/userposts/{id}', 'AdminUserPostsController#show')->name('admin.userposts.show');
I am getting the error that userposts variable is not defined, although I define it in my Controller. Anyone that can help ?

You should "transmit" your variables to your view. There are several ways to do this, but I'd say the most common is to use the "with compact". In your case, you should change this
return view('admin.userposts.archive')->withUsp($userposts);
To this
return view('admin.userposts.archive')->with(compact('userposts'));
How does it work :
compact("varname", [...])
returns an array with the keys being the variable name and the values being the variable values
And the with just transmits all the array to the view
PS :
compact('userposts')
Is exactly the same as this
['userposts' => $userposts]

If you want to use userposts variable, do this:
return view('admin.userposts.archive', compact('userposts');
Or this:
return view('admin.userposts.archive', ['userposts' => $userposts]);

Change this:
return view('admin.userposts.show')->withUsp($userpost);
to
return view('admin.userposts.show', array('userpost' => $userpost));
and try again. You can get $userpost on blade view like:
{{ $userpost }}
If it is an array, use foreach() to get all of its elements.

Related

Why does Livewire run a new query on each render and why are relationships lost

Scenario
What i try to do
I am creating a multicolumn user index page, where the right column shows details from the user selected in the left column.
When selected, the user is not pulled out of the collection but freshly out of the database, so the data is up to date.
I defer the loading of the user list using the described method in the livewire documentation.
The user has a 'roles' relationship, which is displayed in the list column.
What I'd expect
I would expect that once the $this→users is set as a collection of the users and a user is selected, only the query will fire for getting the data for this user.
What actually happens
When a user is selected, a query for getting all users from the database is run (again), and because of the fact that the roles from the user are displayed in the list view, for each user, a new query is executed.
After that, a query for getting the selected user is executed. Afterwards another query for getting the roles of the user is fired to.
So my questions
Why does Livewire lose the relations that were eager loaded in the first declaration of public $users?
Why is it that Livewire reruns the query for getting all users, while the public $users is already defined as a collection of users?
Files:
UserListDetail.php
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
class UsersListDetail extends Component {
public string $search = '';
public $users;
public $selectedUser;
public int $timesRun = 0;
public bool $readyToLoadUserList = false;
protected $queryString = [
'search' => [ 'except' => '' ],
];
// Defer loading users
public function readyToLoadUserList()
{
// Get all users with roles relationship
$this->users = User::with('roles')->get();
$this->readyToLoadUserList = true;
}
public function selectUser(int $userId)
{
$this->selectedUser = User::with('roles')->find($userId);
}
public function render()
{
return view('livewire.users-list-detail', [
'selectedUser' => $this->selectedUser,
]
);
}
}
simplified version of user-list-detail.blade.php
<div>
<div wire:init="readyToLoadUserList">
#if($readyToLoadUserList)
<ul>
#foreach($users as $user)
<li wire:click="selectUser({{ $user->id }})">
{{ $user→name_first }} {{ $user→name_last }},
#foreach($user→roles as $role)
{{ $role→label }},
#endforeach
</li>
#endforeach
</ul>
#endif
</div>
<div>
#isset($selectedUser)
{{ $name_first
#endisset
</div>
</div>
When selectUser() method is triggered, the livewire will re-render the blade and since wire:init="readyToLoadUserList" is there, it will load every user (again).
Replce readyToLoadUserList() with mount() and simply keep wire:init="" empty.
Also, condition with #if($users->count() > 0)

Laravel 5.6: What's the simplest way to set a variable using blade (without echoing it)?

So, i wish to set a variable which i will later append to the beginning of a resource's route, i'm currently using the following code:
{!!
$baseDestinationImage=asset("img/uploads/destinations/");
!!}
<img src="{!! $baseDestinationImage.'/'.$destination->Dimage !!}" alt="{{$destination->Dname}}">
The above works fine, the only issue here is that the variable $baseDestinationImage also gets echoed, what's the simplest way to set a variable without it being displayed in Laravel 5.6?
use in controller then..
public class YourController{
...
public function index()
{
...
$baseDestinationImage=asset("img/uploads/destinations/");
return view('your.blade.view', compact('baseDestinationImage'));
}
}
in Blade
<img src="{{ $baseDestinationImage }}" />
You shouldn't set variables in your Blade templates. Still, if you still want to do it, you can embed PHP code using the #php directive:
#php
$baseDestinationImage=asset("img/uploads/destinations/");
#endphp
You can do it using the eloquent Accessors and mutators
which allow you to format Eloquent attribute values when you retrieve or set them on model instances.
So your model should be like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class YourModel extends Model
{
public function getPhotoAttribute($photo)
{
return $photo ? asset('your/path/' . $photo) : '';
}
}
And on your blade you can use it like this:
{{ $object->photo }}

Issue querying laravel eloquent relationship

This is with reference to this question :
Laravel Eloquent One to Many relationship
I tried the suggested way, but couldn't resolve. Please help. Below is the changes i have done :
Earlier :
//Route for Restaurants Page
Route::get('/home/restaurants',function(){
$restaurants = DB::table('restaurants')->simplepaginate(3);
return view('restaurants',['restaurants_data'=>$restaurants]);
});
Changed as per suggestion :
Route::get('/home/restaurants',function(){
// $restaurants = DB::table('restaurants')->simplepaginate(3);
$restaurants = \App\Restaurant::simplePaginate(3);
return view('restaurants',['restaurants_data'=>$restaurants]);
});
In Restaurant model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Restaurant extends Model
{
public function offer(){
return $this->hasMany('Offer');
}
}
In view, now I am trying to access it by dumping the values.
<?php
var_dump($restaurants_data->offer);
?>
Error :
After doing dd()
Firstly, I would suggest changing your Offer Relationship to:
public function offers()
{
return $this->hasMany(Offer::class, 'restaurant_ID', 'id');
}
The above assumes that the Offer class and Restaurant class are in the same namespace. If they're not please add the correct namespace or import the Offer model in to the class.
Secondly, because you're paginating the results you will end up with a collection of Restaurant models (even if there is only one), so you will need to loop through them to get access to the offers for each model. I would also suggest eager loading the results e.g.
Route:
Route::get('/home/restaurants', function () {
$restaurants = \App\Restaurant::with('offers')->simplePaginate(3);
return view('restaurants', compact('restaurants'));
});
in your view:
#foreach($restaurants as $restaurant)
#foreach($restaurant->offers as $offer)
{!! dump($offer) !!}
#endforeach
#endforeach
{{ $restaurants->links() }}
Can you replace
$restaurants = \App\Restaurant::paginate(3); and amend the blade code to say
<?php
foreach($restraunts_data as $resturant) {
if(count($restaurant->offer) {
print_r($restaurant->offer);
}
}
?>
You are using the models incorrectly. You run no queries and you attempt to run a static method on the Restaurant class without selecting any restaurants. As far as I know is this not supported by Eloquent. If you look at the error message it complains that there are no property $offer.
Try to run some query, and the select the related Offer. This should work as expected.
For example:
$offers = \App\Restaurant::find(1)->offer;
This will return the many Offer relations for the Restaurant with ID 1.

Why doesn't laravel recognize my model?

I get this error that says, "No query results for the model [App\dummy]." I believe the problem is in the controller. When you submit the form it is supposed to trigger the function in the comment controller. This controller is new so, I believe the error is in here. That is when it stopped working. Here is the commentController file:
<?php
namespace App\Http\Controllers;
use App\Dummy;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; //this one is for sql builders
use App\Comments;
use Illuminate\Http\RedirectResponse;
use DateTime; //to create a new date object you need to include this namespace
class commentController extends Controller
{
public function store(Dummy $post){
$date = new DateTime();
$timestamp = $date->getTimestamp();
$id = $post->id;
$post->addComment(request('body'));
return view('post', compact('post', 'timestamp', 'id'));
}
}
I tried making App\Dummy lowercase so it was App\dummy but still it didn't work. It still gives me the error.
Here is my dummy model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class dummy extends Model
{
protected $guarded = [];
public function comments(){
return $this->hasMany(Comments::class, 'post_id');
}
public function addComment($body){
$this->comments()->create(compact('body'));
}
}
Your error is that your class is called dummy buy you are using it as Dummy, so rename it both (file and class) to Dummy.
This class dummy extends Model to this class Dummy extends Model.
Remember that your file should be called Dummy.php too, not dummy.php
Change your model class name to Dummy and file name to Dummy.php.
Your main problem here is the route model binding. When you're trying to add a comment, the $post object is not getting resolved based on your route. You have bad a route setup or trying to add comment to a non existent post.
Basically the error message No query results for the model happens because of this code that the route model binding does for you.
$post = Dummy::findOrFail($id);
Try changing this
Route::post('post/{dummy}/comments', 'commentController#store');
public function store(Dummy $dummy)
The problem was in the form. The action attribute in the form was something like this:
<form class="col s12" action={{ url('/post/$id/comments') }} method="post">
I thought that would get the id because I compacted the id into the variable $id. But then I checked the url and noticed not a number but the actual word $id. So, here is the solution:
<form class="col s12" action={{ url('/post/' . $post->id . '/comments') }} method="post">
Just to let you guys know that when it said, "No query results for the model [App\dummy]." It meant that when I used this method from the dummy model which had this line of code:
public function comments(){
return $this->hasMany(Comments::class, 'post_id');
}
It couldn't find the primary key from the dummies table. Therefore couldn't connect with the foreign key which is the post_id from the comments table. So, it wasn't able to submit the new comment to the table for that unique blog post. This is the last part that submits the comment to the table:
public function addComment($body, $name){
$this->comments()->create(compact('body', 'name'));
}
by the way comments() is the method I created that i just showed before.
Conclusion
It pretty much stopped working in the web.php file(routing file) because it wasn't getting an id. Due to the mistake I made in the action attribute in the form that i explained before.

Laravel 4 pass input from blade to controller

I have a project in laravel 4.
In my blade file i have:
<div class="col-sm-12">
Show more
</div>
I want to pass my limit and gap to the controller. In the controller i use Input::get('limit'); but i get back a null.
Even Input::all() returns null.
Any tips?
Thank you!
HTML(VIEW) CODE
Code for a tag
click ok
Form code
<form method="POST" action="{{url('submit/Parameters..')}}" method="post">
{{ csrf_field() }}
...
</form>
ROUTE CODE
route code with action
Route::get('user/{id}', function ($id) {
echo "id is : ".$id ;
});
route code for controller
Route::get('user/{id}', 'UserController#show');
CONTROLLERS CODE
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
public function index($id)
{
echo $id;
}
}
for more information you see following like
https://laravel.com/docs/5.4/controllers
and https://laravel.com/docs/5.4/routing
Try this:
<div class="col-sm-12">
Show more
And ensure that your route and controller passed params.
Route must be configured with dataLimit and dataGap params, and controller method must accept it.
Input is for forms. If you want to use anchors, you will have to pass parameters to url like this
<a href="/url?limit=12&gap=12" >Show more </a>
This makes them optional to your controller. You just need to get them with request().
$limit = request('limit');
$gap = request('gap');

Categories