Skip to content

Instantly share code, notes, and snippets.

@khoatran
Last active May 20, 2016 09:08
Show Gist options
  • Save khoatran/45e0a54ce546d673d4d4 to your computer and use it in GitHub Desktop.
Save khoatran/45e0a54ce546d673d4d4 to your computer and use it in GitHub Desktop.
A custom Eloquent model from Jenssegers\Mongodb to solve serialisation issue of new MongoDriver
<?php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use LaunchCMS\Utils\SerializeUtil;
abstract class LaunchEloquentModel extends Eloquent implements \Serializable
{
protected $connection = 'mongodb';
protected $array_fields = [];
public function serialize()
{
return SerializeUtil::serialize($this->attributes);
}
public function unserialize($serialized)
{
$data = SerializeUtil::unserialize($serialized);
foreach($data as $key => $value) {
$this->setAttribute($key, $value);
}
$this->exists = isset($this->attributes['_id']) && !empty($this->attributes['_id']);
}
}
<?php
class DateUtil
{
/**
* Return a timestamp as DateTime object.
*
* @param mixed $value
* @return \Carbon\Carbon
*/
public static function asDateTime($value, $dateFormat = 'Y-m-d H:i:s')
{
if ($value == null) {
return null;
}
// Convert UTCDateTime instances.
if ($value instanceof UTCDateTime) {
return Carbon::createFromTimestamp($value->toDateTime()->getTimestamp());
}
// If this value is already a Carbon instance, we shall just return it as is.
// This prevents us having to reinstantiate a Carbon instance when we know
// it already is one, which wouldn't be fulfilled by the DateTime check.
if ($value instanceof Carbon) {
return $value;
}
// If the value is already a DateTime instance, we will just skip the rest of
// these checks since they will be a waste of time, and hinder performance
// when checking the field. We will just return the DateTime right away.
if ($value instanceof DateTime) {
return Carbon::instance($value);
}
// If this value is an integer, we will assume it is a UNIX timestamp's value
// and format a Carbon object from this timestamp. This allows flexibility
// when defining your date fields as they might be UNIX timestamps here.
if (is_numeric($value)) {
return Carbon::createFromTimestamp($value);
}
// If the value is in simply year, month, day format, we will instantiate the
// Carbon instances from that format. Again, this provides for simple date
// fields on the database, while still supporting Carbonized conversion.
if (preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $value)) {
return Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
}
// Finally, we will just assume this date is in the format used by default on
// the database connection and use that format to create the Carbon object
// that is returned back out to the developers after we convert it here.
return Carbon::createFromFormat($dateFormat, $value);
}
/**
* Return a timestamp as unix timestamp.
*
* @param mixed $value
* @return int
*/
public static function asTimeStamp($value, $dateFormat = 'Y-m-d H:i:s')
{
if ($value == null) {
return $value;
}
return (int) self::asDateTime($value, $dateFormat)->timestamp;
}
/**
* Convert a DateTime to a storable UTCDateTime object.
*
* @param DateTime|int $value
* @return UTCDateTime
*/
public static function fromDateTime($value)
{
if ($value == null) {
return null;
}
// If the value is already a UTCDateTime instance, we don't need to parse it.
if ($value instanceof UTCDateTime) {
return $value;
}
if ( !$value instanceof DateTime) {
$value = self::asDateTime($value);
}
return new UTCDateTime($value->getTimestamp() * 1000);
}
public static function formatDateToIndexedFormat(Carbon $date)
{
return $date->toDateString();
}
public static function formatDateTimeToIndexedFormat(Carbon $date)
{
return $date->format('Y-m-d H:i:s');
}
}
<?php
class SerializeUtil
{
/**
* Check value to find if it was serialized.
* If $data is not an string, then returned value will always be false.
* Serialized data is always a string.
*
*
* @param string $data Value to check to see if was serialized.
* @param bool $strict Optional. Whether to be strict about the end of the string. Default true.
* @return bool False if not serialized and true if it was.
*/
public static function is_serialized( $data) {
// if it isn't a string, it isn't serialized.
if ( ! is_string( $data ) ) {
return false;
}
//this piece of code is for checking boolean value. In case of boolean, unserialize return false - which causing wrong.
//So, this trick is used to pass by that case.
if(strlen($data) ===4 && preg_match('/b:\d;/', $data)) {
return true;
}
if (@unserialize($data) === false)
{
return false;
}
return true;
}
public static function serialize($object) {
if(is_array($object)) {
return self::serializeArray($object);
}
if($object instanceof UTCDatetime) {
return serialize(DateUtil::asDateTime($object));
}
if($object instanceof ObjectID) {
return serialize((string) $object);
}
return serialize($object);
}
public static function serializeArray($array) {
$dataToSerialize = [];
foreach($array as $key => $value) {
if(is_array($value)) {
$dataToSerialize[$key] = self::serializeArray($value);
}
else if($value instanceof UTCDatetime) {
$dataToSerialize[$key] = DateUtil::asDateTime($value);
}
else if($value instanceof ObjectID) {
$dataToSerialize[$key] = (string) $value;
}
else {
$dataToSerialize[$key] = $value;
}
}
return serialize($dataToSerialize);
}
public static function unserialize($serialized)
{
if(is_array($serialized)) {
return self::unserializeArray($serialized);
}
else if(is_string($serialized) && self::is_serialized($serialized)) {
$unserializedData = unserialize($serialized);
if(is_array($unserializedData)) {
return self::unserializeArray($unserializedData);
} else if(self::is_serialized($unserializedData)) {
return self::unserialize($unserializedData);
}
return $unserializedData;
}
return $serialized;
}
public static function unserializeArray(array $arrayData) {
$arrayAfterUnserializing = [];
foreach($arrayData as $key => $arrayElement) {
if($key === '_id') {
$arrayAfterUnserializing[$key] = new ObjectID(self::unserialize($arrayElement));
} else {
$arrayAfterUnserializing[$key] = self::unserialize($arrayElement);
}
}
return $arrayAfterUnserializing;
}
}
@ebisbe
Copy link

ebisbe commented May 9, 2016

Hello @khoatran,

Can you add DateUtil class? I have it working but wihtout saving the dates. There is a small error. _id can be a string and there fore will throw and invalid Bson Id.

Thanks for this gist

@khoatran
Copy link
Author

@ebisbe: sorry, I was in a business trip recently. I don't see your comment. I added the DateUtil class for you to refer. Actually, you can find most of those functions inside the core of eloquent. I just move it to the DateUtil class for specific purpose of my project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment