当前位置: 首页 > 工具软件 > EduSoho > 使用案例 >

EDUSOHO踩坑笔记之六:edusoho架构及模块分析

洪璞瑜
2023-12-01

EDUSOHO踩坑笔记之六:edusoho架构及模块分析

       从目录结构、入口文件、配置、控制器、服务层、模型、模块组成等几个角度,进行架构的描述。本文档是以8.0的版本为基准的说明,与其他版本会有些区别。

一、目录结构

入口:{$HOME}\web
控制器:{$HOME}\src\AppBundle\Controller\模块名Controller.php
模型:{$HOME}\src\Biz\Controller\模块名\Dao\Impl\表面DaoImpl.php
视图:{$HOME}\app\Resources\views\视图文件夹路径\名称.html.twig
路由文件:{$HOME}\api\config\routing.php

二、入口文件

{$HOME}\web\app.php

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();
$request = Request::createFromGlobals();
$kernel->setRequest($request);
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

三、配置

//路由
{$HOME}\src\AppBundle\Resources\config\routing.yml
{$HOME}\src\AppBundle\Resources\config\routing_admin.yml

homepage:
    path:  /
    defaults: { _controller: AppBundle:Default:index }
...
order_calculate_price:
    path: /order/price/calculate
    defaults: { _controller: AppBundle:Order/Order:price, limit: '' }
admin_discovery_column_category_tree:
    path: /discovery_column/category/tree
    defaults: { _controller: AppBundle:Admin/DiscoveryColumn:categoryTree }

四、控制器

{HOME}\src\AppBundle

以 http://edu.test/user/4 为例:
$app->get(_u('/user/{id}'), 'res.User:get');
{$HOME}\src\AppBundle\Controller\UserController.php

protected function tryGetUser($id)
{
    $user = $this->getUserService()->getUser($id);
    if (empty($user)) {
        throw $this->createNotFoundException();
    }
    return $user;
}

五、服务层

以 http://edu.test/user/4/about 为例:
{HOME}\src\Biz\User\Service\UserService.php
{$HOME}\src\AppBundle\Controller\UserController.php

public function aboutAction(Request $request, $id)
{
    $user = $this->tryGetUser($id);
    return $this->_aboutAction($user);
}

protected function _aboutAction($user)
{
    $userProfile = $this->getUserService()->getUserProfile($user['id']);
    //不存在 getUserProfile() 方法时,则调用 get 方法,表为 user_profile
    return $this->render('user/about.html.twig', array(
        'user' => $user,
        'userProfile' => $userProfile,
        'type' => 'about',
    ));
}

{$HOME}\src\Biz\User\Service\Impl\UserServiceImpl.php

<?php

namespace Biz\User\Service\Impl;

use Biz\BaseService;
use Biz\User\Dao\UserDao;
...

class UserServiceImpl extends BaseService implements UserService{
	public function getUser($id, $lock = false)
    {
        $user = $this->getUserDao()->get($id, array('lock' => $lock));
        return !$user ? null : UserSerialize::unserialize($user);
    }
    ...
	public function getUserProfile($id)
    {
        return $this->getProfileDao()->get($id);
    }
}

{$HOME}\vendor\codeages\biz-framework\src\Dao\DaoProxy.php

<?php

namespace Codeages\Biz\Framework\Dao;

use Codeages\Biz\Framework\Dao\Annotation\MetadataReader;

class DaoProxy
{
	/**
     * 代理 get 开头的方法调用
     *
     * @param string $method 被调用的 Dao 方法名
     * @param array $arguments 调用参数
     * @return array|null
     */
    protected function get($method, $arguments)
    {
        $lastArgument = end($arguments);
        reset($arguments);
        
        // lock模式下,因为需要借助mysql的锁,不走cache
        if (is_array($lastArgument) && isset($lastArgument['lock']) && true === $lastArgument['lock']) {
            $row = $this->callRealDao($method, $arguments);
            $this->unserialize($row);

            return $row;
        }

        if ($this->arrayStorage) {
            $key = $this->getCacheKey($this->dao, $method, $arguments);
            if (!empty($this->arrayStorage[$key])) {
                return $this->arrayStorage[$key];
            }
        }

        $strategy = $this->buildCacheStrategy();
        if ($strategy) {
            $cache = $strategy->beforeQuery($this->dao, $method, $arguments);
            // 命中 cache, 直接返回 cache 数据
            if (false !== $cache) {
                return $cache;
            }
        }

        $row = $this->callRealDao($method, $arguments);
        $this->unserialize($row);

        // 将结果缓存至 ArrayStorage
        $this->arrayStorage && ($this->arrayStorage[$this->getCacheKey($this->dao, $method, $arguments)] = $row);

        if ($strategy) {
            $strategy->afterQuery($this->dao, $method, $arguments, $row);
        }

        return $row;
    }
}

六、模型

{$HOME}\src\Biz\User\Dao\Impl\UserDaoImpl.php

<?php

namespace Biz\User\Dao\Impl;

use Biz\User\Dao\UserDao;
use Codeages\Biz\Framework\Dao\AdvancedDaoImpl;

class UserDaoImpl extends AdvancedDaoImpl implements UserDao{

	protected $table = 'user';
	...
}

{$HOME}\vendor\codeages\biz-framework\src\Dao\GeneralDaoImpl.php

<?php

namespace Codeages\Biz\Framework\Dao;

use Codeages\Biz\Framework\Context\Biz;

abstract class GeneralDaoImpl implements GeneralDaoInterface{
	...
	public function get($id, array $options = array())
    {
        $lock = isset($options['lock']) && true === $options['lock'];
        $sql = "SELECT * FROM {$this->table()} WHERE id = ?".($lock ? ' FOR UPDATE' : '');
        return $this->db()->fetchAssoc($sql, array($id)) ?: null;
    }
    ...
}

七、模块分析

教师端

在教课程 /my/teaching/course_sets
教学课表 /my/teaching/live/calendar
在教班级 /my/teaching/classrooms
学员问题 /my/teaching/threads/question
学员话题 /my/teaching/threads/discussion
试卷批阅 /my/testpaper/check
作业批阅 /my/homework/check
教学资料库 /material/lib/browse

学生端

我的课程 /my/courses/learning
我的班级 /my/classrooms
我的问答 /my/questions
我的话题 /my/discussions
我的笔记 /my/notebooks
我的作业 /my/homework/finished/list
我的考试 /my/testpaper/list
我的小组 /my/group

管理员

用户 /admin/user
课程 /admin/course_set/normal/index
运营 /admin/article
交易 /admin/order/manage
教育云 /admin/setting/my/cloud/overview
微营销 /admin/login/marketing
分销 /admin/login/distributor
移动端 /admin/wechat_app
系统 /admin/setting/site

 类似资料: