Tyeio
Tyeio

Reputation: 41

Laravel Get Slug from Database

I'm attempting to build a blog like application with the latest version of laravel. I'm trying to figure out how to pull a slug from the database for each article and then route it to all work correctly.

I've got it kind of working but the content wont display on the article if you use the slug to view it.

localhost/articles/1 - works fine, content shows on the page (title etc)

localhost/articles/installing-example - this works but the content errors

This happens when you try to navigate to the page using the slug from the database: Trying to get property 'title' of non-object (View: C:\xampp\htdocs\blogtest\resources\views\articles\show.blade.php)

Error with this line: <h1><?php echo e($articles->title); ?></h1>

app/http/controllers/ArticlesController:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Article;

class ArticlesController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $articles =  Article::all();
        return view('articles.index')->with('articles', $articles);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $articles = Article::find($id);
        return view('articles.show')->with('articles', $articles);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }


}

app/Article.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    protected $table = 'articles';
    public $primaryKey = 'id';
    public $timestamps = true;
}

routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::resource('articles', 'ArticlesController');

resources\views\articles\show.blade.php

@extends('layouts.master')

@section('content')

    <h1>{{$articles->title}}</h1>

@endsection

database https://i.sstatic.net/WaNy0.png

Any help and suggestions will be appreciated thanks.

Upvotes: 3

Views: 8195

Answers (4)

Script47
Script47

Reputation: 14550

Trying to get property 'title' of non-object (View: C:\xampp\htdocs\blogtest\resources\views\articles\show.blade.php)

Implies that that the $articles is not an object, if you dump it, it should be outputting null - quite rightly so.

The find function is to be used to find a row using your primary key and your primary key is not your slug column, therefore it cannot find a record.

You need to setup a route to accept a {slug} and then based on the slug you need to make the following change:

$articles = Article::find($id);

To,

$articles = Article::where('slug', $slug)->first();

and ensure that $slug is the actual slug and not the id column value.

Upvotes: 4

Karan Sadana
Karan Sadana

Reputation: 1373

This Is because you getting null data from database.

Reason is, you passing slug in the id field so

localhost/articles/installing-example

you passing id = installing-example, hence no id is found so no data you get.

so for this convert your slud into original form and search not with id, search with your slug field.

let suppose from the title you make slug. title is installing example so when you get slug, make it into original form then search with original like

$articles = Article::where('titile',$original)->first();

Upvotes: 0

bhavinjr
bhavinjr

Reputation: 1763

Try this

Without slug

Route

Route::resource('articles', 'ArticlesController');

/article/{id}

Controller

public function show($id)
{
    $articles = Article::first($id);
    return view('articles.show', compact('articles'));
}

Blade

@extends('layouts.master')

@section('content')
    @if(!is_null($articles))
        <h1>{{$articles->title}}</h1>
    @endif
@endsection

With Slug

Route

Route::get('/articles/{slug}', ['as'=>'articles.by.slug', 'uses'=> 'ArticlesController@showArticles']);
or
Route::get('/articles/{slug}', 'ArticlesController@showArticles')->name('articles.by.slug');

/article/{slug}

Controller

public function showArticles($slug)
{
    $articles = Article::where('slug', $slug)->first();
    return view('articles.show', compact('articles'));
}

Blade

@extends('layouts.master')

@section('content')
    @if(!is_null($articles)) //or @if($articles)
        <h1>{{$articles->title}}</h1>
    @endif
@endsection

Upvotes: 1

Mayank Dudakiya
Mayank Dudakiya

Reputation: 3869

You need to set route key in your model

// Article model
public function getRouteKeyName(){
    return 'slug';
}

Upvotes: 3

Related Questions