GitHub
Tests: 12 • Commercial: 2 • Pet projects: 4 • Legacy: 4
Total: 22

.NET Framework

Test
2021

Project Request

ASP.NET MVC • C# • SQL Server
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2020

ProjectC

ASP.NET MVC • C# • JSON • jQuery
JSON data processing.
Test
2020

Vehicle Maintenance

ASP.NET MVC • VB.NET • JSON
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2019

Movie Navigator

ASP.NET MVC • VB.NET
Request information about movie from IMDB.
Test
2018

Customers Exchange

ASP.NET MVC • C# • SQL Server
Automated teller machine emulation.
Test
2016

ATM

ASP.NET MVC • C#
Automated teller machine emulation.

.NET Core

Pet project
2022

Mail Daemon

.NET 8 • Console • JSON
Utility to send mails with customizable settings.

Custom

Code
2024

Buns of code

.NET Framework • C# • JavaScript
Code snippets from my projects, ready to use; tiny tests; code examples.

PHP

Test
2024

Mediabox

PHP 8 • Laravel 11 • Vue.js • Composer • SQLite
Test project for media files management.
Test
2020

Loan Castle

PHP • MariaDB
Jums jāizstrādā kāda lielāk projekta prototips. Izstrādājot prototipu, paturiet prātā, ka projektam attīstoties, šo prototipu varētu vajadzēt pilnveidot.
Test
2020

Content Management

PHP • MySQL • AJAX
Создать простой сайт, где будет страница с формой для авторизации и страница для авторизованного пользователя.
Test
2019

Laravel

PHP • Laravel • Vue.js • Composer • SQLite
Izveidot aplikāciju, kura ik pēc noteikta intervāla (60 sekundes) veic ierakstu datubāzē izmantojot Laravel freimworka iebūvēto funkcionalitāti.
Test
2019

Phone Check

PHP • JavaScript • JSON • Docker
Implement application to detect country by phone number.

Frontend

Test
2021

Forex Wall

npm • React
For this exercise, what we need is a simple live wall for tracking currencies.

Business projects

Commercial
2008

Certification Center

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Dapper • JavaScript • jQuery • Git
Transport registration and certification services in Latvia, Customer Relationship Management.
Commercial
2000

Amerikas Auto

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Entity Framework • JavaScript • jQuery • Git
Car service and spare parts for all USA and European car models, Customer Relationship Management.

Pet projects

Pet project
2023

Geolocation Assistant

.NET 8 • ASP.NET Core • C# • Web API • JSON • Git
Website for determining geolocation by IP or geotagged photo.
Pet project
2008

Web Dynamics

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
Software development blog. Articles, books, videos, content management.
Pet project
2000

Blackball

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • XML • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
My entertainment portal created from scratch.

Good old times

Legacy
2000

DOS Clock

Turbo Pascal • Assembler
Digital clock.
Legacy
2000

BrainOut

Turbo Pascal • Assembler
Tank battle game.
Legacy
1999

Airport Administrator

Turbo Pascal
Курсовая работа в институте.
Legacy
1998

Atomizer

Turbo Pascal • Assembler
Atomizer, aka «Studio2D». Graphic raster editor. AGI is my own «Atomizer Generated Image» file format.

Laravel

2019 Test

Izveidot aplikāciju, kura ik pēc noteikta intervāla (60 sekundes) veic ierakstu datubāzē izmantojot Laravel freimworka iebūvēto funkcionalitāti.

PHP Laravel Vue.js Composer SQLite
Information
Source code
  app
  Http
  Auth
  css
  js
  js
  lang
  en
  sass
  app
  data
  logs
  Unit
  src
  src
  lib
  docs
  en
  src
  docs
  en
  lib
  src
  Cron
  Cron
  src
  filp
  src
  css
  js
  Util
  src
  ORM
  Spot
  test
  Core
  Text
  Type
  Xml
  Core
  Text
  Type
  Xml
  html
  src
  src
  src
  Auth
  make
  auth
  Bus
  Auth
  Bus
  Http
  Mail
  View
  Auth
  Bus
  Http
  Http
  Json
  Log
  Mail
  html
  text
  Jobs
  View
  src
  src
  Util
  docs
  Pass
  Pass
  Pass
  doc
  src
  Curl
  doc
  f001
  f002
  f003
  f004
  f005
  f006
  f007
  f008
  src
  Date
  Spl
  src
  Lang
  List
  doc
  lib
  Node
  Expr
  Cast
  Name
  Stmt
  test
  code
  expr
  uvs
  stmt
  loop
  expr
  stmt
  Node
  Stmt
  src
  opis
  src
  dist
  lib
  src
  xml
  xml
  src
  Unit
  src
  src
  Tags
  src
  src
  src
  Call
  Node
  Call
  Util
  src
  Node
  Html
  css
  js
  Xml
  HTML
  XML
  src
  src
  src
  src
  src
  Stub
  Hook
  Util
  Log
  PHP
  cli
  1149
  1216
  1265
  1330
  1335
  1337
  1348
  1351
  1374
  1437
  1468
  1471
  1472
  1570
  2085
  2137
  2145
  2158
  2366
  2380
  2382
  2435
  244
  2448
  2724
  2725
  2731
  2811
  2830
  2972
  3093
  3107
  3156
  322
  3364
  3379
  3380
  3396
  433
  445
  498
  503
  581
  74
  765
  797
  873
  Trac
  1021
  523
  578
  684
  783
  fail
  unit
  Util
  PHP
  psr
  src
  log
  Psr
  Log
  Test
  src
  psy
  src
  Sudo
  Util
  test
  Sudo
  Util
  box
  uuid
  src
  Time
  Node
  Time
  src
  src
  diff
  src
  out
  src
  src
  src
  src
  src
  src
  src
  src
  doc
  lib
  Mime
  Pop
  Auth
  Mime
  bug
  unit
  Mime
  Auth
  dkim
  Node
  Node
  psr4
  phpt
  .dot
  b
  a
  A
  B
  C
  copy
  A
  B
  C
  one
  b
  .dot
  a
  dir
  File
  Test
  File
  test
  Test
  Log
  Log
  mime
  Part
  test
  Part
  glob
  Test
  data
  dat
  res
  Util
  Util
  Test
  css
  js
  Test
  Test
  src
  src
  Css
  Rule
  src
  src
  .env
  null
Root / vendor / laravel / framework / src / Illuminate / Database / Eloquent / Concerns / HasAttributes.php
<?php namespace Illuminate\Database\Eloquent\Concerns; use LogicException; use DateTimeInterface; use Carbon\CarbonInterface; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Date; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Collection as BaseCollection; use Illuminate\Database\Eloquent\JsonEncodingException; trait HasAttributes { /** * The model's attributes. * * @var array */ protected $attributes = []; /** * The model attribute's original state. * * @var array */ protected $original = []; /** * The changed model attributes. * * @var array */ protected $changes = []; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = []; /** * The attributes that should be mutated to dates. * * @var array */ protected $dates = []; /** * The storage format of the model's date columns. * * @var string */ protected $dateFormat; /** * The accessors to append to the model's array form. * * @var array */ protected $appends = []; /** * Indicates whether attributes are snake cased on arrays. * * @var bool */ public static $snakeAttributes = true; /** * The cache of the mutated attributes for each class. * * @var array */ protected static $mutatorCache = []; /** * Convert the model's attributes to an array. * * @return array */ public function attributesToArray() { // If an attribute is a date, we will cast it to a string after converting it // to a DateTime / Carbon instance. This is so we will get some consistent // formatting while accessing attributes vs. arraying / JSONing a model. $attributes = $this->addDateAttributesToArray( $attributes = $this->getArrayableAttributes() ); $attributes = $this->addMutatedAttributesToArray( $attributes, $mutatedAttributes = $this->getMutatedAttributes() ); // Next we will handle any casts that have been setup for this model and cast // the values to their appropriate type. If the attribute has a mutator we // will not perform the cast on those attributes to avoid any confusion. $attributes = $this->addCastAttributesToArray( $attributes, $mutatedAttributes ); // Here we will grab all of the appended, calculated attributes to this model // as these attributes are not really in the attributes array, but are run // when we need to array or JSON the model for convenience to the coder. foreach ($this->getArrayableAppends() as $key) { $attributes[$key] = $this->mutateAttributeForArray($key, null); } return $attributes; } /** * Add the date attributes to the attributes array. * * @param array $attributes * @return array */ protected function addDateAttributesToArray(array $attributes) { foreach ($this->getDates() as $key) { if (! isset($attributes[$key])) { continue; } $attributes[$key] = $this->serializeDate( $this->asDateTime($attributes[$key]) ); } return $attributes; } /** * Add the mutated attributes to the attributes array. * * @param array $attributes * @param array $mutatedAttributes * @return array */ protected function addMutatedAttributesToArray(array $attributes, array $mutatedAttributes) { foreach ($mutatedAttributes as $key) { // We want to spin through all the mutated attributes for this model and call // the mutator for the attribute. We cache off every mutated attributes so // we don't have to constantly check on attributes that actually change. if (! array_key_exists($key, $attributes)) { continue; } // Next, we will call the mutator for this attribute so that we can get these // mutated attribute's actual values. After we finish mutating each of the // attributes we will return this final array of the mutated attributes. $attributes[$key] = $this->mutateAttributeForArray( $key, $attributes[$key] ); } return $attributes; } /** * Add the casted attributes to the attributes array. * * @param array $attributes * @param array $mutatedAttributes * @return array */ protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes) { foreach ($this->getCasts() as $key => $value) { if (! array_key_exists($key, $attributes) || in_array($key, $mutatedAttributes)) { continue; } // Here we will cast the attribute. Then, if the cast is a date or datetime cast // then we will serialize the date for the array. This will convert the dates // to strings based on the date format specified for these Eloquent models. $attributes[$key] = $this->castAttribute( $key, $attributes[$key] ); // If the attribute cast was a date or a datetime, we will serialize the date as // a string. This allows the developers to customize how dates are serialized // into an array without affecting how they are persisted into the storage. if ($attributes[$key] && ($value === 'date' || $value === 'datetime')) { $attributes[$key] = $this->serializeDate($attributes[$key]); } if ($attributes[$key] && $this->isCustomDateTimeCast($value)) { $attributes[$key] = $attributes[$key]->format(explode(':', $value, 2)[1]); } } return $attributes; } /** * Get an attribute array of all arrayable attributes. * * @return array */ protected function getArrayableAttributes() { return $this->getArrayableItems($this->attributes); } /** * Get all of the appendable values that are arrayable. * * @return array */ protected function getArrayableAppends() { if (! count($this->appends)) { return []; } return $this->getArrayableItems( array_combine($this->appends, $this->appends) ); } /** * Get the model's relationships in array form. * * @return array */ public function relationsToArray() { $attributes = []; foreach ($this->getArrayableRelations() as $key => $value) { // If the values implements the Arrayable interface we can just call this // toArray method on the instances which will convert both models and // collections to their proper array form and we'll set the values. if ($value instanceof Arrayable) { $relation = $value->toArray(); } // If the value is null, we'll still go ahead and set it in this list of // attributes since null is used to represent empty relationships if // if it a has one or belongs to type relationships on the models. elseif (is_null($value)) { $relation = $value; } // If the relationships snake-casing is enabled, we will snake case this // key so that the relation attribute is snake cased in this returned // array to the developers, making this consistent with attributes. if (static::$snakeAttributes) { $key = Str::snake($key); } // If the relation value has been set, we will set it on this attributes // list for returning. If it was not arrayable or null, we'll not set // the value on the array because it is some type of invalid value. if (isset($relation) || is_null($value)) { $attributes[$key] = $relation; } unset($relation); } return $attributes; } /** * Get an attribute array of all arrayable relations. * * @return array */ protected function getArrayableRelations() { return $this->getArrayableItems($this->relations); } /** * Get an attribute array of all arrayable values. * * @param array $values * @return array */ protected function getArrayableItems(array $values) { if (count($this->getVisible()) > 0) { $values = array_intersect_key($values, array_flip($this->getVisible())); } if (count($this->getHidden()) > 0) { $values = array_diff_key($values, array_flip($this->getHidden())); } return $values; } /** * Get an attribute from the model. * * @param string $key * @return mixed */ public function getAttribute($key) { if (! $key) { return; } // If the attribute exists in the attribute array or has a "get" mutator we will // get the attribute's value. Otherwise, we will proceed as if the developers // are asking for a relationship's value. This covers both types of values. if (array_key_exists($key, $this->attributes) || $this->hasGetMutator($key)) { return $this->getAttributeValue($key); } // Here we will determine if the model base class itself contains this given key // since we don't want to treat any of those methods as relationships because // they are all intended as helper methods and none of these are relations. if (method_exists(self::class, $key)) { return; } return $this->getRelationValue($key); } /** * Get a plain attribute (not a relationship). * * @param string $key * @return mixed */ public function getAttributeValue($key) { $value = $this->getAttributeFromArray($key); // If the attribute has a get mutator, we will call that then return what // it returns as the value, which is useful for transforming values on // retrieval from the model to a form that is more useful for usage. if ($this->hasGetMutator($key)) { return $this->mutateAttribute($key, $value); } // If the attribute exists within the cast array, we will convert it to // an appropriate native PHP type dependant upon the associated value // given with the key in the pair. Dayle made this comment line up. if ($this->hasCast($key)) { return $this->castAttribute($key, $value); } // If the attribute is listed as a date, we will convert it to a DateTime // instance on retrieval, which makes it quite convenient to work with // date fields without having to create a mutator for each property. if (in_array($key, $this->getDates()) && ! is_null($value)) { return $this->asDateTime($value); } return $value; } /** * Get an attribute from the $attributes array. * * @param string $key * @return mixed */ protected function getAttributeFromArray($key) { if (isset($this->attributes[$key])) { return $this->attributes[$key]; } } /** * Get a relationship. * * @param string $key * @return mixed */ public function getRelationValue($key) { // If the key already exists in the relationships array, it just means the // relationship has already been loaded, so we'll just return it out of // here because there is no need to query within the relations twice. if ($this->relationLoaded($key)) { return $this->relations[$key]; } // If the "attribute" exists as a method on the model, we will just assume // it is a relationship and will load and return results from the query // and hydrate the relationship's value on the "relationships" array. if (method_exists($this, $key)) { return $this->getRelationshipFromMethod($key); } } /** * Get a relationship value from a method. * * @param string $method * @return mixed * * @throws \LogicException */ protected function getRelationshipFromMethod($method) { $relation = $this->$method(); if (! $relation instanceof Relation) { if (is_null($relation)) { throw new LogicException(sprintf( '%s::%s must return a relationship instance, but "null" was returned. Was the "return" keyword used?', static::class, $method )); } throw new LogicException(sprintf( '%s::%s must return a relationship instance.', static::class, $method )); } return tap($relation->getResults(), function ($results) use ($method) { $this->setRelation($method, $results); }); } /** * Determine if a get mutator exists for an attribute. * * @param string $key * @return bool */ public function hasGetMutator($key) { return method_exists($this, 'get'.Str::studly($key).'Attribute'); } /** * Get the value of an attribute using its mutator. * * @param string $key * @param mixed $value * @return mixed */ protected function mutateAttribute($key, $value) { return $this->{'get'.Str::studly($key).'Attribute'}($value); } /** * Get the value of an attribute using its mutator for array conversion. * * @param string $key * @param mixed $value * @return mixed */ protected function mutateAttributeForArray($key, $value) { $value = $this->mutateAttribute($key, $value); return $value instanceof Arrayable ? $value->toArray() : $value; } /** * Cast an attribute to a native PHP type. * * @param string $key * @param mixed $value * @return mixed */ protected function castAttribute($key, $value) { if (is_null($value)) { return $value; } switch ($this->getCastType($key)) { case 'int': case 'integer': return (int) $value; case 'real': case 'float': case 'double': return $this->fromFloat($value); case 'decimal': return $this->asDecimal($value, explode(':', $this->getCasts()[$key], 2)[1]); case 'string': return (string) $value; case 'bool': case 'boolean': return (bool) $value; case 'object': return $this->fromJson($value, true); case 'array': case 'json': return $this->fromJson($value); case 'collection': return new BaseCollection($this->fromJson($value)); case 'date': return $this->asDate($value); case 'datetime': case 'custom_datetime': return $this->asDateTime($value); case 'timestamp': return $this->asTimestamp($value); default: return $value; } } /** * Get the type of cast for a model attribute. * * @param string $key * @return string */ protected function getCastType($key) { if ($this->isCustomDateTimeCast($this->getCasts()[$key])) { return 'custom_datetime'; } if ($this->isDecimalCast($this->getCasts()[$key])) { return 'decimal'; } return trim(strtolower($this->getCasts()[$key])); } /** * Determine if the cast type is a custom date time cast. * * @param string $cast * @return bool */ protected function isCustomDateTimeCast($cast) { return strncmp($cast, 'date:', 5) === 0 || strncmp($cast, 'datetime:', 9) === 0; } /** * Determine if the cast type is a decimal cast. * * @param string $cast * @return bool */ protected function isDecimalCast($cast) { return strncmp($cast, 'decimal:', 8) === 0; } /** * Set a given attribute on the model. * * @param string $key * @param mixed $value * @return mixed */ public function setAttribute($key, $value) { // First we will check for the presence of a mutator for the set operation // which simply lets the developers tweak the attribute as it is set on // the model, such as "json_encoding" an listing of data for storage. if ($this->hasSetMutator($key)) { return $this->setMutatedAttributeValue($key, $value); } // If an attribute is listed as a "date", we'll convert it from a DateTime // instance into a form proper for storage on the database tables using // the connection grammar's date format. We will auto set the values. elseif ($value && $this->isDateAttribute($key)) { $value = $this->fromDateTime($value); } if ($this->isJsonCastable($key) && ! is_null($value)) { $value = $this->castAttributeAsJson($key, $value); } // If this attribute contains a JSON ->, we'll set the proper value in the // attribute's underlying array. This takes care of properly nesting an // attribute in the array's value in the case of deeply nested items. if (Str::contains($key, '->')) { return $this->fillJsonAttribute($key, $value); } $this->attributes[$key] = $value; return $this; } /** * Determine if a set mutator exists for an attribute. * * @param string $key * @return bool */ public function hasSetMutator($key) { return method_exists($this, 'set'.Str::studly($key).'Attribute'); } /** * Set the value of an attribute using its mutator. * * @param string $key * @param mixed $value * @return mixed */ protected function setMutatedAttributeValue($key, $value) { return $this->{'set'.Str::studly($key).'Attribute'}($value); } /** * Determine if the given attribute is a date or date castable. * * @param string $key * @return bool */ protected function isDateAttribute($key) { return in_array($key, $this->getDates()) || $this->isDateCastable($key); } /** * Set a given JSON attribute on the model. * * @param string $key * @param mixed $value * @return $this */ public function fillJsonAttribute($key, $value) { [$key, $path] = explode('->', $key, 2); $this->attributes[$key] = $this->asJson($this->getArrayAttributeWithValue( $path, $key, $value )); return $this; } /** * Get an array attribute with the given key and value set. * * @param string $path * @param string $key * @param mixed $value * @return $this */ protected function getArrayAttributeWithValue($path, $key, $value) { return tap($this->getArrayAttributeByKey($key), function (&$array) use ($path, $value) { Arr::set($array, str_replace('->', '.', $path), $value); }); } /** * Get an array attribute or return an empty array if it is not set. * * @param string $key * @return array */ protected function getArrayAttributeByKey($key) { return isset($this->attributes[$key]) ? $this->fromJson($this->attributes[$key]) : []; } /** * Cast the given attribute to JSON. * * @param string $key * @param mixed $value * @return string */ protected function castAttributeAsJson($key, $value) { $value = $this->asJson($value); if ($value === false) { throw JsonEncodingException::forAttribute( $this, $key, json_last_error_msg() ); } return $value; } /** * Encode the given value as JSON. * * @param mixed $value * @return string */ protected function asJson($value) { return json_encode($value); } /** * Decode the given JSON back into an array or object. * * @param string $value * @param bool $asObject * @return mixed */ public function fromJson($value, $asObject = false) { return json_decode($value, ! $asObject); } /** * Decode the given float. * * @param mixed $value * @return mixed */ public function fromFloat($value) { switch ((string) $value) { case 'Infinity': return INF; case '-Infinity': return -INF; case 'NaN': return NAN; default: return (float) $value; } } /** * Return a decimal as string. * * @param float $value * @param int $decimals * @return string */ protected function asDecimal($value, $decimals) { return number_format($value, $decimals, '.', ''); } /** * Return a timestamp as DateTime object with time set to 00:00:00. * * @param mixed $value * @return \Illuminate\Support\Carbon */ protected function asDate($value) { return $this->asDateTime($value)->startOfDay(); } /** * Return a timestamp as DateTime object. * * @param mixed $value * @return \Illuminate\Support\Carbon */ protected function asDateTime($value) { // If this value is already a Carbon instance, we shall just return it as is. // This prevents us having to re-instantiate a Carbon instance when we know // it already is one, which wouldn't be fulfilled by the DateTime check. if ($value instanceof Carbon || $value instanceof CarbonInterface) { return Date::instance($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 DateTimeInterface) { return Date::parse( $value->format('Y-m-d H:i:s.u'), $value->getTimezone() ); } // 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 Date::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 ($this->isStandardDateFormat($value)) { return Date::instance(Carbon::createFromFormat('Y-m-d', $value)->startOfDay()); } $format = $this->getDateFormat(); // https://bugs.php.net/bug.php?id=75577 if (version_compare(PHP_VERSION, '7.3.0-dev', '<')) { $format = str_replace('.v', '.u', $format); } // 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 Date::createFromFormat($format, $value); } /** * Determine if the given value is a standard date format. * * @param string $value * @return bool */ protected function isStandardDateFormat($value) { return preg_match('/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $value); } /** * Convert a DateTime to a storable string. * * @param mixed $value * @return string|null */ public function fromDateTime($value) { return empty($value) ? $value : $this->asDateTime($value)->format( $this->getDateFormat() ); } /** * Return a timestamp as unix timestamp. * * @param mixed $value * @return int */ protected function asTimestamp($value) { return $this->asDateTime($value)->getTimestamp(); } /** * Prepare a date for array / JSON serialization. * * @param \DateTimeInterface $date * @return string */ protected function serializeDate(DateTimeInterface $date) { return $date->format($this->getDateFormat()); } /** * Get the attributes that should be converted to dates. * * @return array */ public function getDates() { $defaults = [static::CREATED_AT, static::UPDATED_AT]; return $this->usesTimestamps() ? array_unique(array_merge($this->dates, $defaults)) : $this->dates; } /** * Get the format for database stored dates. * * @return string */ public function getDateFormat() { return $this->dateFormat ?: $this->getConnection()->getQueryGrammar()->getDateFormat(); } /** * Set the date format used by the model. * * @param string $format * @return $this */ public function setDateFormat($format) { $this->dateFormat = $format; return $this; } /** * Determine whether an attribute should be cast to a native type. * * @param string $key * @param array|string|null $types * @return bool */ public function hasCast($key, $types = null) { if (array_key_exists($key, $this->getCasts())) { return $types ? in_array($this->getCastType($key), (array) $types, true) : true; } return false; } /** * Get the casts array. * * @return array */ public function getCasts() { if ($this->getIncrementing()) { return array_merge([$this->getKeyName() => $this->getKeyType()], $this->casts); } return $this->casts; } /** * Determine whether a value is Date / DateTime castable for inbound manipulation. * * @param string $key * @return bool */ protected function isDateCastable($key) { return $this->hasCast($key, ['date', 'datetime']); } /** * Determine whether a value is JSON castable for inbound manipulation. * * @param string $key * @return bool */ protected function isJsonCastable($key) { return $this->hasCast($key, ['array', 'json', 'object', 'collection']); } /** * Get all of the current attributes on the model. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set the array of model attributes. No checking is done. * * @param array $attributes * @param bool $sync * @return $this */ public function setRawAttributes(array $attributes, $sync = false) { $this->attributes = $attributes; if ($sync) { $this->syncOriginal(); } return $this; } /** * Get the model's original attribute values. * * @param string|null $key * @param mixed $default * @return mixed|array */ public function getOriginal($key = null, $default = null) { return Arr::get($this->original, $key, $default); } /** * Get a subset of the model's attributes. * * @param array|mixed $attributes * @return array */ public function only($attributes) { $results = []; foreach (is_array($attributes) ? $attributes : func_get_args() as $attribute) { $results[$attribute] = $this->getAttribute($attribute); } return $results; } /** * Sync the original attributes with the current. * * @return $this */ public function syncOriginal() { $this->original = $this->attributes; return $this; } /** * Sync a single original attribute with its current value. * * @param string $attribute * @return $this */ public function syncOriginalAttribute($attribute) { return $this->syncOriginalAttributes($attribute); } /** * Sync multiple original attribute with their current values. * * @param array|string $attributes * @return $this */ public function syncOriginalAttributes($attributes) { $attributes = is_array($attributes) ? $attributes : func_get_args(); foreach ($attributes as $attribute) { $this->original[$attribute] = $this->attributes[$attribute]; } return $this; } /** * Sync the changed attributes. * * @return $this */ public function syncChanges() { $this->changes = $this->getDirty(); return $this; } /** * Determine if the model or any of the given attribute(s) have been modified. * * @param array|string|null $attributes * @return bool */ public function isDirty($attributes = null) { return $this->hasChanges( $this->getDirty(), is_array($attributes) ? $attributes : func_get_args() ); } /** * Determine if the model and all the given attribute(s) have remained the same. * * @param array|string|null $attributes * @return bool */ public function isClean($attributes = null) { return ! $this->isDirty(...func_get_args()); } /** * Determine if the model or any of the given attribute(s) have been modified. * * @param array|string|null $attributes * @return bool */ public function wasChanged($attributes = null) { return $this->hasChanges( $this->getChanges(), is_array($attributes) ? $attributes : func_get_args() ); } /** * Determine if any of the given attributes were changed. * * @param array $changes * @param array|string|null $attributes * @return bool */ protected function hasChanges($changes, $attributes = null) { // If no specific attributes were provided, we will just see if the dirty array // already contains any attributes. If it does we will just return that this // count is greater than zero. Else, we need to check specific attributes. if (empty($attributes)) { return count($changes) > 0; } // Here we will spin through every attribute and see if this is in the array of // dirty attributes. If it is, we will return true and if we make it through // all of the attributes for the entire array we will return false at end. foreach (Arr::wrap($attributes) as $attribute) { if (array_key_exists($attribute, $changes)) { return true; } } return false; } /** * Get the attributes that have been changed since last sync. * * @return array */ public function getDirty() { $dirty = []; foreach ($this->getAttributes() as $key => $value) { if (! $this->originalIsEquivalent($key, $value)) { $dirty[$key] = $value; } } return $dirty; } /** * Get the attributes that were changed. * * @return array */ public function getChanges() { return $this->changes; } /** * Determine if the new and old values for a given key are equivalent. * * @param string $key * @param mixed $current * @return bool */ public function originalIsEquivalent($key, $current) { if (! array_key_exists($key, $this->original)) { return false; } $original = $this->getOriginal($key); if ($current === $original) { return true; } elseif (is_null($current)) { return false; } elseif ($this->isDateAttribute($key)) { return $this->fromDateTime($current) === $this->fromDateTime($original); } elseif ($this->hasCast($key)) { return $this->castAttribute($key, $current) === $this->castAttribute($key, $original); } return is_numeric($current) && is_numeric($original) && strcmp((string) $current, (string) $original) === 0; } /** * Append attributes to query when building a query. * * @param array|string $attributes * @return $this */ public function append($attributes) { $this->appends = array_unique( array_merge($this->appends, is_string($attributes) ? func_get_args() : $attributes) ); return $this; } /** * Set the accessors to append to model arrays. * * @param array $appends * @return $this */ public function setAppends(array $appends) { $this->appends = $appends; return $this; } /** * Get the mutated attributes for a given instance. * * @return array */ public function getMutatedAttributes() { $class = static::class; if (! isset(static::$mutatorCache[$class])) { static::cacheMutatedAttributes($class); } return static::$mutatorCache[$class]; } /** * Extract and cache all the mutated attributes of a class. * * @param string $class * @return void */ public static function cacheMutatedAttributes($class) { static::$mutatorCache[$class] = collect(static::getMutatorMethods($class))->map(function ($match) { return lcfirst(static::$snakeAttributes ? Str::snake($match) : $match); })->all(); } /** * Get all of the attribute mutator methods. * * @param mixed $class * @return array */ protected static function getMutatorMethods($class) { preg_match_all('/(?<=^|;)get([^;]+?)Attribute(;|$)/', implode(';', get_class_methods($class)), $matches); return $matches[1]; } }