Regular Expressions 101

Save & Share

  • Regex Version: ver. 14
  • Update Regex
    ctrl+⇧+s
  • Save new Regex
    ctrl+s
  • Add to Community Library

Flavor

  • PCRE2 (PHP >=7.3)
  • PCRE (PHP <7.3)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java 8
  • .NET 7.0 (C#)
  • Rust
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests

Tools

Sponsors
There are currently no sponsors. Become a sponsor today!
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Non-capturing group
    (?:...)
  • Capturing group
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression

~
~
gm

Test String

Code Generator

Generated Code

const regex = new RegExp('^\\s*[\\w\\s]+\\(.*\\)\\s*\\K({((?>"(?:[^"\\\\]*+|\\\\.)*"|\\'(?:[^\\'\\\\]*+|\\\\.)*\\'|//.*$|/\\*[\\s\\S]*?\\*/|#.*$|<<<\\s*["\\']?(\\w+)["\\']?[^;]+\\3;$|[^{}<\\'"/#]++|[^{}]++|(?1))*)})', 'gm') const str = `<?php namespace Illuminate\\Database\\Eloquent; use Closure; use DateTime; use Exception; use ArrayAccess; use Carbon\\Carbon; use LogicException; use JsonSerializable; use DateTimeInterface; use Illuminate\\Support\\Arr; use Illuminate\\Support\\Str; use InvalidArgumentException; use Illuminate\\Contracts\\Support\\Jsonable; use Illuminate\\Contracts\\Events\\Dispatcher; use Illuminate\\Contracts\\Support\\Arrayable; use Illuminate\\Contracts\\Routing\\UrlRoutable; use Illuminate\\Contracts\\Queue\\QueueableEntity; use Illuminate\\Database\\Eloquent\\Relations\\Pivot; use Illuminate\\Database\\Eloquent\\Relations\\HasOne; use Illuminate\\Database\\Eloquent\\Relations\\HasMany; use Illuminate\\Database\\Eloquent\\Relations\\MorphTo; use Illuminate\\Database\\Eloquent\\Relations\\Relation; use Illuminate\\Database\\Eloquent\\Relations\\MorphOne; use Illuminate\\Support\\Collection as BaseCollection; use Illuminate\\Database\\Eloquent\\Relations\\MorphMany; use Illuminate\\Database\\Eloquent\\Relations\\BelongsTo; use Illuminate\\Database\\Query\\Builder as QueryBuilder; use Illuminate\\Database\\Eloquent\\Relations\\MorphToMany; use Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany; use Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough; use Illuminate\\Database\\ConnectionResolverInterface as Resolver; abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable { /** * The connection name for the model. * * @var string */ protected \$connection; /** * The table associated with the model. * * @var string */ protected \$table; /** * The primary key for the model. * * @var string */ protected \$primaryKey = 'id'; /** * The "type" of the auto-incrementing ID. * * @var string */ protected \$keyType = 'int'; /** * The number of models to return for pagination. * * @var int */ protected \$perPage = 15; /** * Indicates if the IDs are auto-incrementing. * * @var bool */ public \$incrementing = true; /** * Indicates if the model should be timestamped. * * @var bool */ public \$timestamps = true; /** * The model's attributes. * * @var array */ protected \$attributes = []; /** * The model attribute's original state. * * @var array */ protected \$original = []; /** * The loaded relationships for the model. * * @var array */ protected \$relations = []; /** * The attributes that should be hidden for arrays. * * @var array */ protected \$hidden = []; /** * The attributes that should be visible in arrays. * * @var array */ protected \$visible = []; /** * The accessors to append to the model's array form. * * @var array */ protected \$appends = []; /** * The attributes that are mass assignable. * * @var array */ protected \$fillable = []; /** * The attributes that aren't mass assignable. * * @var array */ protected \$guarded = ['*']; /** * 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 attributes that should be cast to native types. * * @var array */ protected \$casts = []; /** * The relationships that should be touched on save. * * @var array */ protected \$touches = []; /** * User exposed observable events. * * @var array */ protected \$observables = []; /** * The relations to eager load on every query. * * @var array */ protected \$with = []; /** * The class name to be used in polymorphic relations. * * @var string */ protected \$morphClass; /** * Indicates if the model exists. * * @var bool */ public \$exists = false; /** * Indicates if the model was inserted during the current request lifecycle. * * @var bool */ public \$wasRecentlyCreated = false; /** * Indicates whether attributes are snake cased on arrays. * * @var bool */ public static \$snakeAttributes = true; /** * The connection resolver instance. * * @var \\Illuminate\\Database\\ConnectionResolverInterface */ protected static \$resolver; /** * The event dispatcher instance. * * @var \\Illuminate\\Contracts\\Events\\Dispatcher */ protected static \$dispatcher; /** * The array of booted models. * * @var array */ protected static \$booted = []; /** * The array of global scopes on the model. * * @var array */ protected static \$globalScopes = []; /** * Indicates if all mass assignment is enabled. * * @var bool */ protected static \$unguarded = false; /** * The cache of the mutated attributes for each class. * * @var array */ protected static \$mutatorCache = []; /** * The many to many relationship methods. * * @var array */ public static \$manyMethods = ['belongsToMany', 'morphToMany', 'morphedByMany']; /** * The name of the "created at" column. * * @var string */ const CREATED_AT = 'created_at'; /** * The name of the "updated at" column. * * @var string */ const UPDATED_AT = 'updated_at'; /** * Create a new Eloquent model instance. * * @param array \$attributes * @return void */ public function __construct(array \$attributes = []) { \$str = "\\""; \$this->bootIfNotBooted(); \$this->syncOriginal(); \$this->fill(\$attributes); } /** * Check if the model needs to be booted and if so, do it. * * @return void */ protected function bootIfNotBooted() { if (! isset(static::\$booted[static::class])) { static::\$booted[static::class] = true; \$this->fireModelEvent('booting', false); static::boot(); \$this->fireModelEvent('booted', false); } } /** * The "booting" method of the model. * * @return void */ protected static function boot() { static::bootTraits(); } /** * Boot all of the bootable traits on the model. * * @return void */ protected static function bootTraits() { \$class = static::class; foreach (class_uses_recursive(\$class) as \$trait) { if (method_exists(\$class, \$method = 'boot'.class_basename(\$trait))) { forward_static_call([\$class, \$method]); } } } /** * Clear the list of booted models so they will be re-booted. * * @return void */ public static function clearBootedModels() { static::\$booted = []; static::\$globalScopes = []; } /** * Register a new global scope on the model. * * @param \\Illuminate\\Database\\Eloquent\\Scope|\\Closure|string \$scope * @param \\Closure|null \$implementation * @return mixed * * @throws \\InvalidArgumentException */ public static function addGlobalScope(\$scope, Closure \$implementation = null) { if (is_string(\$scope) && \$implementation !== null) { return static::\$globalScopes[static::class][\$scope] = \$implementation; } if (\$scope instanceof Closure) { return static::\$globalScopes[static::class][spl_object_hash(\$scope)] = \$scope; } if (\$scope instanceof Scope) { return static::\$globalScopes[static::class][get_class(\$scope)] = \$scope; } throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope.'); } /** * Determine if a model has a global scope. * * @param \\Illuminate\\Database\\Eloquent\\Scope|string \$scope * @return bool */ public static function hasGlobalScope(\$scope) { return ! is_null(static::getGlobalScope(\$scope)); } /** * Get a global scope registered with the model. * * @param \\Illuminate\\Database\\Eloquent\\Scope|string \$scope * @return \\Illuminate\\Database\\Eloquent\\Scope|\\Closure|null */ public static function getGlobalScope(\$scope) { if (! is_string(\$scope)) { \$scope = get_class(\$scope); } return Arr::get(static::\$globalScopes, static::class.'.'.\$scope); } /** * Get the global scopes for this class instance. * * @return array */ public function getGlobalScopes() { return Arr::get(static::\$globalScopes, static::class, []); } /** * Register an observer with the Model. * * @param object|string \$class * @param int \$priority * @return void */ public static function observe(\$class, \$priority = 0) { \$instance = new static; \$className = is_string(\$class) ? \$class : get_class(\$class); // When registering a model observer, we will spin through the possible events // and determine if this observer has that method. If it does, we will hook // it into the model's event system, making it convenient to watch these. foreach (\$instance->getObservableEvents() as \$event) { if (method_exists(\$class, \$event)) { static::registerModelEvent(\$event, \$className.'@'.\$event, \$priority); } } } /** * Fill the model with an array of attributes. * * @param array \$attributes * @return \$this * * @throws \\Illuminate\\Database\\Eloquent\\MassAssignmentException */ public function fill(array \$attributes) { \$totallyGuarded = \$this->totallyGuarded(); foreach (\$this->fillableFromArray(\$attributes) as \$key => \$value) { \$key = \$this->removeTableFromKey(\$key); // The developers may choose to place some attributes in the "fillable" // array, which means only those attributes may be set through mass // assignment to the model, and all others will just be ignored. if (\$this->isFillable(\$key)) { \$this->setAttribute(\$key, \$value); } elseif (\$totallyGuarded) { throw new MassAssignmentException(\$key); } } return \$this; } /** * Fill the model with an array of attributes. Force mass assignment. * * @param array \$attributes * @return \$this */ public function forceFill(array \$attributes) { return static::unguarded(function () use (\$attributes) { return \$this->fill(\$attributes); }); } /** * Get the fillable attributes of a given array. * * @param array \$attributes * @return array */ protected function fillableFromArray(array \$attributes) { if (count(\$this->getFillable()) > 0 && ! static::\$unguarded) { return array_intersect_key(\$attributes, array_flip(\$this->getFillable())); } return \$attributes; } /** * Create a new instance of the given model. * * @param array \$attributes * @param bool \$exists * @return static */ public function newInstance(\$attributes = [], \$exists = false) { // This method just provides a convenient way for us to generate fresh model // instances of this current model. It is particularly useful during the // hydration of new objects via the Eloquent query builder instances. \$model = new static((array) \$attributes); \$model->exists = \$exists; return \$model; } /** * Create a new model instance that is existing. * * @param array \$attributes * @param string|null \$connection * @return static */ public function newFromBuilder(\$attributes = [], \$connection = null) { \$model = \$this->newInstance([], true); \$model->setRawAttributes((array) \$attributes, true); \$model->setConnection(\$connection ?: \$this->connection); return \$model; } /** * Create a collection of models from plain arrays. * * @param array \$items * @param string|null \$connection * @return \\Illuminate\\Database\\Eloquent\\Collection */ public static function hydrate(array \$items, \$connection = null) { \$instance = (new static)->setConnection(\$connection); \$items = array_map(function (\$item) use (\$instance) { return \$instance->newFromBuilder(\$item); }, \$items); return \$instance->newCollection(\$items); } /** * Create a collection of models from a raw query. * * @param string \$query * @param array \$bindings * @param string|null \$connection * @return \\Illuminate\\Database\\Eloquent\\Collection */ public static function hydrateRaw(\$query, \$bindings = [], \$connection = null) { \$instance = (new static)->setConnection(\$connection); \$items = \$instance->getConnection()->select(\$query, \$bindings); return static::hydrate(\$items, \$connection); } /** * Save a new model and return the instance. * * @param array \$attributes * @return static */ public static function create(array \$attributes = []) { \$model = new static(\$attributes); \$model->save(); return \$model; } /** * Save a new model and return the instance. Allow mass-assignment. * * @param array \$attributes * @return static */ public static function forceCreate(array \$attributes) { return static::unguarded(function () use (\$attributes) { return (new static)->create(\$attributes); }); } /** * Begin querying the model. * * @return \\Illuminate\\Database\\Eloquent\\Builder */ public static function query() { return (new static)->newQuery(); } /** * Begin querying the model on a given connection. * * @param string|null \$connection * @return \\Illuminate\\Database\\Eloquent\\Builder */ public static function on(\$connection = null) { // First we will just create a fresh instance of this model, and then we can // set the connection on the model so that it is be used for the queries // we execute, as well as being set on each relationship we retrieve. \$instance = new static; \$instance->setConnection(\$connection); return \$instance->newQuery(); } /** * Begin querying the model on the write connection. * * @return \\Illuminate\\Database\\Query\\Builder */ public static function onWriteConnection() { \$instance = new static; return \$instance->newQuery()->useWritePdo(); } /** * Get all of the models from the database. * * @param array|mixed \$columns * @return \\Illuminate\\Database\\Eloquent\\Collection|static[] */ public static function all(\$columns = ['*']) { \$columns = is_array(\$columns) ? \$columns : func_get_args(); \$instance = new static; return \$instance->newQuery()->get(\$columns); } /** * Reload a fresh model instance from the database. * * @param array|string \$with * @return \$this|null */ public function fresh(\$with = []) { if (! \$this->exists) { return; } if (is_string(\$with)) { \$with = func_get_args(); } \$key = \$this->getKeyName(); return static::with(\$with)->where(\$key, \$this->getKey())->first(); } /** * Eager load relations on the model. * * @param array|string \$relations * @return \$this */ public function load(\$relations) { if (is_string(\$relations)) { \$relations = func_get_args(); } \$query = \$this->newQuery()->with(\$relations); \$query->eagerLoadRelations([\$this]); return \$this; } /** * Begin querying a model with eager loading. * * @param array|string \$relations * @return \\Illuminate\\Database\\Eloquent\\Builder|static */ public static function with(\$relations) { if (is_string(\$relations)) { \$relations = func_get_args(); } \$instance = new static; return \$instance->newQuery()->with(\$relations); } /** * Append attributes to query when building a query. * * @param array|string \$attributes * @return \$this */ public function append(\$attributes) { if (is_string(\$attributes)) { \$attributes = func_get_args(); } \$this->appends = array_unique( array_merge(\$this->appends, \$attributes) ); return \$this; } /** * Define a one-to-one relationship. * * @param string \$related * @param string \$foreignKey * @param string \$localKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasOne */ public function hasOne(\$related, \$foreignKey = null, \$localKey = null) { \$foreignKey = \$foreignKey ?: \$this->getForeignKey(); \$instance = new \$related; \$localKey = \$localKey ?: \$this->getKeyName(); return new HasOne(\$instance->newQuery(), \$this, \$instance->getTable().'.'.\$foreignKey, \$localKey); } /** * Define a polymorphic one-to-one relationship. * * @param string \$related * @param string \$name * @param string \$type * @param string \$id * @param string \$localKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\MorphOne */ public function morphOne(\$related, \$name, \$type = null, \$id = null, \$localKey = null) { \$instance = new \$related; list(\$type, \$id) = \$this->getMorphs(\$name, \$type, \$id); \$table = \$instance->getTable(); \$localKey = \$localKey ?: \$this->getKeyName(); return new MorphOne(\$instance->newQuery(), \$this, \$table.'.'.\$type, \$table.'.'.\$id, \$localKey); } /** * Define an inverse one-to-one or many relationship. * * @param string \$related * @param string \$foreignKey * @param string \$otherKey * @param string \$relation * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo */ public function belongsTo(\$related, \$foreignKey = null, \$otherKey = null, \$relation = null) { // If no relation name was given, we will use this debug backtrace to extract // the calling method's name and use that as the relationship name as most // of the time this will be what we desire to use for the relationships. if (is_null(\$relation)) { list(\$current, \$caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); \$relation = \$caller['function']; } // If no foreign key was supplied, we can use a backtrace to guess the proper // foreign key name by using the name of the relationship function, which // when combined with an "_id" should conventionally match the columns. if (is_null(\$foreignKey)) { \$foreignKey = Str::snake(\$relation).'_id'; } \$instance = new \$related; // Once we have the foreign key names, we'll just create a new Eloquent query // for the related models and returns the relationship instance which will // actually be responsible for retrieving and hydrating every relations. \$query = \$instance->newQuery(); \$otherKey = \$otherKey ?: \$instance->getKeyName(); return new BelongsTo(\$query, \$this, \$foreignKey, \$otherKey, \$relation); } /** * Define a polymorphic, inverse one-to-one or many relationship. * * @param string \$name * @param string \$type * @param string \$id * @return \\Illuminate\\Database\\Eloquent\\Relations\\MorphTo */ public function morphTo(\$name = null, \$type = null, \$id = null) { // If no name is provided, we will use the backtrace to get the function name // since that is most likely the name of the polymorphic interface. We can // use that to get both the class and foreign key that will be utilized. if (is_null(\$name)) { list(\$current, \$caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); \$name = Str::snake(\$caller['function']); } list(\$type, \$id) = \$this->getMorphs(\$name, \$type, \$id); // If the type value is null it is probably safe to assume we're eager loading // the relationship. When that is the case we will pass in a dummy query as // there are multiple types in the morph and we can't use single queries. if (empty(\$class = \$this->\$type)) { return new MorphTo( \$this->newQuery(), \$this, \$id, null, \$type, \$name ); } // If we are not eager loading the relationship we will essentially treat this // as a belongs-to style relationship since morph-to extends that class and // we will pass in the appropriate values so that it behaves as expected. else { \$class = \$this->getActualClassNameForMorph(\$class); \$instance = new \$class; return new MorphTo( \$instance->newQuery(), \$this, \$id, \$instance->getKeyName(), \$type, \$name ); } } /** * Retrieve the fully qualified class name from a slug. * * @param string \$class * @return string */ public function getActualClassNameForMorph(\$class) { return Arr::get(Relation::morphMap(), \$class, \$class); } /** * Define a one-to-many relationship. * * @param string \$related * @param string \$foreignKey * @param string \$localKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasMany */ public function hasMany(\$related, \$foreignKey = null, \$localKey = null) { \$foreignKey = \$foreignKey ?: \$this->getForeignKey(); \$instance = new \$related; \$localKey = \$localKey ?: \$this->getKeyName(); return new HasMany(\$instance->newQuery(), \$this, \$instance->getTable().'.'.\$foreignKey, \$localKey); } /** * Define a has-many-through relationship. * * @param string \$related * @param string \$through * @param string|null \$firstKey * @param string|null \$secondKey * @param string|null \$localKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough */ public function hasManyThrough(\$related, \$through, \$firstKey = null, \$secondKey = null, \$localKey = null) { \$through = new \$through; \$firstKey = \$firstKey ?: \$this->getForeignKey(); \$secondKey = \$secondKey ?: \$through->getForeignKey(); \$localKey = \$localKey ?: \$this->getKeyName(); return new HasManyThrough((new \$related)->newQuery(), \$this, \$through, \$firstKey, \$secondKey, \$localKey); } /** * Define a polymorphic one-to-many relationship. * * @param string \$related * @param string \$name * @param string \$type * @param string \$id * @param string \$localKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\MorphMany */ public function morphMany(\$related, \$name, \$type = null, \$id = null, \$localKey = null) { \$instance = new \$related; // Here we will gather up the morph type and ID for the relationship so that we // can properly query the intermediate table of a relation. Finally, we will // get the table and create the relationship instances for the developers. list(\$type, \$id) = \$this->getMorphs(\$name, \$type, \$id); \$table = \$instance->getTable(); \$localKey = \$localKey ?: \$this->getKeyName(); return new MorphMany(\$instance->newQuery(), \$this, \$table.'.'.\$type, \$table.'.'.\$id, \$localKey); } /** * Define a many-to-many relationship. * * @param string \$related * @param string \$table * @param string \$foreignKey * @param string \$otherKey * @param string \$relation * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany */ public function belongsToMany(\$related, \$table = null, \$foreignKey = null, \$otherKey = null, \$relation = null) { // If no relationship name was passed, we will pull backtraces to get the // name of the calling function. We will use that function name as the // title of this relation since that is a great convention to apply. if (is_null(\$relation)) { \$relation = \$this->getBelongsToManyCaller(); } // First, we'll need to determine the foreign key and "other key" for the // relationship. Once we have determined the keys we'll make the query // instances as well as the relationship instances we need for this. \$foreignKey = \$foreignKey ?: \$this->getForeignKey(); \$instance = new \$related; \$otherKey = \$otherKey ?: \$instance->getForeignKey(); // If no table name was provided, we can guess it by concatenating the two // models using underscores in alphabetical order. The two model names // are transformed to snake case from their default CamelCase also. if (is_null(\$table)) { \$table = \$this->joiningTable(\$related); } // Now we're ready to create a new query builder for the related model and // the relationship instances for the relation. The relations will set // appropriate query constraint and entirely manages the hydrations. \$query = \$instance->newQuery(); return new BelongsToMany(\$query, \$this, \$table, \$foreignKey, \$otherKey, \$relation); } /** * Define a polymorphic many-to-many relationship. * * @param string \$related * @param string \$name * @param string \$table * @param string \$foreignKey * @param string \$otherKey * @param bool \$inverse * @return \\Illuminate\\Database\\Eloquent\\Relations\\MorphToMany */ public function morphToMany(\$related, \$name, \$table = null, \$foreignKey = null, \$otherKey = null, \$inverse = false) { \$caller = \$this->getBelongsToManyCaller(); // First, we will need to determine the foreign key and "other key" for the // relationship. Once we have determined the keys we will make the query // instances, as well as the relationship instances we need for these. \$foreignKey = \$foreignKey ?: \$name.'_id'; \$instance = new \$related; \$otherKey = \$otherKey ?: \$instance->getForeignKey(); // Now we're ready to create a new query builder for this related model and // the relationship instances for this relation. This relations will set // appropriate query constraints then entirely manages the hydrations. \$query = \$instance->newQuery(); \$table = \$table ?: Str::plural(\$name); return new MorphToMany( \$query, \$this, \$name, \$table, \$foreignKey, \$otherKey, \$caller, \$inverse ); } /** * Define a polymorphic, inverse many-to-many relationship. * * @param string \$related * @param string \$name * @param string \$table * @param string \$foreignKey * @param string \$otherKey * @return \\Illuminate\\Database\\Eloquent\\Relations\\MorphToMany */ public function morphedByMany(\$related, \$name, \$table = null, \$foreignKey = null, \$otherKey = null) { \$foreignKey = \$foreignKey ?: \$this->getForeignKey(); // For the inverse of the polymorphic many-to-many relations, we will change // the way we determine the foreign and other keys, as it is the opposite // of the morph-to-many method since we're figuring out these inverses. \$otherKey = \$otherKey ?: \$name.'_id'; return \$this->morphToMany(\$related, \$name, \$table, \$foreignKey, \$otherKey, true); } /** * Get the relationship name of the belongs to many. * * @return string */ protected function getBelongsToManyCaller() { \$self = __FUNCTION__; \$caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function (\$trace) use (\$self) { \$caller = \$trace['function']; return ! in_array(\$caller, Model::\$manyMethods) && \$caller != \$self; }); return ! is_null(\$caller) ? \$caller['function'] : null; } /** * Get the joining table name for a many-to-many relation. * * @param string \$related * @return string */ public function joiningTable(\$related) { // The joining table name, by convention, is simply the snake cased models // sorted alphabetically and concatenated with an underscore, so we can // just sort the models and join them together to get the table name. \$base = Str::snake(class_basename(\$this)); \$related = Str::snake(class_basename(\$related)); \$models = [\$related, \$base]; // Now that we have the model names in an array we can just sort them and // use the implode function to join them together with an underscores, // which is typically used by convention within the database system. sort(\$models); return strtolower(implode('_', \$models)); } /** * Destroy the models for the given IDs. * * @param array|int \$ids * @return int */ public static function destroy(\$ids) { // We'll initialize a count here so we will return the total number of deletes // for the operation. The developers can then check this number as a boolean // type value or get this total count of records deleted for logging, etc. \$count = 0; \$ids = is_array(\$ids) ? \$ids : func_get_args(); \$instance = new static; // We will actually pull the models from the database table and call delete on // each of them individually so that their events get fired properly with a // correct set of attributes in case the developers wants to check these. \$key = \$instance->getKeyName(); foreach (\$instance->whereIn(\$key, \$ids)->get() as \$model) { if (\$model->delete()) { \$count++; } } return \$count; } /** * Delete the model from the database. * * @return bool|null * * @throws \\Exception */ public function delete() { if (is_null(\$this->getKeyName())) { throw new Exception('No primary key defined on model.'); } if (\$this->exists) { if (\$this->fireModelEvent('deleting') === false) { return false; } // Here, we'll touch the owning models, verifying these timestamps get updated // for the models. This will allow any caching to get broken on the parents // by the timestamp. Then we will go ahead and delete the model instance. \$this->touchOwners(); \$this->performDeleteOnModel(); \$this->exists = false; // Once the model has been deleted, we will fire off the deleted event so that // the developers may hook into post-delete operations. We will then return // a boolean true as the delete is presumably successful on the database. \$this->fireModelEvent('deleted', false); return true; } } /** * Force a hard delete on a soft deleted model. * * This method protects developers from running forceDelete when trait is missing. * * @return bool|null */ public function forceDelete() { return \$this->delete(); } /** * Perform the actual delete query on this model instance. * * @return void */ protected function performDeleteOnModel() { \$this->setKeysForSaveQuery(\$this->newQueryWithoutScopes())->delete(); } /** * Register a saving model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function saving(\$callback, \$priority = 0) { static::registerModelEvent('saving', \$callback, \$priority); } /** * Register a saved model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function saved(\$callback, \$priority = 0) { static::registerModelEvent('saved', \$callback, \$priority); } /** * Register an updating model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function updating(\$callback, \$priority = 0) { static::registerModelEvent('updating', \$callback, \$priority); } /** * Register an updated model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function updated(\$callback, \$priority = 0) { static::registerModelEvent('updated', \$callback, \$priority); } /** * Register a creating model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function creating(\$callback, \$priority = 0) { static::registerModelEvent('creating', \$callback, \$priority); } /** * Register a created model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function created(\$callback, \$priority = 0) { static::registerModelEvent('created', \$callback, \$priority); } /** * Register a deleting model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function deleting(\$callback, \$priority = 0) { static::registerModelEvent('deleting', \$callback, \$priority); } /** * Register a deleted model event with the dispatcher. * * @param \\Closure|string \$callback * @param int \$priority * @return void */ public static function deleted(\$callback, \$priority = 0) { static::registerModelEvent('deleted', \$callback, \$priority); } /** * Remove all of the event listeners for the model. * * @return void */ public static function flushEventListeners() { if (! isset(static::\$dispatcher)) { return; } \$instance = new static; foreach (\$instance->getObservableEvents() as \$event) { static::\$dispatcher->forget("eloquent.{\$event}: ".static::class); } } /** * Register a model event with the dispatcher. * * @param string \$event * @param \\Closure|string \$callback * @param int \$priority * @return void */ protected static function registerModelEvent(\$event, \$callback, \$priority = 0) { if (isset(static::\$dispatcher)) { \$name = static::class; static::\$dispatcher->listen("eloquent.{\$event}: {\$name}", \$callback, \$priority); } } /** * Get the observable event names. * * @return array */ public function getObservableEvents() { return array_merge( [ 'creating', 'created', 'updating', 'updated', 'deleting', 'deleted', 'saving', 'saved', 'restoring', 'restored', ], \$this->observables ); } /** * Set the observable event names. * * @param array \$observables * @return \$this */ public function setObservableEvents(array \$observables) { \$this->observables = \$observables; return \$this; } /** * Add an observable event name. * * @param array|mixed \$observables * @return void */ public function addObservableEvents(\$observables) { \$observables = is_array(\$observables) ? \$observables : func_get_args(); \$this->observables = array_unique(array_merge(\$this->observables, \$observables)); } /** * Remove an observable event name. * * @param array|mixed \$observables * @return void */ public function removeObservableEvents(\$observables) { \$observables = is_array(\$observables) ? \$observables : func_get_args(); \$this->observables = array_diff(\$this->observables, \$observables); } /** * Increment a column's value by a given amount. * * @param string \$column * @param int \$amount * @param array \$extra * @return int */ protected function increment(\$column, \$amount = 1, array \$extra = []) { return \$this->incrementOrDecrement(\$column, \$amount, \$extra, 'increment'); } /** * Decrement a column's value by a given amount. * * @param string \$column * @param int \$amount * @param array \$extra * @return int */ protected function decrement(\$column, \$amount = 1, array \$extra = []) { return \$this->incrementOrDecrement(\$column, \$amount, \$extra, 'decrement'); } /** * Run the increment or decrement method on the model. * * @param string \$column * @param int \$amount * @param array \$extra * @param string \$method * @return int */ protected function incrementOrDecrement(\$column, \$amount, \$extra, \$method) { \$query = \$this->newQuery(); if (! \$this->exists) { return \$query->{\$method}(\$column, \$amount, \$extra); } \$this->incrementOrDecrementAttributeValue(\$column, \$amount, \$method); return \$query->where(\$this->getKeyName(), \$this->getKey())->{\$method}(\$column, \$amount, \$extra); } /** * Increment the underlying attribute value and sync with original. * * @param string \$column * @param int \$amount * @param string \$method * @return void */ protected function incrementOrDecrementAttributeValue(\$column, \$amount, \$method) { \$this->{\$column} = \$this->{\$column} + (\$method == 'increment' ? \$amount : \$amount * -1); \$this->syncOriginalAttribute(\$column); } /** * Update the model in the database. * * @param array \$attributes * @param array \$options * @return bool|int */ public function update(array \$attributes = [], array \$options = []) { if (! \$this->exists) { return false; } return \$this->fill(\$attributes)->save(\$options); } /** * Save the model and all of its relationships. * * @return bool */ public function push() { if (! \$this->save()) { return false; } // To sync all of the relationships to the database, we will simply spin through // the relationships and save each model via this "push" method, which allows // us to recurse into all of these nested relations for the model instance. foreach (\$this->relations as \$models) { \$models = \$models instanceof Collection ? \$models->all() : [\$models]; foreach (array_filter(\$models) as \$model) { if (! \$model->push()) { return false; } } } return true; } /** * Save the model to the database. * * @param array \$options * @return bool */ public function save(array \$options = []) { \$query = \$this->newQueryWithoutScopes(); // If the "saving" event returns false we'll bail out of the save and return // false, indicating that the save failed. This provides a chance for any // listeners to cancel save operations if validations fail or whatever. if (\$this->fireModelEvent('saving') === false) { return false; } // If the model already exists in the database we can just update our record // that is already in this database using the current IDs in this "where" // clause to only update this model. Otherwise, we'll just insert them. if (\$this->exists) { \$saved = \$this->performUpdate(\$query); } // If the model is brand new, we'll insert it into our database and set the // ID attribute on the model to the value of the newly inserted row's ID // which is typically an auto-increment value managed by the database. else { \$saved = \$this->performInsert(\$query); } if (\$saved) { \$this->finishSave(\$options); } return \$saved; } /** * Save the model to the database using transaction. * * @param array \$options * @return bool * * @throws \\Throwable */ public function saveOrFail(array \$options = []) { return \$this->getConnection()->transaction(function () use (\$options) { return \$this->save(\$options); }); } /** * Finish processing on a successful save operation. * * @param array \$options * @return void */ protected function finishSave(array \$options) { \$this->fireModelEvent('saved', false); \$this->syncOriginal(); if (Arr::get(\$options, 'touch', true)) { \$this->touchOwners(); } } /** * Perform a model update operation. * * @param \\Illuminate\\Database\\Eloquent\\Builder \$query * @return bool */ protected function performUpdate(Builder \$query) { \$dirty = \$this->getDirty(); if (count(\$dirty) > 0) { // If the updating event returns false, we will cancel the update operation so // developers can hook Validation systems into their models and cancel this // operation if the model does not pass validation. Otherwise, we update. if (\$this->fireModelEvent('updating') === false) { return false; } // First we need to create a fresh query instance and touch the creation and // update timestamp on the model which are maintained by us for developer // convenience. Then we will just continue saving the model instances. if (\$this->timestamps) { \$this->updateTimestamps(); } // Once we have run the update operation, we will fire the "updated" event for // this model instance. This will allow developers to hook into these after // models are updated, giving them a chance to do any special processing. \$dirty = \$this->getDirty(); if (count(\$dirty) > 0) { \$numRows = \$this->setKeysForSaveQuery(\$query)->update(\$dirty); \$this->fireModelEvent('updated', false); } } return true; } /** * Perform a model insert operation. * * @param \\Illuminate\\Database\\Eloquent\\Builder \$query * @return bool */ protected function performInsert(Builder \$query) { if (\$this->fireModelEvent('creating') === false) { return false; } // First we'll need to create a fresh query instance and touch the creation and // update timestamps on this model, which are maintained by us for developer // convenience. After, we will just continue saving these model instances. if (\$this->timestamps) { \$this->updateTimestamps(); } // If the model has an incrementing key, we can use the "insertGetId" method on // the query builder, which will give us back the final inserted ID for this // table from the database. Not all tables have to be incrementing though. \$attributes = \$this->attributes; if (\$this->getIncrementing()) { \$this->insertAndSetId(\$query, \$attributes); } // If the table isn't incrementing we'll simply insert these attributes as they // are. These attribute arrays must contain an "id" column previously placed // there by the developer as the manually determined key for these models. else { \$query->insert(\$attributes); } // We will go ahead and set the exists property to true, so that it is set when // the created event is fired, just in case the developer tries to update it // during the event. This will allow them to do so and run an update here. \$this->exists = true; \$this->wasRecentlyCreated = true; \$this->fireModelEvent('created', false); return true; } /** * Insert the given attributes and set the ID on the model. * * @param \\Illuminate\\Database\\Eloquent\\Builder \$query * @param array \$attributes * @return void */ protected function insertAndSetId(Builder \$query, \$attributes) { \$id = \$query->insertGetId(\$attributes, \$keyName = \$this->getKeyName()); \$this->setAttribute(\$keyName, \$id); } /** * Touch the owning relations of the model. * * @return void */ public function touchOwners() { foreach (\$this->touches as \$relation) { \$this->\$relation()->touch(); if (\$this->\$relation instanceof self) { \$this->\$relation->fireModelEvent('saved', false); \$this->\$relation->touchOwners(); } elseif (\$this->\$relation instanceof Collection) { \$this->\$relation->each(function (Model \$relation) { \$relation->touchOwners(); }); } } } /** * Determine if the model touches a given relation. * * @param string \$relation * @return bool */ public function touches(\$relation) { return in_array(\$relation, \$this->touches); } /** * Fire the given event for the model. * * @param string \$event * @param bool \$halt * @return mixed */ protected function fireModelEvent(\$event, \$halt = true) { if (! isset(static::\$dispatcher)) { return true; } // We will append the names of the class to the event to distinguish it from // other model events that are fired, allowing us to listen on each model // event set individually instead of catching event for all the models. \$event = "eloquent.{\$event}: ".static::class; \$method = \$halt ? 'until' : 'fire'; return static::\$dispatcher->\$method(\$event, \$this); } /** * Set the keys for a save update query. * * @param \\Illuminate\\Database\\Eloquent\\Builder \$query * @return \\Illuminate\\Database\\Eloquent\\Builder */ protected function setKeysForSaveQuery(Builder \$query) { \$query->where(\$this->getKeyName(), '=', \$this->getKeyForSaveQuery()); return \$query; } /** * Get the primary key value for a save query. * * @return mixed */ protected function getKeyForSaveQuery() { if (isset(\$this->original[\$this->getKeyName()])) { return \$this->original[\$this->getKeyName()]; } return \$this->getAttribute(\$this->getKeyName()); } /** * Update the model's update timestamp. * * @return bool */ public function touch() { if (! \$this->timestamps) { return false; } \$this->updateTimestamps(); return \$this->save(); } /** * Update the creation and update timestamps. * * @return void */ protected function updateTimestamps() { \$time = \$this->freshTimestamp(); if (! \$this->isDirty(static::UPDATED_AT)) { \$this->setUpdatedAt(\$time); } if (! \$this->exists && ! \$this->isDirty(static::CREATED_AT)) { \$this->setCreatedAt(\$time); } } /** * Set the value of the "created at" attribute. * * @param mixed \$value * @return \$this */ public function setCreatedAt(\$value) { \$this->{static::CREATED_AT} = \$value; return \$this; } /** * Set the value of the "updated at" attribute. * * @param mixed \$value * @return \$this */ public function setUpdatedAt(\$value) { \$this->{static::UPDATED_AT} = \$value; return \$this; } /** * Get the name of the "created at" column. * * @return string */ public function getCreatedAtColumn() { return static::CREATED_AT; } /** * Get the name of the "updated at" column. * * @return string */ public function getUpdatedAtColumn() { return static::UPDATED_AT; } /** * Get a fresh timestamp for the model. * * @return \\Carbon\\Carbon */ public function freshTimestamp() { return new Carbon; } /** * Get a fresh timestamp for the model. * * @return string */ public function freshTimestampString() { return \$this->fromDateTime(\$this->freshTimestamp()); } /** * Get a new query builder for the model's table. * * @return \\Illuminate\\Database\\Eloquent\\Builder */ public function newQuery() { \$builder = \$this->newQueryWithoutScopes(); foreach (\$this->getGlobalScopes() as \$identifier => \$scope) { \$builder->withGlobalScope(\$identifier, \$scope); } return \$builder; } /** * Get a new query instance without a given scope. * * @param \\Illuminate\\Database\\Eloquent\\Scope|string \$scope * @return \\Illuminate\\Database\\Eloquent\\Builder */ public function newQueryWithoutScope(\$scope) { \$builder = \$this->newQuery(); return \$builder->withoutGlobalScope(\$scope); } /** * Get a new query builder that doesn't have any global scopes. * * @return \\Illuminate\\Database\\Eloquent\\Builder|static */ public function newQueryWithoutScopes() { \$builder = \$this->newEloquentBuilder( \$this->newBaseQueryBuilder() ); // Once we have the query builders, we will set the model instances so the // builder can easily access any information it may need from the model // while it is constructing and executing various queries against it. return \$builder->setModel(\$this)->with(\$this->with); } /** * Create a new Eloquent query builder for the model. * * @param \\Illuminate\\Database\\Query\\Builder \$query * @return \\Illuminate\\Database\\Eloquent\\Builder|static */ public function newEloquentBuilder(\$query) { return new Builder(\$query); } /** * Get a new query builder instance for the connection. * * @return \\Illuminate\\Database\\Query\\Builder */ protected function newBaseQueryBuilder() { \$conn = \$this->getConnection(); \$grammar = \$conn->getQueryGrammar(); return new QueryBuilder(\$conn, \$grammar, \$conn->getPostProcessor()); } /** * Create a new Eloquent Collection instance. * * @param array \$models * @return \\Illuminate\\Database\\Eloquent\\Collection */ public function newCollection(array \$models = []) { return new Collection(\$models); } /** * Create a new pivot model instance. * * @param \\Illuminate\\Database\\Eloquent\\Model \$parent * @param array \$attributes * @param string \$table * @param bool \$exists * @return \\Illuminate\\Database\\Eloquent\\Relations\\Pivot */ public function newPivot(Model \$parent, array \$attributes, \$table, \$exists) { return new Pivot(\$parent, \$attributes, \$table, \$exists); } /** * Get the table associated with the model. * * @return string */ public function getTable() { if (isset(\$this->table)) { return \$this->table; } return str_replace('\\\\', '', Str::snake(Str::plural(class_basename(\$this)))); } /** * Set the table associated with the model. * * @param string \$table * @return \$this */ public function setTable(\$table) { \$this->table = \$table; return \$this; } /** * Get the value of the model's primary key. * * @return mixed */ public function getKey() { return \$this->getAttribute(\$this->getKeyName()); } /** * Get the queueable identity for the entity. * * @return mixed */ public function getQueueableId() { return \$this->getKey(); } /** * Get the primary key for the model. * * @return string */ public function getKeyName() { return \$this->primaryKey; } /** * Set the primary key for the model. * * @param string \$key * @return \$this */ public function setKeyName(\$key) { \$this->primaryKey = \$key; return \$this; } /** * Get the table qualified key name. * * @return string */ public function getQualifiedKeyName() { return \$this->getTable().'.'.\$this->getKeyName(); } /** * Get the value of the model's route key. * * @return mixed */ public function getRouteKey() { return \$this->getAttribute(\$this->getRouteKeyName()); } /** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return \$this->getKeyName(); } /** * Determine if the model uses timestamps. * * @return bool */ public function usesTimestamps() { return \$this->timestamps; } /** * Get the polymorphic relationship columns. * * @param string \$name * @param string \$type * @param string \$id * @return array */ protected function getMorphs(\$name, \$type, \$id) { \$type = \$type ?: \$name.'_type'; \$id = \$id ?: \$name.'_id'; return [\$type, \$id]; } /** * Get the class name for polymorphic relations. * * @return string */ public function getMorphClass() { \$morphMap = Relation::morphMap(); \$class = static::class; if (! empty(\$morphMap) && in_array(\$class, \$morphMap)) { return array_search(\$class, \$morphMap, true); } return \$this->morphClass ?: \$class; } /** * Get the number of models to return per page. * * @return int */ public function getPerPage() { return \$this->perPage; } /** * Set the number of models to return per page. * * @param int \$perPage * @return \$this */ public function setPerPage(\$perPage) { \$this->perPage = \$perPage; return \$this; } /** * Get the default foreign key name for the model. * * @return string */ public function getForeignKey() { return Str::snake(class_basename(\$this)).'_id'; } /** * Get the hidden attributes for the model. * * @return array */ public function getHidden() { return \$this->hidden; } /** * Set the hidden attributes for the model. * * @param array \$hidden * @return \$this */ public function setHidden(array \$hidden) { \$this->hidden = \$hidden; return \$this; } /** * Add hidden attributes for the model. * * @param array|string|null \$attributes * @return void */ public function addHidden(\$attributes = null) { \$attributes = is_array(\$attributes) ? \$attributes : func_get_args(); \$this->hidden = array_merge(\$this->hidden, \$attributes); } /** * Make the given, typically hidden, attributes visible. * * @param array|string \$attributes * @return \$this */ public function makeVisible(\$attributes) { \$this->hidden = array_diff(\$this->hidden, (array) \$attributes); if (! empty(\$this->visible)) { \$this->addVisible(\$attributes); } return \$this; } /** * Get the visible attributes for the model. * * @return array */ public function getVisible() { return \$this->visible; } /** * Set the visible attributes for the model. * * @param array \$visible * @return \$this */ public function setVisible(array \$visible) { \$this->visible = \$visible; return \$this; } /** * Add visible attributes for the model. * * @param array|string|null \$attributes * @return void */ public function addVisible(\$attributes = null) { \$attributes = is_array(\$attributes) ? \$attributes : func_get_args(); \$this->visible = array_merge(\$this->visible, \$attributes); } /** * 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 fillable attributes for the model. * * @return array */ public function getFillable() { return \$this->fillable; } /** * Set the fillable attributes for the model. * * @param array \$fillable * @return \$this */ public function fillable(array \$fillable) { \$this->fillable = \$fillable; return \$this; } /** * Get the guarded attributes for the model. * * @return array */ public function getGuarded() { return \$this->guarded; } /** * Set the guarded attributes for the model. * * @param array \$guarded * @return \$this */ public function guard(array \$guarded) { \$this->guarded = \$guarded; return \$this; } /** * Disable all mass assignable restrictions. * * @param bool \$state * @return void */ public static function unguard(\$state = true) { static::\$unguarded = \$state; } /** * Enable the mass assignment restrictions. * * @return void */ public static function reguard() { static::\$unguarded = false; } /** * Determine if current state is "unguarded". * * @return bool */ public static function isUnguarded() { return static::\$unguarded; } /** * Run the given callable while being unguarded. * * @param callable \$callback * @return mixed */ public static function unguarded(callable \$callback) { if (static::\$unguarded) { return \$callback(); } static::unguard(); try { return \$callback(); } finally { static::reguard(); } } /** * Determine if the given attribute may be mass assigned. * * @param string \$key * @return bool */ public function isFillable(\$key) { if (static::\$unguarded) { return true; } // If the key is in the "fillable" array, we can of course assume that it's // a fillable attribute. Otherwise, we will check the guarded array when // we need to determine if the attribute is black-listed on the model. if (in_array(\$key, \$this->getFillable())) { return true; } if (\$this->isGuarded(\$key)) { return false; } return empty(\$this->getFillable()) && ! Str::startsWith(\$key, '_'); } /** * Determine if the given key is guarded. * * @param string \$key * @return bool */ public function isGuarded(\$key) { return in_array(\$key, \$this->getGuarded()) || \$this->getGuarded() == ['*']; } /** * Determine if the model is totally guarded. * * @return bool */ public function totallyGuarded() { return count(\$this->getFillable()) == 0 && \$this->getGuarded() == ['*']; } /** * Remove the table name from a given key. * * @param string \$key * @return string */ protected function removeTableFromKey(\$key) { if (! Str::contains(\$key, '.')) { return \$key; } return last(explode('.', \$key)); } /** * Get the relationships that are touched on save. * * @return array */ public function getTouchedRelations() { return \$this->touches; } /** * Set the relationships that are touched on save. * * @param array \$touches * @return \$this */ public function setTouchedRelations(array \$touches) { \$this->touches = \$touches; return \$this; } /** * Get the value indicating whether the IDs are incrementing. * * @return bool */ public function getIncrementing() { return \$this->incrementing; } /** * Set whether IDs are incrementing. * * @param bool \$value * @return \$this */ public function setIncrementing(\$value) { \$this->incrementing = \$value; return \$this; } /** * Convert the model instance to JSON. * * @param int \$options * @return string */ public function toJson(\$options = 0) { return json_encode(\$this->jsonSerialize(), \$options); } /** * Convert the object into something JSON serializable. * * @return array */ public function jsonSerialize() { return \$this->toArray(); } /** * Convert the model instance to an array. * * @return array */ public function toArray() { \$attributes = \$this->attributesToArray(); return array_merge(\$attributes, \$this->relationsToArray()); } /** * Convert the model's attributes to an array. * * @return array */ public function attributesToArray() { \$attributes = \$this->getArrayableAttributes(); // 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. foreach (\$this->getDates() as \$key) { if (! isset(\$attributes[\$key])) { continue; } \$attributes[\$key] = \$this->serializeDate( \$this->asDateTime(\$attributes[\$key]) ); } \$mutatedAttributes = \$this->getMutatedAttributes(); // 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. foreach (\$mutatedAttributes as \$key) { if (! array_key_exists(\$key, \$attributes)) { continue; } \$attributes[\$key] = \$this->mutateAttributeForArray( \$key, \$attributes[\$key] ); } // 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. foreach (\$this->getCasts() as \$key => \$value) { if (! array_key_exists(\$key, \$attributes) || in_array(\$key, \$mutatedAttributes)) { continue; } \$attributes[\$key] = \$this->castAttribute( \$key, \$attributes[\$key] ); if (\$attributes[\$key] && (\$value === 'date' || \$value === 'datetime')) { \$attributes[\$key] = \$this->serializeDate(\$attributes[\$key]); } } // 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; } /** * 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) { return array_intersect_key(\$values, array_flip(\$this->getVisible())); } return array_diff_key(\$values, array_flip(\$this->getHidden())); } /** * Get an attribute from the model. * * @param string \$key * @return mixed */ public function getAttribute(\$key) { if (array_key_exists(\$key, \$this->attributes) || \$this->hasGetMutator(\$key)) { return \$this->getAttributeValue(\$key); } 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 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 an attribute from the \$attributes array. * * @param string \$key * @return mixed */ protected function getAttributeFromArray(\$key) { if (array_key_exists(\$key, \$this->attributes)) { return \$this->attributes[\$key]; } } /** * Get a relationship value from a method. * * @param string \$method * @return mixed * * @throws \\LogicException */ protected function getRelationshipFromMethod(\$method) { \$relations = \$this->\$method(); if (! \$relations instanceof Relation) { throw new LogicException('Relationship method must return an object of type ' .'Illuminate\\Database\\Eloquent\\Relations\\Relation'); } \$this->setRelation(\$method, \$results = \$relations->getResults()); return \$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; } /** * 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->keyType, ], \$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 the type of cast for a model attribute. * * @param string \$key * @return string */ protected function getCastType(\$key) { return trim(strtolower(\$this->getCasts()[\$key])); } /** * 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 (float) \$value; 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': case 'datetime': return \$this->asDateTime(\$value); case 'timestamp': return \$this->asTimeStamp(\$value); default: return \$value; } } /** * Set a given attribute on the model. * * @param string \$key * @param mixed \$value * @return \$this */ 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)) { \$method = 'set'.Str::studly(\$key).'Attribute'; return \$this->{\$method}(\$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 && (in_array(\$key, \$this->getDates()) || \$this->isDateCastable(\$key))) { \$value = \$this->fromDateTime(\$value); } if (\$this->isJsonCastable(\$key) && ! is_null(\$value)) { \$value = \$this->asJson(\$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'); } /** * Get the attributes that should be converted to dates. * * @return array */ public function getDates() { \$defaults = [static::CREATED_AT, static::UPDATED_AT]; return \$this->timestamps ? array_merge(\$this->dates, \$defaults) : \$this->dates; } /** * Convert a DateTime to a storable string. * * @param \\DateTime|int \$value * @return string */ public function fromDateTime(\$value) { \$format = \$this->getDateFormat(); \$value = \$this->asDateTime(\$value); return \$value->format(\$format); } /** * Return a timestamp as DateTime object. * * @param mixed \$value * @return \\Carbon\\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) { 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 DateTimeInterface) { return new Carbon( \$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 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(\$this->getDateFormat(), \$value); } /** * 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 format for database stored dates. * * @return string */ protected 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; } /** * 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); } /** * Clone the model into a new, non-existing instance. * * @param array|null \$except * @return \\Illuminate\\Database\\Eloquent\\Model */ public function replicate(array \$except = null) { \$defaults = [ \$this->getKeyName(), \$this->getCreatedAtColumn(), \$this->getUpdatedAtColumn(), ]; \$except = \$except ? array_unique(array_merge(\$except, \$defaults)) : \$defaults; \$attributes = Arr::except(\$this->attributes, \$except); \$instance = new static; \$instance->setRawAttributes(\$attributes); return \$instance->setRelations(\$this->relations); } /** * 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); } /** * 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) { \$this->original[\$attribute] = \$this->attributes[\$attribute]; return \$this; } /** * Determine if the model or given attribute(s) have been modified. * * @param array|string|null \$attributes * @return bool */ public function isDirty(\$attributes = null) { \$dirty = \$this->getDirty(); if (is_null(\$attributes)) { return count(\$dirty) > 0; } if (! is_array(\$attributes)) { \$attributes = func_get_args(); } foreach (\$attributes as \$attribute) { if (array_key_exists(\$attribute, \$dirty)) { return true; } } return false; } /** * Get the attributes that have been changed since last sync. * * @return array */ public function getDirty() { \$dirty = []; foreach (\$this->attributes as \$key => \$value) { if (! array_key_exists(\$key, \$this->original)) { \$dirty[\$key] = \$value; } elseif (\$value !== \$this->original[\$key] && ! \$this->originalIsNumericallyEquivalent(\$key)) { \$dirty[\$key] = \$value; } } return \$dirty; } /** * Determine if the new and old values for a given key are numerically equivalent. * * @param string \$key * @return bool */ protected function originalIsNumericallyEquivalent(\$key) { \$current = \$this->attributes[\$key]; \$original = \$this->original[\$key]; return is_numeric(\$current) && is_numeric(\$original) && strcmp((string) \$current, (string) \$original) === 0; } /** * Get all the loaded relations for the instance. * * @return array */ public function getRelations() { return \$this->relations; } /** * Get a specified relationship. * * @param string \$relation * @return mixed */ public function getRelation(\$relation) { return \$this->relations[\$relation]; } /** * Determine if the given relation is loaded. * * @param string \$key * @return bool */ public function relationLoaded(\$key) { return array_key_exists(\$key, \$this->relations); } /** * Set the specific relationship in the model. * * @param string \$relation * @param mixed \$value * @return \$this */ public function setRelation(\$relation, \$value) { \$this->relations[\$relation] = \$value; return \$this; } /** * Set the entire relations array on the model. * * @param array \$relations * @return \$this */ public function setRelations(array \$relations) { \$this->relations = \$relations; return \$this; } /** * Get the database connection for the model. * * @return \\Illuminate\\Database\\Connection */ public function getConnection() { return static::resolveConnection(\$this->getConnectionName()); } /** * Get the current connection name for the model. * * @return string */ public function getConnectionName() { return \$this->connection; } /** * Set the connection associated with the model. * * @param string \$name * @return \$this */ public function setConnection(\$name) { \$this->connection = \$name; return \$this; } /** * Resolve a connection instance. * * @param string|null \$connection * @return \\Illuminate\\Database\\Connection */ public static function resolveConnection(\$connection = null) { return static::\$resolver->connection(\$connection); } /** * Get the connection resolver instance. * * @return \\Illuminate\\Database\\ConnectionResolverInterface */ public static function getConnectionResolver() { return static::\$resolver; } /** * Set the connection resolver instance. * * @param \\Illuminate\\Database\\ConnectionResolverInterface \$resolver * @return void */ public static function setConnectionResolver(Resolver \$resolver) { static::\$resolver = \$resolver; } /** * Unset the connection resolver for models. * * @return void */ public static function unsetConnectionResolver() { static::\$resolver = null; } /** * Get the event dispatcher instance. * * @return \\Illuminate\\Contracts\\Events\\Dispatcher */ public static function getEventDispatcher() { return static::\$dispatcher; } /** * Set the event dispatcher instance. * * @param \\Illuminate\\Contracts\\Events\\Dispatcher \$dispatcher * @return void */ public static function setEventDispatcher(Dispatcher \$dispatcher) { static::\$dispatcher = \$dispatcher; } /** * Unset the event dispatcher for models. * * @return void */ public static function unsetEventDispatcher() { static::\$dispatcher = null; } /** * 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) { \$mutatedAttributes = []; // Here we will extract all of the mutated attributes so that we can quickly // spin through them after we export models to their array form, which we // need to be fast. This'll let us know the attributes that can mutate. if (preg_match_all('/(?<=^|;)get([^;]+?)Attribute(;|\$)/', implode(';', get_class_methods(\$class)), \$matches)) { foreach (\$matches[1] as \$match) { if (static::\$snakeAttributes) { \$match = Str::snake(\$match); } \$mutatedAttributes[] = lcfirst(\$match); } } static::\$mutatorCache[\$class] = \$mutatedAttributes; } /** * Dynamically retrieve attributes on the model. * * @param string \$key * @return mixed */ public function __get(\$key) { return \$this->getAttribute(\$key); } /** * Dynamically set attributes on the model. * * @param string \$key * @param mixed \$value * @return void */ public function __set(\$key, \$value) { \$this->setAttribute(\$key, \$value); } /** * Determine if the given attribute exists. * * @param mixed \$offset * @return bool */ public function offsetExists(\$offset) { return isset(\$this->\$offset); } /** * Get the value for a given offset. * * @param mixed \$offset * @return mixed */ public function offsetGet(\$offset) { return \$this->\$offset; } /** * Set the value for a given offset. * * @param mixed \$offset * @param mixed \$value * @return void */ public function offsetSet(\$offset, \$value) { \$this->\$offset = \$value; } /** * Unset the value for a given offset. * * @param mixed \$offset * @return void */ public function offsetUnset(\$offset) { unset(\$this->\$offset); } /** * Determine if an attribute or relation exists on the model. * * @param string \$key * @return bool */ public function __isset(\$key) { return ! is_null(\$this->getAttribute(\$key)); } /** * Unset an attribute on the model. * * @param string \$key * @return void */ public function __unset(\$key) { unset(\$this->attributes[\$key], \$this->relations[\$key]); } /** * Handle dynamic method calls into the model. * * @param string \$method * @param array \$parameters * @return mixed */ public function __call(\$method, \$parameters) { if (in_array(\$method, ['increment', 'decrement'])) { return call_user_func_array([\$this, \$method], \$parameters); } \$query = \$this->newQuery(); return call_user_func_array([\$query, \$method], \$parameters); } /** * Handle dynamic static method calls into the method. * * @param string \$method * @param array \$parameters * @return mixed */ public static function __callStatic(\$method, \$parameters) { \$instance = new static; return call_user_func_array([\$instance, \$method], \$parameters); } /** * Convert the model to its string representation. * * @return string */ public function __toString() { return \$this->toJson(); } /** * When a model is being unserialized, check if it needs to be booted. * * @return void */ public function __wakeup() { \$this->bootIfNotBooted(); } }`; // Reset `lastIndex` if this regex is defined globally // regex.lastIndex = 0; let m; while ((m = regex.exec(str)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === regex.lastIndex) { regex.lastIndex++; } // The result can be accessed through the `m`-variable. m.forEach((match, groupIndex) => { console.log(`Found match, group ${groupIndex}: ${match}`); }); }

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for JavaScript, please visit: https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions