其实服务端没什么好说,就是那几个字段,那就几个逻辑。后面我会贴出来,关键是要理解服务端开发整体的结构框架,其实对我所在公司这样的中小企业来说,最最核心部分还是服务端,其实对大公司也一样,但是大公司的 APP 动辄上百万甚至更多,对用户体验,客户端架构设计有着更高的要求。如果想做服务端,关键是 php 环境搭建。这里给大家介绍下我自己学习过程中的材料,不过多讲解,毕竟服务端我也半吊子,『师傅领进门,修行靠个人』。
我负责的项目服务端目前是基于Symfony2框架做的。
Symfony2官方文档:http://www.symfonychina.com/doc/current/setup.html
其实对一些刚入门服务端的朋友,看Symfony2官方文档还是有一些吃力的,这里介绍一个非常基础Symfony2框架视频教程:http://www.imooc.com/learn/244
这个教程也是刚踏坑时候看的,虽然不长,非常夯实基础,对Symfony2环境搭建,目录结构,路由,表单,模板引擎,数据库基础知识等等都有非常详细的解释。
另外我们在用的第三方管理后台sonata admin :http://www.newlifeclan.com/symfony/archives/520
bundle的github地址:https://github.com/sonata-project/SonataAdminBundle
理解了Symfony2框架,我们在看下我们开屏广告的服务端代码部分:
数据库表字段:
熟悉 Symfony2 都知道,Symfony2其实弱化了数据库操作的,数据表的创建不需要自己手动去添加。只要 php 生成好对象属性,数据表的构建,查询等等都是Symfony2去帮助我们完成的,我们只要以面向对象的方式去读写就 ok 了,这很牛逼。
下面我代码发一下吧 entity部分其实只有字段定义需要手动写,get set方法和Repository类调用app/console generate:doctrine:entities+entity 名称即可生成。
当然Repository里的业务逻辑需要自己添加。
之后调用:app/console doctrine:schema:update --dump-sql --force -C 会生成数据库表。(这也就Symfony2厉害的地方,开发者只用关心自己业务逻辑即可。)
MainAdver.php
<?php
/**
* Created by PhpStorm.
* User: apple
* Date: 16/1/25
* Time: 下午2:03
*/
namespace Wan\MainBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\HttpFoundation\File\UploadedFile;
/**
* MainAdver
*
* @ORM\Table(name="w_main_adver")
* @ORM\Entity(repositoryClass="Wan\MainBundle\Entity\MainAdverRepository")
*/
class MainAdver
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Title
* @var string
* @ORM\Column(name="title", type="string", length=150, nullable=false)
*/
private $title;
/**
* 活动状态
* @var integer
*
* @ORM\Column(name="type", type="integer")
* 0:已结束,1:安卓,2:IOS 3:全部
*/
protected $type = 1;
/**
*
* @var string
* @ORM\Column(name="pic", type="string", length=500, nullable=false)
*/
private $pic;
/**
*
* @var string
* @ORM\Column(name="link", type="string", length=1000, nullable=false)
*/
private $link;
private $file;
/**
*
* @var User
* @ORM\ManyToOne(targetEntity="Wan\UserBundle\Entity\User")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* 创建时间
* @Gedmo\Timestampable(on="create")
* @ORM\Column(name="created_at", type="datetime", nullable=false)
*/
private $createdAt;
/**
* @var \DateTime $updated
*
* @Gedmo\Timestampable(on="update")
* @ORM\Column(name="updated", type="datetime")
*/
private $updated;
/**
* 活动-开始
* @ORM\Column(name="start_at", type="datetime", nullable=true)
*/
private $startAt;
/**
* 活动-结束
* @ORM\Column(name="end_at", type="datetime", nullable=true)
*/
private $endAt;
/**
* 是否显示
* @var bool
*
* @ORM\Column(name="is_show", type="boolean",nullable=false, options={"default" = true})
*/
protected $isShow = true;
public function setFile(UploadedFile $file)
{
$this->file = $file;
return $this;
}
public function getFile()
{
return $this->file;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* @param string $title
* @return MainAdver
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set pic
*
* @param string $pic
* @return MainAdver
*/
public function setPic($pic)
{
$this->pic = $pic;
return $this;
}
/**
* Get pic
*
* @return string
*/
public function getPic()
{
return $this->pic;
}
/**
* Set createdAt
*
* @param \DateTime $createdAt
* @return MainAdver
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
/**
* Get createdAt
*
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Set updated
*
* @param \DateTime $updated
* @return MainAdver
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* @return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set startAt
*
* @param \DateTime $startAt
* @return MainAdver
*/
public function setStartAt($startAt)
{
$this->startAt = $startAt;
return $this;
}
/**
* Get startAt
*
* @return \DateTime
*/
public function getStartAt()
{
return $this->startAt;
}
/**
* Set endAt
*
* @param \DateTime $endAt
* @return MainAdver
*/
public function setEndAt($endAt)
{
$this->endAt = $endAt;
return $this;
}
/**
* Get endAt
*
* @return \DateTime
*/
public function getEndAt()
{
return $this->endAt;
}
/**
* Set isShow
*
* @param boolean $isShow
* @return MainAdver
*/
public function setIsShow($isShow)
{
$this->isShow = $isShow;
return $this;
}
/**
* Get isShow
*
* @return boolean
*/
public function getIsShow()
{
return $this->isShow;
}
/**
* Set user
*
* @param \Wan\UserBundle\Entity\User $user
* @return MainAdver
*/
public function setUser(\Wan\UserBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return \Wan\UserBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* 1 未开始 2 已开始 3已结束
* @return int
*/
public function getState()
{
$now = new \DateTime();
if ($now->getTimestamp() < $this->getStartAt()->getTimestamp()) {
return MainAdverRepository::STATUS_NO;
}
if ($now->getTimestamp() < $this->getEndAt()->getTimestamp()) {
return MainAdverRepository::STATUS_ING;
}
return MainAdverRepository::STATUS_ED;
}
/**
* @return int
*/
public function getType()
{
return $this->type;
}
/**
* @param int $type
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return string
*/
public function getLink()
{
return $this->link;
}
/**
* @param string $link
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* 状态描述
* @return mixed
*/
public function getStateDescribe()
{
return MainAdverRepository::$STATUS[$this->getState()];
}
public function getTypeDecribe()
{
return MainAdverRepository::$TYPE[$this->getType()];
}
}
Repository:
<?php
namespace Wan\MainBundle\Entity;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Wan\CommonBundle\Classes\MainClass;
use Wan\CommonBundle\Core\WanEntityRepository;
use Wan\CommonBundle\Utils\QArray2;
use Wan\Lib\SiteUtils;
/**
* MainAdverRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class MainAdverRepository extends WanEntityRepository
{
const STATUS_ALL = 1;
const STATUS_NO = 2;
const STATUS_ING = 3;
const STATUS_ED = 4;
public static $STATUS = array(
self::STATUS_ALL => '全部',
self::STATUS_NO => '未开始',
self::STATUS_ING => '进行中',
self::STATUS_ED => '已结束'
);
const TYPE_ANDROID = 1;
const TYPE_IOS = 2;
const TYPE_ALL = 3;
public static $TYPE = array(
self::TYPE_ANDROID => '安卓',
self::TYPE_IOS => 'IOS',
self::TYPE_ALL => '全部',
);
protected function queryByType($type, array $critical = array(), array $options = array())
{
$qb = $this->createQueryBuilder('E');
if (!isset($options['orderby'])) {
$options['orderby'] = array('updated DESC');
}
$typeArray = array();
$typeArray[] = self::TYPE_ALL;
$typeArray[] = $type;
$strSubs = implode(",", $typeArray);
$qb->andWhere("E.type in ({$strSubs})");
$this->applyOptions($qb, 'E', $options);
$this->appendSimpleCritical($qb, 'E', $critical);
$this->appendSimpleOrder($qb, 'E', $options['orderby']);
return $qb;
}
private function applyOptions(QueryBuilder $builder, $alias, array $options)
{
$now = new \DateTime();
$nowFormat = $now->format("Y-m-d H:i:s");
$builder->andWhere("E.startAt < '{$nowFormat}' and E.endAt > '{$nowFormat}'");
$builder->andWhere("E.isShow = 1");
}
public function toApiValue($doc)
{
if (!$doc || !$doc instanceof MainAdver) {
return array();
}
$ret = array(
"id" => $doc->getId(),
'pic' => $doc->getPic() ?: '',
'link' => (string)$doc->getLink(),
"endtime" => $doc->getEndAt()->getTimestamp(),
);
return $ret;
}
}
这里我们的Repository 是继承 WanEntityRepository WanEntityRepository又继承EntityRepository,我们在WanEntityRepository做了一些自己的结构封装。
Ctroller 里的查询方法:
$repAdver = $em->getRepository("WanMainBundle:MainAdver");
$adverDate = array();
$advers = $repAdver->findByType($type, array(), ["limit" => 1]);
foreach ($advers as $val) {
$adverDate[] = $repAdver->toApiValue($val);
}
接口返回给$adverDate给客户端即可,这里我就不放出 sonata admin 里的部分代码,想了解朋友去看下sonata admin 管理后台如何配置和创建。
其实,php 服务端的部分业务和功能都没什么好说,根本还是要对Symfony2有升入了解。
另外介绍另外一个 PHP 框架:laravel :http://www.golaravel.com
这个我也没看过,等我看了可以再来介绍下。