zoukankan      html  css  js  c++  java
  • 万源之源之drupal7

    (注:学习交流用)

    学习joomla的时候,看过一位前辈写的万源之源的帖子,让我记忆深刻,最新工作需要用到了drupal,所以把学习笔记整理出来,借用了一下“万源之源”的标题。

    对于程序的认识每个人都有可能不同,特别是一套相对成熟的框架,但是不管怎么理解或者怎么解释一段程序,唯一不变的就是研究对象(代码),所以需一切从代码开始。

    drupal的强大毋庸置疑,本章内容对于整个drupal仅仅是最小的一部分,由于本人也是初学,有错误的地方请大家理解,并且在您方便的时候帮忙指正一下,万分感激

    <?php
    //定义drupal的根目录
    define('DRUPAL_ROOT', getcwd());
    //引入引导文件
    require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
    
    //加载drupal,在这里定义drupal全部加载。其他的方式可以具体查看这个函数的执行过程。
    //这个过程就像是计算机的操作系统,如果要使用一台计算机,那么这台计算机一定要先运行
    //操作系统,然后才能正常使用,我们可以选择这台计算机的启动方式
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    
    //drupal系统已经准备好了,现在开始执行网站程序。
    menu_execute_active_handler();
    
    //按照页面的执行逻辑,解释下面的参数
    function menu_execute_active_handler($path = NULL, $deliver = TRUE){
    	// Check if site is offline.
    	//判断网站是否是offline
    	$page_callback_result = _menu_site_is_offline() ? MENU_SITE_OFFLINE : MENU_SITE_ONLINE;
    
    	// Allow other modules to change the site status but not the path because that
    	// would not change the global variable. hook_url_inbound_alter() can be used
    	// to change the path. Code later will not use the $read_only_path variable.
    	$read_only_path = !empty($path) ? $path : $_GET['q'];
    	//触发 menu_site_status_alter hook, 可以让module根据当前的路径修改网站的状态
    	drupal_alter('menu_site_status', $page_callback_result, $read_only_path);
    	
    	/** Only continue if the site status is not set.
    	只有在网站正常运行的时候,才执这段代码,这段代码的左右是根据 $path(现在这里是$_GET)在数据库menu_router
    	表里找到路由参数,在参数中,page_callback代表可以得到本页面的主要信息内容的函数,page_arguments代表所
    	需要的参数。
    	menu_router 表的更新工作是在 menu_rebuild() 的函数执行的,这个函数只有在需要的时候执行,比如第一次网站
    	被访问的时候或是clearn cache的时候
    	在得到menu_get_item函数中, 查到相应的路由参数后,执行了
    	    drupal_alter('menu_get_item', $router_item, $path, $original_map);
    	可以使module修改这个路由参数。*/
    	if ($page_callback_result == MENU_SITE_ONLINE) {
    		if ($router_item = menu_get_item($path)) {
    		if ($router_item['access']) {
    			if ($router_item['include_file']) {
    			require_once DRUPAL_ROOT . '/' . $router_item['include_file'];
    			}
    
    			$page_callback_result = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
    		}
    		else {
    			$page_callback_result = MENU_ACCESS_DENIED;
    		}
    		}
    		else {
    		$page_callback_result = MENU_NOT_FOUND;
    		}
    	}
    
    	// Deliver the result of the page callback to the browser, or if requested,
    	// return it raw, so calling code can do more processing.
    	//是否返回浏览器所需要的整体HTML结构,还是仅仅返回页面的主要内容,这里要是返回给浏览器输出的
    	if ($deliver) {
    		$default_delivery_callback = (isset($router_item) && $router_item) ? $router_item['delivery_callback'] : NULL;
    		//这句可以理解成,drupal 交付页面
    		drupal_deliver_page($page_callback_result, $default_delivery_callback);
    	}
    	else {
    		return $page_callback_result;
    	}
    }
    /**
     * Delivers a page callback result to the browser in the appropriate format.
     *
     * This function is most commonly called by menu_execute_active_handler(), but
     * can also be called by error conditions such as drupal_not_found(),
     * drupal_access_denied(), and drupal_site_offline().
     *
     * 这个函数的功能就是生成交付给浏览器的最终的HTML。
     * 
     * 在这个函数中用运行了一次$router_item = menu_get_item();别担心,因为在上个函数中已经运行过
     * 这个函数了,已经把所需要的路由参数放到cache中了,所以这次得到的是cache中的路由参数
     * 
     * 在得到交付函数后,执行了
     * 	drupal_alter('page_delivery_callback', $delivery_callback);
     * 代表可以在module里改变交付函数,作用是我们可以在不改变源代码的情况下修改它。
     */
    function drupal_deliver_page($page_callback_result, $default_delivery_callback = NULL){
    	if (!isset($default_delivery_callback) && ($router_item = menu_get_item())) {
    		$default_delivery_callback = $router_item['delivery_callback'];
    	}
    	$delivery_callback = !empty($default_delivery_callback) ? $default_delivery_callback : 'drupal_deliver_html_page';
    	// Give modules a chance to alter the delivery callback used, based on
    	// request-time context (e.g., HTTP request headers).
    	drupal_alter('page_delivery_callback', $delivery_callback);
    	if (function_exists($delivery_callback)) {
    		//这里是默认的 drupal_deliver_html_page() 函数。
    		$delivery_callback($page_callback_result);
    	}
    	else {
    		// If a delivery callback is specified, but doesn't exist as a function,
    		// something is wrong, but don't print anything, since it's not known
    		// what format the response needs to be in.
    		watchdog('delivery callback not found', 'callback %callback not found: %q.', array('%callback' => $delivery_callback, '%q' => $_GET['q']), WATCHDOG_ERROR);
    	}
    }
    
    /**
     * Packages and sends the result of a page callback to the browser as HTML.
     *
     * 默认的交付函数,根据页面回调函数结果得到的最终的HTML。
     */
    function drupal_deliver_html_page($page_callback_result){
    	// Emit the correct charset HTTP header, but not if the page callback
    	// result is NULL, since that likely indicates that it printed something
    	// in which case, no further headers may be sent, and not if code running
    	// for this page request has already set the content type header.
    	
    	/**
    	 *如果有返回结果,并且还没有 Content-Type 则添加默认的 Content-Type
    	 */
    	if (isset($page_callback_result) && is_null(drupal_get_http_header('Content-Type'))) {
    		drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
    	}
    
    	// Send appropriate HTTP-Header for browsers and search engines.
    	/**
    	 *添加页面的当前语言
    	 */
    	global $language;
    	drupal_add_http_header('Content-Language', $language->language);
    
    	// Menu status constants are integers; page content is a string or array.
    	/**
    	 *如果没有页面的主要内容,则执行错误处理,以为每个页面都有一个主要内容,如果没有
    	 *找到这个需要的内容,则代表页面无效。
    	 *
    	 *@$page_callback_result 正常情况下是一个字符串或者数组,如果是数字,则代表
    	 *是一个错误代号,根据这个错误代码执行相应的处理方法
    	 */
    	if (is_int($page_callback_result)) {
    		/*。。。。。。。*/
    	}elseif (isset($page_callback_result)) {
    		// Print anything besides a menu constant, assuming it's not NULL or
    		// undefined.
    		/**
    		 *渲染渲染整个页面。
    		 */
    		print drupal_render_page($page_callback_result);
    	}
    	
    	// Perform end-of-request tasks.
    	drupal_page_footer();
    }
    
    /**
     * Renders the page, including all theming.
     * 
     * 渲染整个页面,包括所有的主题内容
     */
    function drupal_render_page($page) {
    	//如果看了代码的引导阶段的话,你会发现很多地方用到了 drupal_static 函数,这个函数的功能可以
    	//理解成扩展的static 变量,他可以让其他的函数访问并修改本函数定义的静态变量,从而实现了对象
    	//属性的功能。
    	$main_content_display = &drupal_static('system_main_content_added', FALSE);
    
    	// Allow menu callbacks to return strings or arbitrary arrays to render.
    	// If the array returned is not of #type page directly, we need to fill
    	// in the page with defaults.
    	if (is_string($page) || (is_array($page) && (!isset($page['#type']) || ($page['#type'] != 'page')))) {
    		/**
    		 * 这个函数的作用是设置页面的主要内容,经过这个函数,我们可以在以后通过 
    		 *    drupal_set_page_content()//注意是不带参数的
    		 * 得到这里设置的主要内容,但是得到以后,system_main_content_added就会自动设置等TRUE,
    		 * 代表我们已经提取过页面的主要内容了
    		 */
    		drupal_set_page_content($page);
    		/**
    		 * Retrieves the default properties for the defined element type.
    		 * function element_info($type){...}
    		 * 这个函数触发了 module_invoke_all('element_info') hook,并把他缓存到cache里.
    		 * 
    		 * 这里得到page的element_info
    		 */
    		$page = element_info('page');
    		
    	}
    
    	// Modules can add elements to $page as needed in hook_page_build().
    	/**
    	 * 等于句代码 module_invoke_all($hook),允许module 参与page的生成,也可以根据$page的内容定义自己的逻辑
    	 */
    	foreach (module_implements('page_build') as $module) {
    		$function = $module . '_page_build';
    		$function($page);
    	}
    	// Modules alter the $page as needed. Blocks are populated into regions like
    	// 'sidebar_first', 'footer', etc.
    	/**
    	 *在生成$page之后,允许module修改 $page的参数(看到hook在drupal中的地位了吧,几乎所有的逻辑都是通过它实现的,
    	 *这也是drupal的自由之处,往往自用和代码逻辑已经分布联系非常紧密,你写的代码可以让别人二次开发么?这就需要经验
    	 *规划了)
    	 */
    	drupal_alter('page', $page);
    
    	// If no module has taken care of the main content, add it to the page now.
    	// This allows the site to still be usable even if no modules that
    	// control page regions (for example, the Block module) are enabled.
    	/**
    	 *前面介绍过,如果还没有提取过页面的主要内容,我们在这里提取页面的主要内容,
    	 *前面可以在hook里用 drupal_set_page_content() 提取页面的主要内容,如果提取了,下面将不会再一次提取。
    	 */
    	if (!$main_content_display) {
    		$page['content']['system_main'] = drupal_set_page_content();
    	}
    	
    	/**
    	 *根据$page内容渲染页面, 也就是返回$page 的 HTML。
    	 */
    	return drupal_render($page);
    }
    
    /**
     *这个函数非常重要,对于刚接触drupal也比较复杂,理解这个函数要小心+细心。
     *这个函数的功能是根据传过来的参数,渲染这个数组成需要的HTML。
     *@$elements 是一个关联(键/值对)数组, 它记录着所有的渲染的标签(如何渲染,渲染的过程等等),我们称它为已经结构
     *    化的数组树。键的名字以#开始的,代表当前的记录是$elements的一个属性,而其他的表示$elements 的子树,需要重新
     *    被执行drupal_render()进行递归。
     *    #access 记录当前元素是否有权利能被渲染。
     *    #printed 表示当前元素是不是被已经渲染过。
     *    #cache 表示当前元素是否需要被缓存,缓存的结构是
     *    		1)
     *    		'#cache'=>array(
     *    			'bid'=>NULL || 'your bid',
     *    			'cid'=>'your cid'
     *    		);
     *    		2)
     *    		'#cache'=>array(
     *    			'bid'=>NULL || 'your bid',
     *    			'key'=>array('your','key'),
     *    			'granularity'=> NULL || DRUPAL_CACHE_PER_ROLE || DRUPAL_CACHE_PER_USER || DRUPAL_CACHE_PER_PAGE
     *    		);
     *    #markup 标记, 如果这个值存在而 #type的值不存在的话,就使 #type = 'markup'
     *    #defaults_loaded 表示当前元素是不是被完全的(包括所有默认的属性),如果不是执行
     *    		$elements += element_info($elements['#type']);
     *    		重新加载。
     *    #pre_render 表示当前元素是否需要提前渲染,这里的值是用来渲染的函数,参数就是当前元素
     *    #children 存放当前元素被渲染后的结果
     *    #theme_wrappers 如果有的话,用theme(theme($theme_wrapper, $elements))重新渲染,可以在首次渲染的结果上进行二次加工
     *    #post_render 过滤输出内容,用来做输出前的最后工作,用来返回浏览器执行的安全内容。
     *    #states javascript 控制dom对象的状态,常在form控制表单是使用
     *    #attached 这里存储着所需要加载的javascript,css
     *    #prefix 和 #suffix 存放着当前元素渲染后的前缀和后缀。用来做最后的输出。
     *    		$output = $prefix . $elements['#children'] . $suffix;
     *    
     */
    function drupal_render(&$elements){
    	//......
    }
    /******未完待续(接下来就是theme函数)*******/
    
  • 相关阅读:
    flutter_bloc使用解析骚年,你还在手搭bloc吗!
    白嫖JetBrains正版全家桶!
    一文总结设计模式
    201671010119 201620172《Java程序设计》第五周学习心得
    201671010119 201620172《Java程序设计》第二周学习心得
    201671010119 201620172《Java程序设计》第三周学习心得
    201671010119 201620172《Java程序设计》第八周学习心得
    201671010119 201620172《Java程序设计》第四周学习心得
    201671010119 201620172《Java程序设计》第六周学习心得
    201671010119 201620172《Java程序设计》第一周学习心得
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2998619.html
Copyright © 2011-2022 走看看