Followup of @chris
Incase you, like me, have gotten the task to save a shop which has migrated their store completely wrong here's a functioning script which takes a categoryId and attempt to recreate the category url_rewrite from the category request path to magento's internal mapping of category id.
You can use this in combination with Magento\Catalog\Model\ResourceModel\Category\Collection
to walk through every category in your store
This is a function taken from a console command i made to walk the entire store ( https://devdocs.magento.com/guides/v2.4/extension-dev-guide/cli-cmds/cli-howto.html )
$this->output
is just the OutputInterface
$this->storeId
is the current store you which to use.
public function handleRedirect($categoryId)
{
try {
// use Magento\Catalog\Api\CategoryRepositoryInterface;
/** @var Category $category */
$category = $this->categoryRepository->get($categoryId);
// use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator;
$requestPath = $this->categoryUrlPathGenerator->getUrlPath($category);
$this->output->writeln('<info>Processing: ' . $category->getName() . '</info>');
$this->output->writeln('<comment>' . $requestPath . '</comment>');
// use Magento\UrlRewrite\Model\UrlRewriteFactory;
/** @var \Magento\UrlRewrite\Model\UrlRewrite $rewrite */
$rewrite = $this->urlRewriteFactory->create();
$rewrite->setStoreId($this->storeId);
$rewrite->setRequestPath($requestPath);
$rewrite->setEntityType('category');
$rewrite->setEntityId($category->getId());
$rewrite->setTargetPath('catalog/category/view/id/' . $category->getId());
$rewrite->setRedirectType(0);
$rewrite->setDescription('Category Regeneration');
// use Magento\UrlRewrite\Model\ResourceModel\UrlRewrite
$this->urlRewriteResource->save($rewrite);
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
$this->output->writeln('<error>' . $e->getMessage() . '</error>');
}
}
This method is non-destructive as it does not duplicate existing urls and only helps fill out the void that some poor soul has created when migrating categories incorrectly :(
Before attempting it check you link, if it's somewhere along the lines of catalog/category/view/id/<id>
you can manually create a url_rewrite in the backend ( select category and pick your category ) you can then create it and test it before running the script