Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

connecteev's avatar

Changing primary key of a polymorphic 'comments' table from 'id' to a varchar, PHP runs out of memory

When I change the primary key of my polymorphic 'comments' table from 'id' to a varchar, PHP runs out of memory. How can I fix this?

This is my comments table schema. I would like every request (CRUD) to be based off of comment_hash instead of 'id'. Can this actually be accomplished?

CREATE TABLE `comments` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `comment_hash` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `body` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `commentable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `commentable_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `comment_user_hash_parentid_unique` (`user_id`,`comment_hash`,`commentable_id`),
  KEY `comment_hash_index` (`comment_hash`),
  CONSTRAINT `user_fk_369255` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2048 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

This is a snippet from my Comments.php model:

class Comment extends Model
{
    use SoftDeletes;

    public $table = 'comments';


    /**
     * Customize the primary key for comment model. Results in 'out of memory'
     */
    protected $primaryKey = 'comment_hash';

    /**
     * Get the owning commentable model.
     */
    public function commentable()
    {
        return $this->morphTo();
    }

    /**
     * Get all of the comments (single-level, not recursively)
     */
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }

    /**
     * Get all of the comments' comments recursively.
     */
    public function nestedComments()
    {
        // Get comments recursively, from https://laraveldaily.com/eloquent-recursive-hasmany-relationship-with-unlimited-subcategories/
        return $this->morphMany(Comment::class, 'commentable')->with('nestedComments');
    }

And this is my API / Controller code which times out (this works perfectly and returns nested comments if dont change the Comments primary key from id to comment_hash, as seen above)


$max_top_level_comments = 20;

$post =
    Post::with([
        'comments' => function ($query) use ($max_top_level_comments) {
            $query
                ->where([
                    ['is_removed', '=', '0'],
                    ['deleted_at', '=', NULL],
                ])
                ->select('id', 'comment_hash', 'body', 'user_id', 'commentable_id', 'commentable_type', 'created_at')
                ->with([
                    'nestedComments' => function ($query) {
                        $query
                            ->where([
                                ['is_removed', '=', '0'],
                                ['deleted_at', '=', NULL],
                            ])
                            ->select('id', 'comment_hash', 'body', 'user_id', 'commentable_id', 'commentable_type', 'created_at');
                    },
                ])
                ->take($max_top_level_comments)
                ->get();
        },

    ])
    ->find(1);


This is the error I see in the browser when I try to hit the API:

Error:

This page isn’t working
localhost is currently unable to handle this request.
HTTP ERROR 500

Error logs in terminal:

[Fri Sep 27 10:08:08 2019] PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 163840 bytes) in /Users/kp/kb_backend_apis_laravel/vendor/composer/ClassLoader.php on line 444

Can this actually be accomplished? if so, how?

0 likes
0 replies

Please or to participate in this conversation.