DoeJohn's avatar

Make articles with published_at attribute in future inaccessible

Hi,

My Article model has two attributes that define whether it will be visible or not:

  • published_at - this is datetime attribute and if it has a value that is in the future - article will not be visible.
  • published - boolean (actually 1 or 0) - if its value is 0 - article will not be visible.

In Article.php I have the following scope method:

    public function scopePublished($query)
    {
        $query->where('published_at', '<=', Carbon::now())->where('published', 1);
    }

So, in ArticleController.php I return only published() articles to a view:

    public function index()
    {
        $published_articles = $this->articles->latest('published_at')->published()->paginate(5);
        return view('articles.index', compact('published_articles'));
    }

For displaying one specific article, I have show($id) method:

    public function show($id)
    {
        $article = $this->articles->find($id);
        return view('articles.show', compact('article');
    }

As you can see, I am NOT using Route Model Binding. The problem is that I can still access some articles that have published_at in future or *published = 0*. For example, if one article with id = 5 has *published = 0*, it will not be visible on index page, but I can access it by opening http://localhost/articles/5.

In Laravel 5 Fundamentals course Jeffrey solved this problem with Route Model Binding:

public function boot(Router $router)
{
    parent::boot($router);
    $router->bind('articles', function($id) {
        return \App\Article::published()->findOrFail($id);
    });
}

but since I'm not using Route Model Binding, I tried this:

In model Article.php I created the following method:

    public function checkAccessible()
    {
        if ($this->published_at > Carbon::now() || $this->published == 0) {
            return redirect('articles');
        }
    }

And now, for example, in ArticleController@show I just call this method:

    public function show($id)
    {
        $article = $this->articles->find($id);
        $article->checkAccessible();
        return view('articles.show', compact('article');
    }

But, for some reason - it doesn't work. Anyway, I feel that this is a bad way, there must be a better way. How would you solve this problem?

0 likes
1 reply
Prullenbak's avatar
Level 26

maybe try:

public function show($id)
{
    $article = $this->articles->find($id);
    if ($article->published_at->isFuture()) {
        return redirect('articles');
    }
    return view('articles.show', compact('article');
}

(if your published_at is a carbon instance, of course...if not, just add it to the $dates array on your article model.

2 likes

Please or to participate in this conversation.