Trying to retrieve posts from table by category slug - laravel

Hello i am trying to loop posts that are associated to each category by the slug. It works when i use the ids but when i change my controller function to search by slug it retrieves the slug but does not load the foreach loop.
I have tried so many methods and i don't know where i am going wrong please help.
Category Model :
protected $table = 'post_categories';
public function posts()
{
return $this->hasMany('App\Post', 'id', 'name', 'catslug');
}
Post Model
public function user()
{
return $this->belongsTo('App\User');
}
public function postCategories()
{
return $this->belongsTo('App\PostCategory');
}
Controller
public function getPostCategory($catslug) {
$postCategories = PostCategory::with('posts')
->orderBy('name', 'asc')
->where('catslug', '=', $catslug)
->first();
return view ('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
Route
Route::get('articles/category/{catslug}', [
'uses' => 'ArticlesController#getPostCategory' ,
'as' => 'PostCategory'
] );
View
#foreach($postCategories->posts as $post)
<h4>{{ substr($post->title, 0, 50) }}</h4>
<p>{{ substr($post->body, 0, 90) }}</p>
#endforeach
When i use id there is no problem i cant see what i am doing wrong any feedback will be truly appreciated
Thanks
Ash

Save category id in posts table insted of category name or slug.
Change in post category model:
public function posts()
{
return $this->hasMany('App\Post', 'category_id');
}
Your controller method:
public function getPostCategory($catslug)
{
$postCategories = PostCategory::with('posts')->where('catslug', $catslug)->first();
return view('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
If you want to order posts by name then add orderBy() in relationship :
public function posts()
{
return $this->hasMany('App\Post', 'category_id')->orderBy('name', 'asc');
}

Related

Create new Post with default Category belongsToMany

I have a Post/Category manyToMany relations and would like to be able to attach a default category named "Uncategorised" to each new post that is created. How can I do that? A BelongsToMany method only works on the Details page, not on Create page.
BelongsToMany::make(__('Categories'), 'categories', Category::class),
You can also set default value to your database field so that you can omit passing category and will be taken default to Uncategorised like if you are using MySQL you can do it this way by creating migration
$table->text('category')->default(0);
Because the BelongsToMany not show on mode create in Post Nova model. So we have to make our custom Select, by add this code to your fields:
public function fields(Request $request)
{
if($request->editMode=="create"){
$categories = \App\Category::get(['id','name']);
$options = [];
foreach($categories as $value){
$options[$value->id] = $value->name;
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
Select::make('Categories', 'category_id')
->options($options)
->displayUsingLabels()
->withMeta(['value' => 1]) // 1 = id of Uncategorised in categories table
];
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
BelongsToMany::make('Categories','categories')->display('name'),
];
}
Don’t forget relationship function in both, Post and Category model:
class Post extends Model
{
public function categories(){
return $this->belongsToMany(Category::class, 'category_post', 'post_id', 'category_id');
}
}
And:
class Category extends Model
{
public function posts(){
return $this->belongsToMany(Post::class,'category_post', 'category_id', 'post_id');
}
}
Then, custom the function process the data on mode Create of Post resource page, it’s at nova\src\Http\Controllers\ResourceStoreController.php, change function handle to this:
public function handle(CreateResourceRequest $request)
{
$resource = $request->resource();
$resource::authorizeToCreate($request);
$resource::validateForCreation($request);
$model = DB::transaction(function () use ($request, $resource) {
[$model, $callbacks] = $resource::fill(
$request, $resource::newModel()
);
if ($request->viaRelationship()) {
$request->findParentModelOrFail()
->{$request->viaRelationship}()
->save($model);
} else {
$model->save();
// your code to save to pivot category_post here
if(isset($request->category_id)&&($resource=='App\Nova\Post')){
$category_id = $request->category_id;
$post_id = $model->id;
\App\Post::find($post_id)->categories()->attach($category_id);
}
}
ActionEvent::forResourceCreate($request->user(), $model)->save();
collect($callbacks)->each->__invoke();
return $model;
});
return response()->json([
'id' => $model->getKey(),
'resource' => $model->attributesToArray(),
'redirect' => $resource::redirectAfterCreate($request, $request->newResourceWith($model)),
], 201);
}
}
All runs well on my computer. A fun question with me! Hope best to you, and ask me if you need!
What I ended up doing was saving the data on Post Model in boot().
public static function boot()
{
parent::boot();
static::created(function (Post $post) {
$post->categories()->attach([1]);
});
}

Trying to display eloquent data base from ID's

Hi I am trying to create a record base from ID of an order transaction.
I have here the ORDERS, CAMPANIES and CURRENCIES models.
Now I want the ORDER to get the ID from a URL Parameter, and then the companies should grab the company_id from Orders same with currency, I want to grab the currency_id from orders.
Here's what I came up so far:
public function create($order_id)
{
$order = Orders::find($order_id)->where('id', '=', $order_id)->get();
$company = Companies::where('id', '=', $order['company_id'])->get();
$currency = Currencies::where('id', '=', $order['company_id'])->get();
$banks = Banks::all('name','acronym','id')->get();
return view('orderPayments.create', compact('order'))
->with('company', $company)
->with('currency', $currency)
->with('banks', $banks);
}
currencies model
public function orderPayments()
{
return $this->hasMany('App\Orderpayments', 'id','currency_id');
}
Companies Model
public function orderPayments()
{
return $this->hasMany('App\Orderpayments', 'id','company_id');
}
Order Payments Model
public function company()
{
return $this->hasOne('App\Companies', 'id','company_id');
}
public function currency()
{
return $this->hasOne('App\Currencies', 'id', 'currency_id');
}
public function bank()
{
return $this->hasOne('App\Bank', 'id', 'currency_id');
}
How can I achieve it? thank you so much in advance!
UPDATE
I just applied #sandy's answer. I checked if the $order has a content so I echod the $order by doing this, {{ $order }} The return value is ok.
but when I calling the other attributes like $order->grandtotal, or $order->companies->comp_name the error is
If your relationship between your models is a One To Many relationship you should use belongsTo in your relations like this:
OrderPayment Model
public function company()
{
return $this->belongsTo('App\Companies','company_id');
}
public function currency()
{
return $this->belongsTo('App\Currencies','currency_id');
}
public function bank()
{
return $this->belongsTo('App\Bank', 'currency_id');
}
Also, the second parameter on the function should be your foreign key.
Answering your question:
If you want to access the relations of a given Order you could do this:
$order = Order::find($order_id);
$order->company; // this will return the company
$order->currency; // this will return the currency
If you want to display in your view:
{{$order->company->anyCompanyAttribute}}
Note:
You should name your models in SINGULAR like Currency, Company. Not in plural.
try like this
$order = Orders::with(['company','currency'])->where('id', '=', $order_id)->get();

Laravel, Simple and Correct way for relationship

I want to list related categories of related brand with this logic.
Products Table
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug');
$table->integer('brand_id')->unsigned();
$table->foreign('brand_id')->references('id')->on('brands')->onDelete('cascade');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
}
web.php
Route::get('{Brand}/{Category}/{Product}', 'ProductsController#show');
Route::get('{Brand}/{Category}', 'ProductsController#index');
1st route, for example; Samsung/phones should list all of Samsung's phones with following code part. Is there another way to make these codes simple? And this query returns null. I checked that query is getting correct columns but returns null.
use App\Product;
use App\Brand;
use App\Category;
class ProductsController extends Controller
{
public function index(Request $request)
{
$category = $request->Category;
$cat_id = Category::select('id')
->where('slug',$category)
->get();
$brand = $request->Brand;
$br_id = Brand::select('id')
->where('slug', $brand)
->get();
$products = Product::select('id','name','slug')
->where('category_id', $cat_id)
->where('brand_id', $br_id)
->get();
return view('products.index', compact('products'));
}
}
Product.php
class Product extends Model
{
public function brands()
{
return $this->belongsTo('App\Brand');
}
public function categories()
{
return $this->belongsTo('App\Category');
}
}
Category.php
class Category extends Model
{
public function brands()
{
return $this->belongsToMany('App\Brand');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
First of all read the docs about laravel relationships:
https://laravel.com/docs/5.7/eloquent-relationships
The reason your current code is not working is because in your route you ask for parameters:
Route::get('{Brand}/{Category}', 'ProductsController#index');
But in your index() method on your ProductsController you have not included these parameters.
public function index(Request $request, Brand $brand, Category $category)
The second problem in your code is that you are not using your relationships at all. Your current controller just makes a new eloquent query.
Example of getting all the products for the given category using the method you have defined on your Category Model:
public function index(Request $request, Brand $brand, Category $category)
{
$products = $category->products;
return view('products.index', compact('products'));
}
Example of extending this with the given brand:
public function index(Request $request, Brand $brand, Category $category)
{
$products = $category->products()->where('brand_id', $brand->id)->get();
return view('products.index', compact('products'));
}
UPDATE
As noted in the comments, the URL parameters are slugs and not ids, so auto route-model-binding will not work. An updated solution with slugs:
public function index(Request $request, $brand, $category)
{
$categoryModel = Category::where('slug', $category)->firstOrFail();
$brandModel = Brand::where('slug', $brand)->firstOrFail();
$products = $categoryModel->products()->where('brand_id', $brandModel->id)->get();
return view('products.index', compact('products'));
}
Further improving your code would be to add a scope or helper method so you can do something like Brand::FindBySlug($slug);
I think you are using get method at last that will give you array not only one value. Could you please try with below code. This might help
use App\Product;
use App\Brand;
use App\Category;
class ProductsController extends Controller
{
public function index(Request $request)
{
$category = $request->Category;
$cat_id = Category::where('slug',$category)->value('id);
$brand = $request->Brand;
$br_id = Brand::where('slug', $brand)->value('id);
$products = Product::select('id','name','slug')
->where('category_id', $cat_id)
->where('brand_id', $br_id)
->get();
return view('products.index', compact('products'));
}
}
You should try this:
public function index($brand, $category,Request $request)
{
$products = Product::select('id','name','slug')
->where('category_id', $category)
->where('brand_id', $brand)
->get();
return view('products.index', compact('products'));
}

One-to-many and one-to-many relationship 1 laravel

i did this(sorry my english it's bad bad....)
controller:
public function index()
{
$lessons = course::find(1)->lesson;
return view('home',compact('lessons'));
}
model lesson
public function course() {
return $this->belongsTo(Course::class);
}
model courses
public function lesson() {
return $this->hasMany(Lesson::class);
}
blade
#foreach ($lessons as $lesson )
<h4>{{$lesson->title}}</h4>
#endforeach
in browser nothing appears
why?:(
First rename your lesson method with plural lessons.
// Course model
public function lessons() // plural
{
return $this->hasMany(Lesson::class);
}
Now get the lesson's collection.
public function index()
{
$lessons = Course::find(1)->lessons;
return view('home', compact('lessons'));
}
#foreach ($lessons as $lesson )
<h4>{{$lesson->course->title}}</h4>
#endforeach
Have you tried it like this:
return view('greeting')->with('lessons', $lessons);
Now you can call '$lessons' in your view. Take a look at this link
https://laravel.com/docs/5.6/views
Can you try to use return $lessons; and show me what it says?

get data from multiple relations in laravel eloquent

I have the following tables pharmacies,categories,medicines and I am using laravel
the relations are like this
pharmacy have many medicines and the medicine belongs to one category
the medicines table have pharmacy_id and category_id columns + other columns
I want to show a pharmacy by id and it should return an object of pharmacy with categories, each category have object of medicines in this pharmacy. If there is no medicine in any category, then it should not be returned.
I think its a model relations issue
any idea could be useful
the category model
class Category extends Model
{
protected $table = 'categories';
public function pharmacies()
{
return $this->belongsToMany(Pharmacy::class, 'pharmacy_category', 'category_id', 'id');
}
public function medicines()
{
return $this->hasMany(Medicine::class);
}
}
the pharmacy model
class Pharmacy extends Model
{
use SoftDeletes;
protected $table = 'pharmacies';
protected $appends = ['favourite'];
public function categories()
{
return $this->belongsToMany(Category::class,'pharmacy_category','pharmacy_id','id');
}
public function getFavouriteAttribute()
{
if (!Auth::check()) {
return 0;
}
return (FavouritePharmacy::where('user_id', Auth::user()->id)->where('pharmacy_id', $this->id)->count() == 1) ? 1 : 0;
}
}
the medicine model
class Medicine extends Model
{
protected $appends = ['favourite'];
public function orders()
{
return $this->belongsToMany(Order::class);
}
public function getFavouriteAttribute()
{
if (!Auth::check()) {
return 0;
}
return (FavouriteMedicine::where('user_id', Auth::user()->id)->where('medicine_id', $this->id)->count() == 1) ? 1 : 0;
}
}
If you want to display pharmacy info, categories with medicines, with these relationships I'd do this:
$pharmacy = Pharmacy::find($id);
$categoriesWithMedicines = Category::whereHas('medicines', function($q) use($id) {
$q->where('pharmacy_id', $id);
})
->with(['medicines' => function($q) use($id) {
$q->where('pharmacy_id', $id);
}])
->get();
Then in a view, you'll have a pharmacy object and a list of categories with medicines which belong to the pharmacy:
#foreach ($categoriesWithMedicines as $category)
{{ $category->name }}
#foreach ($category->medicines as $medicine)
{{ $medicine->name }}
#endforeach
#endforeach

Resources