LuXY 发布的文章

在PHP中处理树形结构,特别是从一个数组转换为树形结构(arrayToTree)以及将树形结构转换回数组(treeToArray),是实现复杂数据处理和展示的常见需求。此外,获取树的最大深度也是一个有用的功能。下面我将详细介绍如何实现这些功能。

构建树形结构(arrayToTree

首先,我们从一个简单的数组构建一个树形结构。假设我们有一个数组,其中每个元素都有一个parent_id字段指向其父节点。

$items = [
    ['id' => 1, 'name' => 'Root', 'parent_id' => 0],
    ['id' => 2, 'name' => 'Child 1', 'parent_id' => 1],
    ['id' => 3, 'name' => 'Child 2', 'parent_id' => 1],
    ['id' => 4, 'name' => 'Child 3', 'parent_id' => 2],
    ['id' => 5, 'name' => 'Child 4', 'parent_id' => 2]
];

我们可以使用以下函数将这个数组转换为树形结构:

function arrayToTree($items, $parentId = 0) {
    $branch = [];
    foreach ($items as $item) {
        if ($item['parent_id'] == $parentId) {
            $children = arrayToTree($items, $item['id']);
            if ($children) {
                $item['children'] = $children;
            }
            $branch[] = $item;
        }
    }
    return $branch;
}
 
$tree = arrayToTree($items);
print_r($tree);

将树形结构转换回数组(treeToArray

将树形结构转换回数组通常是为了便于存储或进一步处理。我们可以使用递归函数来实现这一点:

function treeToArray($tree) {
    $result = [];
    foreach ($tree as $node) {
        $result[] = $node;
        if (!empty($node['children'])) {
            foreach (treeToArray($node['children']) as $child) {
                $result[] = $child;
            }
        }
    }
    return $result;
}
 
$array = treeToArray($tree);
print_r($array);

获取树的最大深度

要获取树的最大深度,我们可以使用递归函数来遍历每个节点并记录最大深度:

function getMaxDepth($tree) {
    $depths = [];
    foreach ($tree as $node) {
        $depths[] = getNodeDepth($node);
    }
    return max($depths);
}
 
function getNodeDepth($node, $depth = 0) {
    if (empty($node['children'])) {
        return $depth; // Base case: leaf node reached.
    } else {
        $maxChildDepth = 0; // Initialize max depth for children.
        foreach ($node['children'] as $child) {
            $maxChildDepth = max($maxChildDepth, getNodeDepth($child, $depth + 1)); // Recursive call.
        }
        return $maxChildDepth; // Return the maximum depth found in children.
    }
}
 
$maxDepth = getMaxDepth($tree);
echo "Max Depth: " . $maxDepth; // Output the maximum depth.

你也许不需要 jQuery (You (Might) Don't Need jQuery)

Query 选择器

常用的 class、id、属性 选择器都可以使用 document.querySelectordocument.querySelectorAll 替代。区别是

  • document.querySelector 返回第一个匹配的 Element
  • document.querySelectorAll 返回所有匹配的 Element 组成的 NodeList。它可以通过 [].slice.call() 把它转成 Array
  • 如果匹配不到任何 Element,jQuery 返回空数组 [],但 document.querySelector 返回 null,注意空指针异常。当找不到时,也可以使用 || 设置默认的值,如 document.querySelectorAll(selector) || []

注意:document.querySelectordocument.querySelectorAll 性能很。如果想提高性能,尽量使用 document.getElementByIddocument.getElementsByClassNamedocument.getElementsByTagName

1.0 选择器查询

// jQuery
$('selector');

// Native
document.querySelectorAll('selector');

- 阅读剩余部分 -

/**
* 判断字符串是否为 Json 格式
*
* @param string $data Json 字符串
* @param bool $assoc 是否返回关联数组。默认返回对象
*
* @return array|bool|object 成功返回转换后的对象或数组,失败返回 false
*/
function isJson($data = '', $assoc = false) {
  $data = json_decode($data, $assoc);
  if (($data && is_object($data)) || (is_array($data) && !empty($data))) {
    return $data;
  }
  return false;
}

使用 window 对象的 open() 方法可以打开一个新窗口。用法如下:

window.open(url, target, features)

该方法返回值为新创建的 window 对象,使用它可以引用新创建的窗口。

url
可选字符串,声明新窗口需要载入的 url 地址,可以是 web 上的 html 页面也可以是图片文件或者其他任何浏览器支持的文件格式。
如果省略,或者为空,则新窗口就不会显示任何文档。

target
可选字符串,声明新窗口的名称。该字符串可以用来作为超链接 <a> 或表单 <form> 元素的目标属性值。字符串中不能含有空白字符。
如果该参数指定了一个已经存在的窗口,那么 open() 方法就不再创建一个新窗口,而只是返回对指定窗口的引用,在这种情况下,features 参数将被忽略。

features
可选字符串,声明了将要打开的窗口的一些特性 (窗口功能和工具栏),具体说明如下表所示。
如果省略该参数,新窗口将具有所有标准特征。

- 阅读剩余部分 -

在 jQuery 中,获取元素高度的方法有 3 个:height()innerHeight()outerHeight()

元素的盒模型: height(高度)、padding(内边距)、margin(外边距)、border(边框)。

height()

  • 用于设置或返回当前匹配元素的高度;
  • 高度不包括元素的外边距(margin)、内边距(padding)、边框(border)等;
  • 对不可见的元素依然有效;
  • 可获取window,document对象的高度
$(window).height();  // 返回浏览器视口的高度
$(document).height();  // 返回HTML文档的高度

- 阅读剩余部分 -

/*!
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

// the semi-colon before the function invocation is a safety 
// net against concatenated scripts and/or other plugins 
// that are not closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global 
    // variable in ECMAScript 3 and is mutable (i.e. it can 
    // be changed by someone else). undefined isn't really 
    // being passed in so we can ensure that its value is 
    // truly undefined. In ES5, undefined can no longer be 
    // modified.

    // window and document are passed through as local 
    // variables rather than as globals, because this (slightly) 
    // quickens the resolution process and can be more 
    // efficiently minified (especially when both are 
    // regularly referenced in your plugin).

    // Create the defaults once
    var pluginName = 'defaultPluginName',
        defaults = {
            propertyName: "value"
        };

    // The actual plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method that merges the 
        // contents of two or more objects, storing the 
        // result in the first object. The first object 
        // is generally empty because we don't want to alter 
        // the default options for future instances of the plugin
        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype.init = function () {
        // Place initialization logic here
        // You already have access to the DOM element and
        // the options via the instance, e.g. this.element 
        // and this.options
    };

    // A really lightweight plugin wrapper around the constructor, 
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, 
                new Plugin( this, options ));
            }
        });
    }

})( jQuery, window, document );
(function( $ ){

  var methods = {
    init : function( options ) { // THIS },
    show : function( ) { // IS   },
    hide : function( ) { // GOOD },
    update : function( content ) { // !!! }
  };

  $.fn.tooltip = function( method ) {

    // Method calling logic
    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }    

  };

})( jQuery );

如果是MySQL数据库,可进入主机的数据库管理后台,找到博客数据库中的typecho_users表,修改password的值为e10adc3949ba59abbe56e057f20f883e(相当于加密过的密码123456)。

如果使用Sqlite数据库,则先将数据库下载到本地,用数据库管理工具(如Navicat)按上述步骤修改,修改后再上传回虚拟主机。

完成后,用密码123456登录,进入到后台修改密码。

日期和时间戳互换

FROM_UNIXTIME(unixtime, format) 将时间戳转换为日期时间字符串
UNIX_TIMESTAMP(date) 将指定的日期或者日期字符串转换为时间戳
DATE_FORMAT(date, format) 根据参数对date进行格式化

获取当前日期、时间

select now(); 或 select current_timestamp(); //获得当前时间  格式:2016-01-12 23:19:43
select curdate(); 或 select current_date(); //获得当前时间  格式: 2016-01-12
select current_date()+0;  //获得当前时间  格式: 20160112
select curtime(); 或 select current_time(); //获得当前时间  格式:23:19:43

- 阅读剩余部分 -

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

URL.createObjectURL(blob)和FileReader.readAsDataURL(file)很相似:

区别

  • 通过FileReader.readAsDataURL(file)可以获取一段data:base64的字符串
  • 通过URL.createObjectURL(blob)可以获取当前文件的一个内存URL

- 阅读剩余部分 -

<?php Typecho_Widget::widget('Widget_Stat')->to($stat); ?>
文章总数:<?php $stat->publishedPostsNum() ?>篇
分类总数:<?php $stat->categoriesNum() ?>个
评论总数:<?php $stat->publishedCommentsNum() ?>条
页面总数:<?php $stat->publishedPagesNum() ?>个
当前作者的文章总数:<?php $stat->myPublishedPostsNum() ?>篇

- 阅读剩余部分 -