在不使用数据库查询或主机文件的情况下检查子域是否存在的更好方法

时间:2015-06-03 10:08:38

标签: php apache symfony optimization wildcard-subdomain

我正在使用symfony2,在我的学生住宿申请中,我为每所大学创建动态子域名,我使用通配符子域条目配置虚拟主机,因此任何子域都有效。

如何检查子域是否已注册且属于大学,我如何有效地将其与随机键入的 非用户注册 子域进行区分?

如果我使用数据库查询,那么来自好奇用户的每次随机访问都会导致大量的数据库查询,并且使用hosts文件会太慢(不是最佳实践)

请使用php或symfony或您熟悉的任何其他技巧建议一种有效的方法

(附加信息)将有一个免费试用版'选项,这将导致很多子域名,因为任何人和每个人都会开始免费试用,这是我试图实现的一个非常好的例子。StudyStays

-Thanks

1 个答案:

答案 0 :(得分:1)

您可以缓存所有每个子域请求(使用Doctrine缓存作为您使用的任何缓存系统的包装器),这样每次后续检查只需要检查缓存而不是数据库。

此外,在添加/删除/更新子域对象时,您可以更新缓存值以使其保持最新状态。

应用程序/配置/ config.yml

设置Doctrine Cache Bundle的提供程序,有关详细信息,请参阅the docs(您需要将Doctrine Cache Bundle添加到供应商和AppKernel中。)

doctrine_cache:
    providers:
        acme_subdomain:
            type: filesystem # apc, array, redis, etc
            namespace: acme_subdomain

的Acme \ YourBundle \注册表\ SubdomainRegistry

创建一个可以检查子域状态的注册表,并在需要时更新缓存。这个例子将状态存储为字符串而不是布尔值(据我所知)a" not found" key将返回false而不是null。

use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Persistence\ObjectManager;

class SubdomainRegistry implements SubdomainRegistry
{
    const REGISTERED   = 'registered';
    const UNREGISTERED = 'unregistered';

    /**
     * @param ObjectManager
     */
    protected $manager;

    /**
     * @param Cache
     */
    protected $cache;

    public function __construct(ObjectManager $manager, Cache $cache)
    {
        $this->manager = $manager;
        $this->cache = $cache;
    }

    /**
     * @param string $subdomain
     * @return boolean
     */
    public function isSubdomainRegistered($subdomain)
    {
        // If subdomain is not in cache update cache
        if (!$this->cache->has($subdomain)) {
            $this->updateRegistry($subdomain);
        }

        return self::REGISTERED === $this->cache->get($subdomain);
    }

    /**
     * @param string $subdomain
     * @return boolean
     */
    public function registerSubdomain($subdomain)
    {
        $this->cache->set($subdomain, self::REGISTERED);

        return $this;
    }

    /**
     * @param string $subdomain
     * @return boolean
     */
    public function unregisterSubdomain($subdomain)
    {
        $this->cache->set($subdomain, self::UNREGISTERED);

        return $this;
    }

    /**
     * @param string $subdomain
     * @return null
     */
    private function updateRegistry($subdomain)
    {
        $object = $this->manager->findOneBy(array('subdomain' => $subdomain);

        // $object->isActive() assume you are storing all subdomains after cancelling
        // and setting it to inactive. You could put your own real logic here
        if (null === $object || !$object->isActive()) {
            $this->unregisterSubdomain($subdomain);

            return null;
        }

        $this->registerSubdomain($subdomain);
    }

然后,当您注册或取消注册子域时,您可以在方法中添加对注册表的调用。

例如......

$subdomain = new Subdomain();
// Subdomain as a property of subdomain seems weird to me
// but as I can't immediately think of anything better I'll go with it
$subdomain->setSubdomain('acme');
// .. subdomain details
$this->manager->persist($subdomain);
$this->manager->flush();
$this->registry->registerSubdomain($subdomain->getSubdomain());