分类:programming

Build PHP Development Environment on Mac OSX

完整的步骤——Steps::

如果顺利完成,肯定最好,但大我数情况下,都会出些状况:

http://minuo.me
  • sudo apachectl start
  • sudo nano /etc/apache2/httpd.conf
  • remove # before #LoadModule php7…
  • sudo apachectl restart
  • sudo nano /etc/apache2/httpd.conf
  • Add index.php in DirectoryIndex line
  • sudo apachectl restart
  • sudo nano /Library/WebServer/Documents/index.php
  • download and install Mysql: https://dev.mysql.com/downloads/
  • SAVE YOUR PASSWORD!
  • sudo mkdir /var/mysql
  • sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock
  • Start mysql Server
  • cd /usr/local/mysql/bin
  • sudo ./mysql -u root -p
  • Alter user ’root’@‘localhost’ identified by ‘newpassword’;
  • Download phpmyadmin: https://www.phpmyadmin.net
  • Copy paste it into Documents folder and rename to phpMyAdmin
  • cd /Library/Webserver/Documents/
  • cd phpMyAdmin
  • sudo mkdir config
  • sudo chmod o+x config
  • open localhost/phpmyadmin
  • Under Authentication, enter mysql password
  • Download Config
  • Copy/Paste config into config folder
  • Enjoy

我在新的macbook pro上安装时遇到的状况:

1.命令行 输入mysql提示错误-bash: Export: command not found

ln -s  /usr/local/mysql/bin/mysql  /usr/bin

提示:ln: /usr/bin/mysql: Operation not permitted

sudo ln -s  /usr/local/mysql/bin/mysql  /usr/bin

提示:ln: /usr/bin/mysql: Operation not permitted

alias mysql=/usr/local/mysql/bin/mysql

$mysql -u root -p

输入密码,OK,成功。

2. mysqli.default_socket、pdo_mysql.default_socket的值(php.ini文件中)我这里没有用前面的步骤,我直接修改的。

在终端启动mysql,执行命令 STATUS;

使用UNIX socket的值,替换php.ini中2项的值

3.The server requested authentication method unknown to the client

这是由于新版本的mysql账号密码解锁机制不一致导致的

解决办法:

删除创建的用户和授权,

找到mysql配置文件并加入
 default_authentication_plugin=mysql_native_password
 变为原来的验证方式,然后从新创建用户并授权即可

mysql -uroot -p
use mysql;
 ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';

如何手动在CentOS 7 上部署LNMP环境(安装Nginx+MySQL+PHP)

接上文,今天是第3天,凭着印象继续巩固部署流程。

回顾三个步骤

  • 安装Nginx 1.12.2
  • 安装MySQL 5.7
  • 安装PHP 7.0.33

想想后面那么长的命令还是有点毛……

安装Nginx

1.运行命令yum -y install nginx安装Nginx。

2.运行命令nginx -v,查看所安装Nginx的版本号

3.返回结果为nginx version: nginx/1.12.2说明安装成功

安装MySQL

1.更新 yum 源。

rpm -Uvh  http://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm

2.运行命令yum -y install mysql-community-server安装MySQL。

3.运行命令mysql -V,查看所安装MySQL版本号

4. 返回mysql Ver 14.14 Distrib 5.7.28, for Linux (x86_64) using EditLine wrapper表明安装成功。

安装PHP

1.更新 yum 源(命令还是拷贝的)

# yum install -y http://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/ius-release-1.0-15.ius.centos7.noarch.rpm
# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

2.安装PHP

yum -y install php70w-devel php70w.x86_64 php70w-cli.x86_64 php70w-common.x86_64 php70w-gd.x86_64 php70w-ldap.x86_64 php70w-mbstring.x86_64 php70w-mcrypt.x86_64  php70w-pdo.x86_64   php70w-mysqlnd  php70w-fpm php70w-opcache php70w-pecl-redis php70w-pecl-mongo

3.运行命令php -v,查看安装的PHP版本信息,返回如下说明安装成功。

PHP 7.0.33 (cli) (built: Dec  6 2018 22:30:44) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
     with Zend OPcache v7.0.33, Copyright (c) 1999-2017, by Zend Technologies

这样算是把三个安装步骤回顾一遍,配置后续继续吧。

journalctl 简单介绍

在 journald 之前,每个服务的日志都由自己控制,输出在松散不同的地方,这给系统管理员带来了极大的不便。查询不同的服务日志,就得知道各自服务的日志路径,再加上每个服务日志的记录格式或风格等均有不同程度的差异。

journald的出现,就是提供一个中心化日志管理的方式,所有systemd管理的服务日志均记录到同一个地方,以同样的二进制格式记录相似的上下文信息格式。这样的好处就是对于查询来说,只需要用同样的命令,便可以根据需求附加不同的查询条件来返回所需要的日志信息。

作为 systemd 家族的一员,journalctl 命令被用作查询日志。它对应的守护进程是 journald,服务为 systemd-journald.service

一些日常使用实例

查询所有日志

# journalctl

-- Logs begin at 四 2019-07-11 11:10:15 CST, end at 二 2019-10-15 09:01:01 CST. --
10月 14 20:27:26 AliYun systemd[1]: Closed udev Kernel Socket.
10月 14 20:27:26 AliYun systemd[1]: Closed udev Control Socket.
10月 14 20:27:26 AliYun systemd[1]: Starting Cleanup udevd DB...
10月 14 20:27:26 AliYun systemd[1]: Started Cleanup udevd DB.
10月 14 20:27:26 AliYun systemd[1]: Reached target Switch Root.
10月 14 20:27:26 AliYun systemd[1]: Started Plymouth switch root service.
10月 14 20:27:26 AliYun systemd[1]: Starting Switch Root...
10月 14 20:27:26 AliYun systemd[1]: Switching root.
10月 14 20:27:26 AliYun systemd-journal[102]: Journal stopped

常用的一些选项:

  • 空格键: 显示下一页
  • b: 显示上一页
  • 向右键: 向右滚动 (由于 journalctl 显示的日志默认格式为一行一条日志,所以要想看到日志的所有字符,通常需要横向滚动)
  • 向左键: 向左滚动
  • g: 跳跃到整个日志的第一行
  • G: 跳跃到整个日志的最后一行
  • q: 退出

更多参考:如何使用Journalctl查看并操作Systemd日志
英文参考:How To Use Journalctl to View and Manipulate Systemd Logs by Justin Ellingwood

如何手动在CentOS 7 上部署LNMP环境(准备编译环境)

前几天瞎折腾,在阿里云上新购了一台ECS服务器,欲在手动搭建LNMP环境的同时给自己一个复习巩固linux常用命令的机会。

当然,少不了先看文档,然而“凑巧”翻到了手动部署LNMP环境(CentOS 7)这一章节,更新时间还是比较近的(2019-09-16 17:26:09),然一发不可收拾,直接看完,并顺利部署。

不管学习什么东西,要是先看答案,终感觉不对劲。

Minuo

到今天为止,已过2天,是时候不看答案复习一下了。

操作步骤

  1. 准备编译环境
  2. 安装Nginx
  3. 安装MySQL
  4. 安装PHP
  5. 配置Nginx
  6. 配置MySQL
  7. 配置PHP
  8. 测试部署结果

准备编译环境

  1. 连接Linux实例。
  2. 检查并关闭防火墙。
    1. 运行systemctl status firewalld命令查看防火墙运行状态
      • 如果状态参数为inactive,则防火墙是关闭状态。
      • 如果状态参数为active,则防火墙是开启状态。
    2. 关闭防火墙。
      • 临时关闭防火墙,运行命令systemctl stop firewalld
      • 永久关闭防火墙,运行命令systemctl disable firewalld
  3. 检查并关闭SElinux(一文彻底明白linux中的selinux到底是什么)。
    1. 运行getenforce命令查看SElinux运行状态。
      • 如果状态参数为disabled,则为关闭状态。
      • 如果状态参数为enforcing,则为开启状态。
    2. 关闭SElinux。
      • 临时关闭,运行命令setenforce 0
      • 永久关闭,运行命令vim /selinux/config编辑配置文件。把SELINUX=enforcing这一行,修改为SELINUX=disabled
    3. 重启系统,使设置生效。

CSS 去除图片元素底的空白

This “problem” persists because it’s not a bug. It’s just how the inline-formatting context works.

minuo.me

DIV+CSS排版时图片标签<img src="#">底部会出现空白,解决方法有很多,在此记录我常用的2个。

No.1 img {display: block;}
No.2 img {vertical-align: text-bottom[bottom,middle,top ... ];}

方法二在父元素也是inline元素的时候会影响到父元素的位置,所以我选择了方法代码少的方法一。

接下来,了解一下图片元素底部会出现空白的原因。

You’re seeing the space for descenders (the bits that hang off the bottom of ‘y’ and ‘p’) because img is an inline element by default.

robertc

CSS对inline 元素vertical-align属性有不同的规范值,用来设置元素的垂直对齐方式(所有浏览器都支持 vertical-align 属性)。

Note that vertical-align only applies to inline and table-cell elements: you can’t use it to vertically align block-level elements.

https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
常用值作用描述
baseline默认值。元素放置在父元素的基线上。
bottom将元素及其后代的底部与整行的底部对齐
text-bottom元素的底端与父元素字体的底端对齐。
middle元素放置在父元素的中部。
top将元素及其后代的顶部与整行的顶部对齐
text-top将元素的顶部与父元素的字体的顶部对齐。

查看实例:Example on codepen

其他更多参数请参考(https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align

Understanding Caching in WordPress, Part 3

In the previous two posts, I’ve talked about the basics of caching and how caching works in WordPress, at least to a degree.

Understanding Caching in WordPress
Understanding Caching in WordPress

But remember that this series was motivated by an email from someone who thought that I could do a better job of explaining how transients and caching work in WordPress and why it’s important to understand how everything works in tandem with each other.

Understanding Caching in WordPress
Understanding Caching in WordPress

So in this post, I’m aiming to bring it all together and talk about how the Transients API works in conjunction with MySQL, why it’s important to understand the relationship, and how to handle this moving forward.

How Do Transients Work in WordPress?

How Transients Work

First, according to the Codex, transients work like this:

This page contains the technical documentation of WordPress Transients API, which offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a time frame after which it will expire and be deleted.

Transients API via the WordPress Codex

The idea behind this seems simple enough, right?

  1. You save an option to the database,
  2. Set a time for how long it should exist,
  3. Then it’s stored for that amount of time
  4. And, if requested after expiration, is retrieved and moved back into its transient state.

So where lies the confusion?

As mentioned in the first post, I wasn’t clear about how long the transient information would be available. Rather than being a minimum amount of time the data will be available, it’s a maximum.

This means that if you set something to be available for a day, it will be available for a day. No less; no more. And after that time has expired, then it will have to be recreated into the transient state once again.

At least, this is the conventional wisdom behind it. It’s not wrong but there’s more to it. This is where it gets a bit more technical, though.

What Role Does MySQL Play?

As WordPress, hosting, and other technologies have matured, the underlying databases that power the application have changed, too. This isn’t a good thing or a bad thing (though perhaps we could argue it’s a good thing in a future post).

But it can help explain why transients work the way they do given the stack with which we’re used to working and how they may not work as expected with out database systems.

If you opt to use MySQL as the database for your WordPress installation, which I venture to say that most people still do, then the information that’s in the Options table (which is where transients are stored, too) then the Transients API will work as outlined above.

But what happens when you introduce other forms of caching like object caching through software like Memcached or Redis, and so on?

In that case, the data may not be available as you expect. In short, the caching software can choose to drop information that isn’t requested as often as other information. That is, it gives a level of priority to information that’s more frequently requested.

Moving Forward

When you take all of the above into account, you’re looking at several things:

  1. the Transients API,
  2. a database,
  3. a third-party caching system.

When you have the Transients API and a standard database, you’re going to be fine in that things will work as you expect.

But if you introduce a third-party caching system, the outcome may be different. Specifically, things may not – and likely will not – work in the way you expect.

That is, the third-party caching system can disregard whatever information it wants to drop whenever it thinks it needs to remove it. This means that whatever you think you may have available in cache won’t be there.

Ultimately, the best advice I can give is this:

  1. If you’re using MySQL and the Transients API, then things will work as described in Codex.
  2. If, on the other hand, you’re using another caching system, then it’s important to understand how it works and how you can write code against it so it works as you’d like.

And with that, there’s nothing more to add on this primer for understanding caching in WordPress.

Understanding Caching in WordPress, Part 2

In the previous post, I shared a basic primer for how database-backed applications – specifically WordPress – work without caching.

And before we talk about how basic caching works in WordPress, namely with the Transients API, it’s important to discuss the basic principles of caching. This includes why we do it, its benefits, and how it works.

Then we’ll get into how we can take advantage of basic facilities in WordPress to actually do this.

Understanding Caching in WordPress: Caching?

Why We Do It

Generally speaking, we do this to make sure our sites are fast. We know that speed plays a role how a page is ranked in search results. And though that may not be the primary reason, it’s an important reason.

Perhaps the simplest and best argument for caching is to have a fast site (or a performant site). And, in this context, this may mean a site or a web application.

Regardless, we know what it feels like when we’re sitting there waiting for a page or part of a page to load. If we don’t like it, why would we want our visitors to experience that?

Its Benefits

The benefits of caching come in at least two main areas:

  1. user experience,
  2. time to load.

In the last section, I said the benefits of caching can be felt if you’re a user. It’s something we’ve all experienced and, as developers, it’s something we can offer to our users through a variety of techniques.

But “time to load” is also something that matters and this is not just talking about the benefits of how long it takes for a user to load the site. Instead, it’s a bit more technical.

Recall in the previous post that a request – or a trip – starts from when the users requests information from the server and then the process goes from the user’s machine to the server to the database and back again.

Understanding Caching in WordPress

When we’ve introduced caching, we don’t have to do all of that. Instead, a trip is shortened because the data is actually kept somewhere else. And if the trip is shorter (and I don’t mean from the user’s computer to where the server is located in the world), then it should also be faster.

But how?

How It Works

There are numerous types of caching that are available but I’m keeping this particular series high-level. That is, I’m not going to distinguish between a browser cache, page cache, object cache, etc.

Perhaps in a future post. But, for now, I’m talking specifically about caching at a high-level.

Anyway, here’s how it works:

  1. During the first trip to a page, all of the information required to load the page is assembled.
  2. Rather than discarding it when the user leaves the site (or the page), the information is kept somewhere that’s easily accessible like the server’s memory.
  3. When the next user hits the page, the trip doesn’t have to go to the database to get all of the information, assemble it, and then return it to the user. Instead, it pulls the fully assembled information from the server’s memory (which is, in most cases) already faster, and then returns it to the user.
Understanding Caching in WordPress

There are plenty of caveats to consider when doing this such as customized user data, partial page loads, and so on, but the principle behind the trip remains the same.

WordPress Transients

So how does this work in WordPress? At the most fundamental level, the Transients API provides some basic functionality for this.

But it’s important to understand how it works and why it works the way it does. So in the next post in this series, I’m going to talk specifically about that.

Understanding Caching in WordPress, Part 1

Back in may, I wrote an article about using the WordPress Transients API. I summarize the article like this:

To simulate cookies and their feature of expiration, using WordPress transients may be a viable solution.

https://tommcfarlin.com/using-wordpress-transients/

Though the purpose of the article was to lay out a foundation for how we can design a class to work with the Transients API to simulate the behavior of cookies, one of the side effects of the article is that it didn’t do a good job of explaining how the Transients API (and, by proxy, how MySQL) works.

This was brought to my attention via email by David at UpDraft Plus.

So I thought it useful to talk about the concept of caching from a practical level, how it’s implemented in WordPress, then maybe look at we how to utilize plugins or newer technology to better power our sites and applications as well as have a better understanding.

Understanding Caching: The Basics

The concept of caching is relatively easy. But I think it’s best demonstrated by talking about data serialization and retrieval without caching, first.

Without Caching

Writing Data

Whenever you write information to the underlying database, you’re recording a record – or series of records – to the database.

For example, when you publish a post, you’re going to be writing a record to the table for posts and table for post metadata each of which are related by a post ID.

How they are related isn’t important for this post.

Instead, the thing to understand in this part is that when data is written to the database at least one record, if not multiple, is created.

Reading Data

When a visitor lands on the site to read that particular post, all of the information for said post will be request from the database, served to the WordPress application, and then rendered on the front-end.

Think of this entire process as a trip:

  1. ❓the visitor requests the page,
  2. 🔍 the web server identified what page to load,
  3. 📂 the page is requested from the database from multiple tables,
  4. 🏗 the data is assembled and sent to the core application,
  5. 🖥 the data is presented to the user.

So the trip starts when the user requests a page and ends when the information is presented to them in their browser.

It’s a Trip

And, without caching, this happens for every single user. That is, for each user that visits your site, a trip has to be made.

Understanding Caching in WordPress

That can get very expensive in terms of resource and time (especially depending on the size of your database).

But this is where caching can come into play.

Before Getting into Caching

The idea behind caching is to make this entire process faster. That is, if we know a trip is about to happen then we can keep the information in a place such that it’s already assembled and faster to retrieve.

Before talking about though, which I will in the next post, note that this is like making a trip to the hard disk of the server on which the site is hosted each time the site is visited.

Because, ultimately, the database, files, and all of the assets necessary to power the site reside on a hard disk. And yes, things like solid-state drives can make this process faster, it’s still not as optimal as possible.

And that’s where caching enters the picture. To better understand the Transients API, it’s important to understanding caching, which first requires a basic understanding how things work without caching.

It’s a Primer

So consider this a basic primer on how a database-backed site without caching works. And then we’ll build on this more in the next post.

Mac自带PHP+Apache环境中不显示错误信息的解决

近日因工作调整,重拾PHP的活,遂启用macbook的开发用途,采用mac自带Apache+PHP搭建本地环境,然发现在macbook自带的Apache+PHP环境中没有开启错误提示,这里提供一个解决方案:

首先,找到的环境中php.ini之所在,修改display_errorserror_reporting两项的值。

找到 display_errors = Off ,把Off 改为 On . 修改后为 display_errors = On ;

找到 error_reporting = E_ALL & ~E_NOTICE 或者error_reporting = E_ALL & ~E_DEPRECATED  改为 error_reporting = E_ALL | E_STRICT

其次,找到环境中的httpd.conf之所在,在文件的最后面加上下面代码以完善相应配置:

php_flag display_errors on
php_value error_reporting 2039

相关常识

Mac中的php.ini在哪里?

Mac OS X中没有默认的php.ini文件,其对应的模板文件php.ini.default,位于/private/etc/php.ini.default 或者是 /etc/php.ini/default ,可以自行拷贝一份进行修改。

sudo cp /private/etc/php.ini.default /private/etc/php.ini

MAC中默认的http.conf在哪里?

Mac OS X中的http.conf位于/etc/apache2/httpd.conf

Apache相关的运行命令:

sudo apachectl start  //开始
sudo apachectl stop  //停止
sudo apachectl restart  //重启

以root身份运行Homebrew非常危险,不再受支持

因为工作原因,近期重拾WordPress的相关工作,久未接触,而今发现Jetpack已如此强大,遂至Automattic一探究竟,然能力有限,耗时费力。

本地环境中需要使用Homebrew安装yarn,惯而采用$sudo brew install yarn进行安装,结果提示以下警告信息:

Error: Running Homebrew as root is extremely dangerous and no longer supported.As Homebrew does not drop privileges on installation you would be giving all build scripts full access to your system.

错误:以root身份运行Homebrew非常危险,不再受支持。由于Homebrew不会放弃安装特权,因此您需要为所有的构建脚本提供对系统的完全访问权限。

遂改为$ brew install yarn,然后出现如下提示:

Error: The following directories are not writable by your user:
/usr/local/share/man/man5
/usr/local/share/man/man7

并给出了解决方案:

  • 为用户目录赋予相应的权限
  • 确保该用户具备写权限

You should change the ownership of these directories to your user.

$ sudo chown -R $(whoami) /usr/local/share/man/man5 /usr/local/share/man/man7

And make sure that your user has write permission.

$ chmod u+w /usr/local/share/man/man5 /usr/local/share/man/man7

之后,再次运行$ brew install yarn命令,之后,Homebrew完成更新并顺利安装yarn

以上为个人学习中遇到的些许问题,留存以备忘。