PHP在线相册--【强撸项目】

news2024/10/3 4:32:15

强撸项目系列总目录在000集

PHP要怎么学–【思维导图知识范围】

文章目录

    • 本系列校训
    • 本项目使用技术
  • 上效果图
  • phpStudy 设置
  • 导数据库
  • 项目目录如图:
  • 代码部分:
    • 主页
  • 配套资源
  • 作业:

本系列校训

用免费公开视频,卷飞培训班哈人!打死不报班,赚钱靠狠干!
只要自己有电脑,前后项目都能搞!N年苦学无人问,一朝成名天下知!

本项目使用技术

PHP无类PHP类写法ThinkPHP框架其它框架
*

环境

PHP版本mysql版本运行工具编辑工具
5.4.45+Apache5.5(phpstudy自带)phpstudy2018VSCode

上效果图

在php 当中,上传图片,上传照片这种小功能还是挺方便的。注意没有登陆
所以,在线相册这个小项目还是有一定的价值的。比如某宝(好象人家不会用这么LOW的)那就作业吧

在这里插入图片描述

修改了代码,可以搜索了。
在这里插入图片描述在这里插入图片描述

phpStudy 设置

网站目录,不能有中文或空格,就乖乖的用C语言能识别的变量名

在这里插入图片描述

导数据库

打开mysql-front 或navicat
注意:数据库名:email 超级用户:root 密码:123456
运行本例附件即可。最后导入数据库成功的截图如下:

在这里插入图片描述

项目目录如图:

在这里插入图片描述
颜色主题:
在这里插入图片描述

代码部分:

主页

<?php
require './common/init.php';
// 接收参数
$id = input('get', 'id', 'd');
$sort = input('get', 'sort', 's');
$action = input('post', 'action', 's');
// 判断相册是否存在
if ($id && !album_data($id)) {
    exit('相册不存在!');
}
// 新建相册
if ($action == 'new') {
    album_new($id, input('post', 'name', 's'));
}
// 上传图片
elseif ($action == 'upload') {
    album_upload($id, input($_FILES, 'upload', 'a'));
}
// 删除相册
elseif ($action == 'delete') {
    album_delete(input('post', 'action_id', 'd'));
}
// 设为封面
elseif ($action == 'pic_cover') {
    album_picture_cover(input('post', 'action_id', 'd'), $id);
}
// 删除图片
elseif ($action == 'pic_delete') {
    album_picture_delete(input('post', 'action_id', 'd'));
}
// 查询相册名称作为网页标题
$title = album_data($id)['name'] ?: '首页';
// 查询导航栏
$nav = album_nav($id);
// 查询相册列表
$list = album_list($id, $sort);
// 载入模板
require './view/index.html';

主页的html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><?=htmlspecialchars($title)?> - 在线相册</title>
    <link rel="stylesheet" href="./css/style.css">
  </head>
  <body>
    <?php require './view/common/top.html'; ?>
    <div class="container">
      <div class="opt">
        <div class="opt-sort">
          <a class="<?=($sort!='old') ? 'curr' : ''?>" href="?id=<?=$id?>">最新的</a>
          <a class="<?=($sort=='old') ? 'curr' : ''?>" href="?id=<?=$id?>&sort=old">最旧的</a>
        </div>
        <div class="opt-new">
          <form method="post">
            <input type="hidden" name="action" value="new">
            <input type="text" name="name" placeholder="输入相册名称" required><input type="submit" value="创建相册">
          </form>
        </div>
        <div class="opt-upload">
          <form method="post" enctype="multipart/form-data">
            <input type="hidden" name="action" value="upload">
            <input type="file" name="upload" required><input type="submit" value="上传图片">
          </form>
        </div>
        <div class="opt-search">
          <form method="get" action="search.php">
            <input type="hidden" name="action" value="search">
            <input type="text" name="search" placeholder="输入关键词" required><input type="submit" value="搜索">
          </form>
        </div>
      </div>
      <div class="album">
        <?php if(empty($list['album']) && empty($list['picture'])): ?>
          <div class="album-tip">该相册为空。</div>
        <?php endif; ?>
        <!-- 子相册列表 -->
        <?php foreach ($list['album'] as $v): ?>
          <div class="album-list album-dir">
            <div class="album-list-content">
              <div class="album-list-tips">相册</div>
              <a href="?id=<?=$v['id']?>"><img src="./covers/<?=$v['cover'] ?: 'nopic.png'?>"></a>
              <div class="album-list-desc"><p><a href="?id=<?=$v['id']?>"><?=htmlspecialchars($v['name'])?></a> (<?=$v['total']?>)</p></div>
              <div class="album-list-opt">
                <form method="post">
                  <input type="hidden" name="action_id" value="<?=$v['id']?>">
                  <button class="js-del" name="action" value="delete">删除</button>
                </form>
              </div>
            </div>
          </div>  
        <?php endforeach; ?>
        <!-- 图片列表 -->
        <?php foreach($list['picture'] as $v): ?>
        <div class="album-list">
          <div class="album-list-content">
            <a href="show.php?id=<?=$v['id']?>"><img src="./thumbs/<?=$v['save']?>"></a>
            <div class="album-list-desc"><p><a href="show.php?id=<?=$v['id']?>"><?=htmlspecialchars($v['name'])?></a></p></div>
            <div class="album-list-opt">
              <form method="post">
                <input type="hidden" name="action_id" value="<?=$v['id']?>">
                <?php if($id): ?><button name="action" value="pic_cover">设为封面</button><?php endif; ?>
                <button class="js-del" name="action" value="pic_delete">删除</button>
              </form>
            </div>
          </div>
        </div>
        <?php endforeach; ?>
      </div>
    </div>
    <?php require './view/common/footer.html'; ?>
    <script src="./js/common.js"></script>
  </body>
</html>

后台关键逻辑代码:

<?php

/**
 * 查询相册记录(缓存查询结果)
 * @param int $id 相册ID
 * @return array 查询结果数组,不存在时返回false
 */
function album_data($id)
{
    static $data = [0 => false];
    if (!isset($data[$id])) {
        $data[$id] = db_fetch_row("SELECT `pid`,`path`,`name`,`cover`,`total` FROM `album` WHERE `id`=$id") ?: false;
    }
    return $data[$id];
}

/**
 * 查询相册层级导航
 * @param int $id 相册ID
 * @return array 查询结果数组,不存在时返回空数组
 */
function album_nav($id)
{
    $path = preg_replace('/^0,/', '', (album_data($id)['path'] . $id));
    return $path ? db_fetch_all("SELECT `id`,`name` FROM `album` WHERE `id` IN ($path) ORDER BY FIELD(`id`,$path)") : [];
}

/**
 * 查询当前相册所有的子相册和图片
 * @param int $id 相册ID
 * @param string $sort 排序(new、old)
 * @return array 查询结果数组
 */
function album_list($id, $sort)
{
    $sort = ($sort == 'old') ? 'ASC' : 'DESC';
    return [
        'album' => db_fetch_all("SELECT `id`,`name`,`cover`,`total` FROM `album` WHERE `pid`=$id  ORDER BY `id` $sort"),
        'picture' => db_fetch_all("SELECT `id`,`name`,`save` FROM `picture` WHERE `pid`=$id ORDER BY `id` $sort")
    ];
}

/**
 * 创建相册
 * @param int $pid 新相册的上级目录ID
 * @param string $name 新相册的名称
 */
function album_new($pid, $name)
{
    $data = album_data($pid);
    if (substr_count($data['path'], ',') >= config('LEVEL_MAX')) {
        return tips('无法继续创建子目录,已经达到最多层级!');
    }
 /* if (!preg_match('/^\w{1,12}$/', $name)) {
        return tips('无法创建相册,只允许1~12位字母、数字、下划线组成。');
    } */
    $name = mb_strimwidth(trim($name), 0, 12);
    db_exec('INSERT INTO `album` (`pid`,`path`,`name`) VALUES (?,?,?)', 'iss', [
        $pid, ($data['path'] . $pid . ','), ($name ?: '未命名')
    ]);
}

/**
 * 上传图片
 * @param int $pid 图片所属的相册ID
 * @param array $file 上传文件 $_FILES['xx'] 数组
 */
function album_upload($pid, $file)
{
    // 检查文件是否上传成功
    if (true !== ($error = upload_check($file))) {
        return tips("文件上传失败:$error");
    }
    // 检查文件类型是否正确
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    if (!in_array(strtolower($ext), config('ALLOW_EXT'))) {
        return tips('文件上传失败:只允许扩展名:' . implode(', ', config('ALLOW_EXT')));
    }
    // 生成文件名和保存路径
    $new_dir = date('Y-m/d');                       // 生成子目录
    $new_name = md5(microtime(true)) . ".$ext";     // 生成文件名
    // 创建原图保存目录
    $upload_dir = "./uploads/$new_dir";
    if (!is_dir($upload_dir) && !mkdir($upload_dir, 0777, true)) {
        return tips('文件上传失败:无法创建保存目录!');
    }
    // 创建缩略图保存目录
    $thumb_dir = "./thumbs/$new_dir";
    if (!is_dir($thumb_dir) && !mkdir($thumb_dir, 0777, true)) {
        return tips('文件上传失败:无法创建缩略图保存目录!');
    }
    // 保存上传文件
    if (!move_uploaded_file($file['tmp_name'], "$upload_dir/$new_name")) {
        return tips('文件上传失败:无法保存文件!');
    }
    // 创建缩略图
    thumb("$upload_dir/$new_name", "$thumb_dir/$new_name", config('THUMB_SIZE'));
    // 保存到数据库
    $name = mb_strimwidth(trim(pathinfo($file['name'], PATHINFO_FILENAME)), 0, 80);
    db_exec('INSERT INTO `picture` (`pid`,`name`,`save`) VALUES (?,?,?)', 'iss', [$pid, $name, "$new_dir/$new_name"]);
    $pid && album_total($pid, '+1');
}

/**
 * 修改相册的total字段
 * @param int $id 相册ID
 * @param string $method 操作(+1、-1)
 */
function album_total($id, $method = '+1')
{
    $path = preg_replace('/^0,/', '', (album_data($id)['path'] . $id));
    $path && db_exec("UPDATE `album` SET `total`=`total`$method WHERE `id` IN ($path)");
}

/**
 * 删除相册
 * @param int $id 相册ID
 */
function album_delete($id)
{
    $data = album_data($id);
    if ($data['total'] > 0) {
        return tips('删除失败:只能删除空相册!');
    }
    if (db_fetch_row("SELECT 1 FROM `album` WHERE `pid`=$id")) {
        return tips('删除失败:该相册含有子相册!');
    }
    db_exec("DELETE FROM `album` WHERE `id`=$id");
    $data['cover'] && is_file("./covers/{$data['cover']}") && unlink("./covers/{$data['cover']}");
}

/**
 * 查询图片记录
 * @param int $id 图片ID
 * @return array 查询结果数组,不存在时返回null
 */
function album_picture_data($id)
{
    return db_fetch_row("SELECT `pid`,`name`,`save` FROM `picture` WHERE `id`=$id");
}

/**
 * 设置图片为相册封面
 * @param int $id 图片ID
 * @param int $pid 相册ID
 */
function album_picture_cover($id, $pid)
{
    if (!$data = album_picture_data($id)) {
        return tips('设置失败:图片不存在!');
    }
    $cover_dir = './covers/' . dirname($data['save']);
    if (!is_dir($cover_dir) && !mkdir($cover_dir, 0777, true)) {
        return tips('设置失败:无法创建封面图保存目录!');
    }
    $cover_del = album_data($pid)['cover'];
    is_file("./covers/$cover_del") && unlink("./covers/$cover_del");
    copy("./thumbs/{$data['save']}", "./covers/{$data['save']}");
    db_exec("UPDATE `album` SET `cover`=? WHERE `id`=?", 'si', [$data['save'], $pid]);
    tips('设置成功!');
}

/**
 * 删除图片
 * @param int $id 图片ID
 */
function album_picture_delete($id)
{
    if (!$data = album_picture_data($id)) {
        return tips('删除失败:图片不存在!');
    }
    db_exec("DELETE FROM `picture` WHERE `id`=$id");
    is_file("./thumbs/{$data['save']}") && unlink("./thumbs/{$data['save']}");
    is_file("./uploads/{$data['save']}") && unlink("./uploads/{$data['save']}"); 
    $data['pid'] && album_total($data['pid'], '-1');
}

配套资源

PHP在线相册-强撸项目
https://download.csdn.net/download/dearmite/88084818

作业:

PHP在线相册,美化前台页面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】【Image Inpainting】Free-Form Image Inpainting with Gated Convolution

模型&#xff1a;DeepFillv2 (CVPR’2019) 论文&#xff1a;https://arxiv.org/abs/1806.03589 代码&#xff1a;https://github.com/JiahuiYu/generative_inpainting 文章目录 效果AbstractIntroductionRelated WorkAutomatic Image InpaintingGuided Image Inpainting and Sy…

KaiwuDB 资深解决方案专家周幸骏:打造核心时序引擎,释放数据新价值

以下为浪潮 KaiwuDB 资深解决方案专家周幸骏受邀于7月4日在京举行的可信数据库发展大会发表演讲的实录摘要&#xff0c;欢迎大家点赞、收藏、关注&#xff01; 01 聚焦“时序” 据 IDC 等权威数据统计&#xff0c;预估 2025 年物联网设备产生的数据可达到 79.4ZB &#xff1b;…

ubuntu与windows之间的文件共享

最近在做项目&#xff0c;需要用到ubuntu进行代码编译生成可执行文件&#xff0c;但是我个人阅读和编写代码喜欢用source insight这个软件IDE。安利一下这个软件&#xff0c;阅读代码和编辑代码真的很棒啊&#xff0c;谁用谁知道吧&#xff01; 由于在ubuntu中安装source insig…

ShardingJDBC - 学习笔记

一、简介 官网&#xff1a;Apache ShardingSphere 下载地址&#xff1a;下载 :: ShardingSphere 快速入门&#xff1a;ShardingSphere-JDBC :: ShardingSphere 分库分表框架 ShardingSphere包括Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar三个开源分布式数据库中间件解…

每月被攻击4000万次,全球最不安全的关键基础设施实锤了

在当今不确定的地缘政治环境中&#xff0c;无论是个人还是企业都高度关注潜在的网络攻击。而这其中最令人担忧的是对关键基础设施和工业资产的攻击。 关键基础设施中尤其是电力、交通、通信、金融等系统均在现代社会中发挥着至关重要的作用&#xff0c;因此关键基础设施一直是…

程序员如何向老板提加薪?

今天的问题不仅适用于程序员&#xff0c;对于其他职业同样适用。如果你认为自己所做的工作应该得到更多的报酬&#xff0c;并且想为此做点什么&#xff0c;你有两个选择&#xff1a;找一个新的高薪工作或要求加薪。 这两种选择都会带来新的焦虑&#xff0c;但它们都会带来新的…

【框架篇】Spring Boot 配置文件(详细教程)

Spring Boot 配置文件 一&#xff0c;配置文件的用途 配置文件在Spring Boot项目中的地位是比较重要&#xff0c;其功能可主要归纳为以下几个&#xff1a; 进行配置程序属性&#xff1a;配置文件允许设置应用程序的各种属性&#xff0c;如数据库连接、端口号、日志级别、缓存…

多态及其原理

文章目录 构成多态的条件虚函数作用&#xff1a;完成重写 重写重载 重写 隐藏为什么析构函数要搞成符合多态?原理预热对于基类指针或引用指向父类或者子类的成员函数是如何调用不同的函数呢&#xff1f; 一个类如果是基类&#xff0c;它的析构函数最好加上virtual 构成多态的条…

【【51单片机的LCD1602 最简单的一集】】

最简单的一集&#xff0c;明白运算显示就没问题 这一节相对简单 其实只要明白显示行列就可以了 剩下来的取什么基本上就是遍历 然后读取到\0停止 下面是基础的LCD1602的功能 #include <REGX52.H> sbit LCD_RSP2^6; sbit LCD_RWP2^5; sbit LCD_EP2^7; #define LCD_Data…

ES6基础知识七:你是怎么理解ES6中 Generator的?使用场景?

一、介绍 Generator 函数是 ES6 提供的一种异步编程解决方案&#xff0c;语法行为与传统函数完全不同 回顾下上文提到的解决异步的手段&#xff1a; 回调函数promise 那么&#xff0c;上文我们提到promsie已经是一种比较流行的解决异步方案&#xff0c;那么为什么还出现Gen…

归并排序法解释

什么是归并排序法 归并排序是一种常见的排序算法&#xff0c;它基于分治策略&#xff0c;将一个大问题分解为小问题来解决。归并排序的主要思想是将待排序的数组分成两个子数组&#xff0c;分别对这两个子数组进行排序&#xff0c;最后将两个有序的子数组合并成一个有序的数组…

Openlayers入门,Openlayers调整中心点坐标、Openlayers调整缩放级别、Openlayers调整地图可视角度和地图复位

专栏目录: OpenLayers入门教程汇总目录 前言 本章介绍一下Openlayers最基础的调整中心点坐标方式、调整缩放级别、调整地图可视角度和地图复位的小功能示例,非常简单,可直接上手。 二、依赖和使用 "ol": "^6.15.1"使用npm安装依赖npm install ol@6…

重学C++系列之继承

一、什么是继承 继承是面向对象三大特性之一&#xff0c;C中&#xff0c;被继承的类称为基类&#xff08;父类&#xff09;&#xff0c;继承别的类的类成为派生类&#xff08;子类&#xff09;&#xff0c;继承除了基类的构造函数和析构函数不继承外&#xff0c;其余成员全部继…

【安卓】视频播放器实现过程,超详细注释,自定义视频进度条,打开本地文件播放视频等功能。

一、实现效果 废话不多说&#xff0c;直接上代码&#xff0c;里面有详细注释&#xff0c;不清楚的评论区留言。 二、布局代码 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res…

Android安卓实战项目(3)—一个炫酷的健身APP界面

Android安卓实战项目&#xff08;3&#xff09;—一个炫酷的健身APP界面 一.项目运行介绍 1.大致浏览 2.功能介绍 &#xff08;1&#xff09;功能一 上导航条 &#xff08;2&#xff09;功能二 下导航条 二.具体实现 MainActivity.java package com.rckdeveloper.fitene…

python 面向对象编程的特点 - 封装 - 继承(经典类、新式类) - 多态 - 静态方法、类方法 - 下划线的使用 - 回合制攻击游戏实验

目录 面向对象编程的特点&#xff1a; 封装&#xff1a;封装是将数据和操作&#xff08;方法&#xff09;封装在一个对象中的能力 继承&#xff1a;继承是指一个类&#xff08;子类&#xff09;可以继承另一个类&#xff08;父类&#xff09;的属性和方法。 我们为什么需要继…

Python采集法外狂徒张三所有视频【含jS逆向解密】

传说中&#xff0c;有人因为只是远远的看了一眼法外狂徒张三就进去了&#x1f602; 我现在是获取他视频&#xff0c;岂不是直接终生了&#x1f929; 网友&#xff1a;赶紧跑路吧 &#x1f60f; 好了话不多说&#xff0c;我们直接开始今天的内容吧&#xff01; 你需要准备 …

详解STM32的GPIO八种输入输出模式,GPIO各种输入输出的区别、初始化的步骤详解,看这文章就行了(超详细)

在STM32微控制器中&#xff0c;常见的输入输出(GPIO)模式有八种&#xff0c;分别是推挽输出、开漏输出、复用推挽输出、复用开漏输出、浮空输入、上拉输入、下拉输入和模拟输入。下面我将为你解释每种模式的特点和区别&#xff0c;并提供相应的示例代码。 文章目录 介绍区别初…

组合模式-树形结构的处理

A公司需要筛选出年龄35岁及以上(如果是领导&#xff0c;年龄为45岁及以上)的人。其组织架构图如下。 图 A公司部分组织架构图 图 传统解决方案 public class Development {private String name;public Development(String name) {this.name name;}List<Employee> emplo…

uni-app优雅的实现时间戳转换日期格式

现在显示的格式如下图&#xff1a; 我期望统一格式&#xff0c;所以不妨前端处理一下&#xff0c;核心代码如下 filters: {// 时间戳处理formatDate: function(value, spe /) {value value * 1000let data new Date(value);let year data.getFullYear();let month data.…