Je crée des URL conviviales dans mon application, mais cela ne fonctionne pas, l'application me pose des problèmes liés à "-". Cela me donne une erreur de:

ErrorException in PostController.php line 60:
Trying to get property of non-object

Mon URL idéale est:

http://domain.com/CATEGORY-title-of-post-ID

Mon itinéraire est:

Route::get('{category}-{title}-{id}', 'PostController@show');

Fonction d'affichage de PostController:

public function show($category,$title,$id)
    {
        $post = Post::find($id);
        $user = Auth::user();

        $comments = Comment::where('post_id',$id)
                            ->where('approved',1)
                            ->get();




        return view('posts.show',compact('post','comments','user'));
    }

Vue de la lame:

 <?php
     $title_seo = str_slug($feature->title, '-');
 ?>
 <a href="{{url($feature->categories[0]->internal_name."-".$title_seo."-".$feature->id)}}" rel="bookmark">
...</a>
0
Pedro 16 janv. 2017 à 14:55

2 réponses

Meilleure réponse

Il existe une bibliothèque appelée Eloquent-Sluggable qui créera un slug unique pour chaque message et encodera correctement l'URL il.

Pour installer (extrait de la documentation):

composer require cviebrock/eloquent-sluggable:^4.1

Ensuite, mettez à jour config/app.php en ajoutant une entrée pour le fournisseur de services.

'providers' => [
    // ...
    Cviebrock\EloquentSluggable\ServiceProvider::class,
];

Enfin, à partir de la ligne de commande à nouveau, publiez le fichier de configuration par défaut:

php artisan vendor:publish --provider="Cviebrock\EloquentSluggable\ServiceProvider"

Pour l'utiliser, ajoutez le trait Sluggable à votre modèle:

use Cviebrock\EloquentSluggable\Sluggable;

class Post extends Model
{
    use Sluggable;

    /**
 * Return the sluggable configuration array for this model.
 *
 * @return array
 */
public function sluggable()
{
    return [
        'slug' => [
            'source' => 'title'
            ]
        ];
    }

}

Lorsque vous enregistrez une instance de votre modèle, la bibliothèque crée automatiquement un slug et l'enregistre dans la colonne slug nouvellement créée de la table de votre modèle. Donc, pour accéder au slug que vous utiliseriez $model->slug

Pour atteindre le slug souhaité, plutôt que de le créer à partir de title défini par défaut. Vous pouvez passer l'attribut source de la méthode sluggable à un tableau de noms de champs, en utilisant une notation par points pour accéder aux attributs d'un modèle associé, comme ceci:

public function sluggable()
{
    return [
        'slug' => [
            'source' => ['category.name','title','id']
            ]
        ];
    }

}
2
TimothyBuktu 16 janv. 2017 à 12:09

Pourquoi générez-vous votre "URL conviviale" manuellement?

Vous disposez d'une fonction d'assistance route qui crée pour vous une URL basée sur les paramètres donnés.

Route::get('{category}-{title}-{id}', [
    'as => 'post.show', 
    'uses' => 'PostController@show'
]);

echo route('post.show', ['testing', 'title', 'id']); // http://domain.dev/testing-title-id

Ce n'est de toute façon pas la meilleure approche pour implémenter des URL optimisées pour le référencement.


Dans votre contrôleur, vous utilisez TOUJOURS votre identifiant pour trouver un message, ce qui signifie que la catégorie et le titre sont totalement inutiles pour déterminer quelle ressource doit être servie à l'utilisateur.

Vous pouvez vous faciliter la vie en faisant quelque chose comme:

Route::get('{id}-{slug}', [
    'as => 'post.show', 
    'uses' => 'PostController@show'
]);

echo route('post.show', ['id', 'slug']); // http://domain.dev/id-slug

Dans votre modèle, vous créez une fonction d'assistance qui génère le slug pour votre message:

class Post
{
    [...]

    public function slug()
    {
        return str_slug("{$this->category}-{$this->title}");
    }
}

Ensuite, dans votre contrôleur, vous devez vérifier que le slug utilisé pour accéder à l'article est correct ou non, car vous ne voulez pas que Google indexe la publication avec de mauvais slugs. Vous forcez essentiellement une URL à être d'une certaine manière et vous ne perdez pas de points d'index.

class PostController 
{
    [...]

    public function show($id, $slug)
    {
        $post = Post::findOrFail($id);
        $user = Auth::user();

        if ($post->slug() !== $slug) {
            return redirect()->route('posts.show', ['id' => 1, 'slug' => $post->slug()]);
        }

        $comments = Comment::where('post_id', $id)->where('approved', 1)->get();
        return view('posts.show', compact('post', 'comments', 'user'));
    }
}
2
GiamPy 16 janv. 2017 à 12:11