Preston Garvey
Preston Garvey

Reputation: 1421

Limit user posts in a single record

I have this scenario in my app where I have to limit post that can be written by users. Example, I have a table named Edition to store edition data and Article table to store article data. Edition table and Article table has one-to-many relationship (one Edition has many Articles). Now, I have a Users table to store users data and this table has one-to-many relationship with Article table (one User has many Articles). Cut to the case, I want to make a rule where a user CAN ONLY HAVE ONE ARTICLE IN EACH EDITION. Let's just say there is an edition record called "Japanese Food", in this edition record users may post their article but ONLY ONE ARTICLE. Users that already post their article in this "Japanese Food" edition will only be able to post a new article in another edition record where they haven't post any article yet. Now my question is, how to make such rule in Laravel ? especially Laravel 5.3. I have created my migrations and the models, below are the codes (in case it's necessary to help you answer my question).

Edition table :

public function up() {
        Schema::create('edition', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('volume');
            $table->text('cover')->nullable();
            $table->integer('number');
            $table->timestamps();
        });
        Schema::table('article', function(Blueprint $table) {
            $table->foreign('id_edition')->references('id')->on('edition')->onDelete('cascade')->onUpdate('cascade');
        });
    }
    public function down() {
        Schema::table('article', function(Blueprint $table) {
            $table->dropForeign('article_id_edition_foreign');
        });

        Schema::drop('edition');
    }

Article table :

public function up() {
        Schema::create('article', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title', 255);
            $table->text('content');
            $table->text('file');
            $table->integer('id_edition')->unsigned();
            $table->integer('user_id')->unsigned();
            $table->string('articleslug');
            $table->enum('publish', ['yes', 'no']);
            $table->timestamps();
        });
        Schema::table('article', function(Blueprint $table) {
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
        });
    }
    public function down() {
        Schema::table('article', function(Blueprint $table) {
            $table->dropForeign('article_user_id_foreign');
        });
        Schema::drop('article');
    }

Users table :

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('username')->unique();
            $table->string('userslug');
            $table->string('nameslug');
            $table->string('email')->unique();
            $table->string('phone')->nullable();
            $table->string('address')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->enum('level', ['admin', 'author']);
            $table->timestamps();
        });
    }
    public function down()
    {
        Schema::drop('users');
    }

My controller :

public function storeArticle(ArticleRequest $request) {
        $input = $request->all();
        $input['user_id'] = Auth::id();
        $idi = $request->id;
        $id_edition = Edition::findOrfail($idi);
        $user = Auth::user();
        if ($this->userPolicy->userHasArticle($user, $id_edition)) {
            //Input PDF
            if ($request->hasFile('file')) {
                $input['file'] = $this->uploadPDF($request);
            }
            //Insert article datas
            $article = Edition::findOrFail($idi)->article()->create($input);
            $article->user()->attach($request->input('penulis'));
            return redirect()->route('edition', ['id' => $idi]);
        } else {
            return 'Error! You already posted your article in this edition, please pick another edition instead';
        }
    }

Thank you for the helps! :)

Upvotes: 0

Views: 1066

Answers (2)

Preston Garvey
Preston Garvey

Reputation: 1421

It truly worked now, so I did something like this in my controller without using policy (gonna write it down here in case somebody need it)

public function storearticle(ArticleRequest $request) {
        $input = $request->all();
        $input['user_id'] = Auth::id();
        $idi = $request->id;
        $articlerules = Article::where('id_edition', $idi)
                ->where('user_id', $request->user()->id)
                ->exists();
        if ($articlerules == true) {
            return 'You already have an article in this edition, please pick another edition instead.';
        } else {
            if ($request->hasFile('file')) {
                $input['file'] = $this->uploadPDF($request);
            }

            //Insert article datas
            $article = Edition::findOrFail($idi)->article()->create($input);
            $article->user()->attach($request->input('authors'));

            return redirect()->route('edition', ['id' => $idi]);
        }
    }

Upvotes: 0

PassionInfinite
PassionInfinite

Reputation: 638

Feasible Solution is that you just have to make UserPolicy and a method in it to check whether the user has already created the article or not. Like this

UserPolicy will be having method like this:

    public function userHasArticle(User $user, $edition_id){
        //Made Article Model
        $article = Article::query()->where('user_id', $user->id)->where('id_edition', $edition_id)->get();
        if(is_null($article)){
            return true;
        }else{
            return false;
        }
    }

While in controller logic should be like this:

protected $usersPolicy;

public function __construct(UsersPolicy $usersPolicy)
{
    $this->usersPolicy = $usersPolicy;
}


public function post(Request $request){
    //First check like this
    //Get the id_edition and before processing anything first check this condition

    if($this->usersPolicy->userHasArticle(auth()->user(), $id_edition)){

    }else{
        //Return Error!
    }

}

Make Sure UserPolicy has use HandlesAuthorization trait Hope! You get my Point. Any queries comment below! :)

Upvotes: 2

Related Questions