$this->belongsToMany(Categories::class, 'category_post','category_id','post_id');
Во вторым аргументе указывается название таблицы связи. Или вы неправильно её написали в методе, или в вопросе (category_post или post_categories?). А последние 2 аргумента можно вообще опустить - ларавел сам додумается в данном случае (то есть просто возьмёт название класса + '_id').
public function category() { ... }
Стоит назвать categories, а то потом сами запутаетесь. Связь же многие-ко-многим, а название метода в ед. числе.
В остальном связи правильно прописаны.
А вот в контроллере проблема - метод findOrNew нужен не для того, чтобы в зависимости от наличия аргумента отдавать новую или существующую запись. Его задача в том, чтобы попытаться найти запись с переданным ID, и если найти таковую не удалось - вернуть свежий экземпляр. То есть совершенно логично, что он ругается на отсутствующий аргумент, так как он ему необходим для работы :)
Ещё момент - вы пытаетесь вызвать sync, хотя на момент вызова пост ещё может быть не создан. По причине того, что у свежесозданной записи ещё нет идентификатора, sync, очевидно, тоже упадёт с ошибкой, то есть предварительно нужно вызвать $post->save(). А ещё лучше saveOrFail(), который сразу кинет исключение, если не удалось сохранить запись.
Ну и
Александр тут уже написал, что хорошая мысль разделить на 2 метода создание и редактирование элемента. По остальным вопросам, как, опять же, уже упоминалось, нужно читать документацию. У ларавел она очень понятная и хорошо структурированная (хотя и многого не охватывает, но для начала вполне достаточно информации).