Added Unicode support for regular expressions in the Router.
+
Added support for removing hidden folders in the delete_files helper
+
fetchGlobal in the Request class now supports applying filters to arrays of data, not just the first item.
+
file validation now works with arrays of files.
+
URI class now supports a setSilent() method that will disable the throwing of Exceptions.
+
New argument to URI::getSegment() that allows us to change the default value returned if nothing exists.
+
Implemented a withResource() in Image so that you can use method chaining instead of using the provided getResource() (used in tests). To just compress your image.
+
Cookies and headers can be copied from the global Response object when doing a redirect using the new withCookies() and withHeaders() methods.
+
Support for special prefix 「hex2bin:」 which can be used with $key parameter in Encryption class or in .env file.
+
+
Bugs Fixed:
+
+
Fixed location for the SQLite3 database which by default will be now located in a writable folder instead of the public folder.
+
Fixed bug where force_https could add https:// a second time.
+
Fixed a bug with CurlRequest that could result in incorrect 「100 Continue」 headers.
+
Image::save() bug fixed when $target parameter was null
+
fixes for set_checkbox() and set_radio() when the $default parameter is set to true
+
fix for result object handling in Model class .
+
fixed escape character SQLite database
+
fix for inserts on Postgres and Entities when the primary key was null
+
CLI scripts can now correctly recognize dashes within arguments.
+
CURLRequest now properly sets content length with multipart data
+
Misc. stability improvements for the ImageMagick handler
+
setting validation errors within a config file should now work
+
Unicode characters are not escaped when saving JSON from Entities.
+
redirecting with a custom HTTP code should work correctly now
+
Time::setTimezone now working correctly
+
added full outer join support for Postgres
+
some cast items in the Entity (like array, json) were not being set correctly during a fill() process.
+
Fixed bug in Image GD handler that would try to compress images twice in certain cases
+
Ensure get translation output logic work on selected locale, dashed locale, and fallback 「en」
+
Fix is_unique/is_not_unique validation called on POST/PUT via API in Postgresql
+
Added $arguments parameter to after() and before() in FilterInterface. This is a breaking change, so all code implementing the FilterInterface must be updated
+
Fixed a bug where filter arguments were not passed to after()
New URL helper function url_to() which creates absolute URLs based on controllers.
+
New Model option: $useAutoIncrement which when set to false allows you to provide your own primary key for each record in the table. Handy when we want to implement 1:1 relation or use UUIDs for our model.
+
New URL helper function url_is() which allows you to check the current URL to see if matches the given string.
+
Services now have their config parameters strictly typehinted. This will ensure no one will pass a different config instance. If you need to pass a new config with additional properties, you need to extend that particular config.
+
Support for setting SameSite attribute on Session and CSRF cookies has been added. For security and compatibility with latest browser versions, the default setting is Lax.
+
Guessing file extensions from mime type in Config\Mimes::guessExtensionFromType now only reverse searches the $mimes array if no extension is proposed (i.e., usually not for uploaded files).
+
The getter functions for file extensions of uploaded files now have different fallback values ($this->getClientExtension() for UploadedFile->getExtension() and '' for UploadedFile->guessExtension()). This is a security fix and makes the process less dependent on the client.
+
The Cache FileHandler now allows setting the file permissions mode via Config\Cache
+
+
Changes:
+
+
System messages defined in system/Language/en/ are now strictly for internal framework use and are not covered by backwards compatibility (BC) promise. Users may use these messages in their applications but at their own risks.
+
+
Bugs Fixed:
+
+
Fixed a bug in Entity class where declaring class parameters was preventing data propagation to the attributes array.
+
Handling for the environment variable encryption.key has changed. Previously, explicit function calls, like getenv('encryption.key') or env('encryption.key') where the value has the special prefix hex2bin: returns an automatically converted binary string. This is now changed to just return the character string with the prefix. This change was due to incompatibility with handling binary strings in environment variables on Windows platforms. However, accessing $key using Encryption class config remains unchanged and still returns a binary string.
+
Config\Services (in app/Config/Services.php) now extends CodeIgniter\Config\BaseService to allow proper discovery of third-party services.
+
+
Deprecations:
+
+
Deprecated BaseCommand::getPad in favor of BaseCommand::setPad.
+
Deprecated CodeIgniter\Controller::loadHelpers in favor of helper function.
+
Deprecated Config\Format::getFormatter in favor of CodeIgniter\Format\Format::getFormatter
+
Deprecated CodeIgniter\Security\Security::CSRFVerify in favor of CodeIgniter\Security\Security::verify
+
Deprecated CodeIgniter\Security\Security::getCSRFHash in favor of CodeIgniter\Security\Security::getHash
+
Deprecated CodeIgniter\Security\Security::getCSRTokenName in favor of CodeIgniter\Security\Security::getCSRTokenName
+
Deprecated Config\App::$CSRFTokenName in favor of Config\Security::$tokenName
+
Deprecated Config\App::$CSRFHeaderName in favor of Config\Security::$headerName
+
Deprecated Config\App::$CSRFCookieName in favor of Config\Security::$cookieName
+
Deprecated Config\App::$CSRFExpire in favor of Config\Security::$expire
+
Deprecated Config\App::$CSRFRegenerate in favor of Config\Security::$regenerate
+
Deprecated Config\App::$CSRFRedirect in favor of Config\Security::$redirect
+
Deprecated Config\App::$CSRFSameSite in favor of Config\Security::$samesite
+
Deprecated migrate:create command in favor of make:migration command.
+
Deprecated CodeIgniter\Database\ModelFactory in favor of CodeIgniter\Config\Factories::models()
+
Deprecated CodeIgniter\Config\Config in favor of CodeIgniter\Config\Factories::config()
+
Deprecated CodeIgniter\HTTP\Message::getHeader in favor of header() to prepare for PSR-7
+
Deprecated CodeIgniter\HTTP\Message::getHeaders in favor of headers() to prepare for PSR-7
+
Deprecated Config\Cache::$storePath in favor of Config\Cache::$file['storePath']
Autoloader::loadLegacy() method was previously used for migration of non-namespaced classes in transition to CodeIgniter v4. Since 4.1.0, this support was removed.
+
Deprecated Model::fillPlaceholders(array $rules, array $data) method, use fillPlaceholders(array $rules, array $data) from Validation instead.
Use the list command to get a list of available commands and their descriptions, sorted by categories. You may also use spark list –simple to get a raw list of all available commands, sorted alphabetically.
CodeIgniter4 now comes equipped with generators to ease the creation of stock controllers, models, entities,
+etc. You can also scaffold a complete set of files with just one command.
All built-in generators reside under the Generators namespace when listed using phpsparklist.
+To view the full description and usage information on a particular generator, use the command:
+
>phpsparkhelp<generator_command>
+
+
+
where <generator_command> will be replaced with the command to check.
--session: Generate a migration file for database sessions.
+
--table: Set the table name to use for database sessions. Defaults to ci_sessions.
+
--dbgroup: Set the database group for database sessions. Defaults to default group.
+
--namespace: Set the root namespace. Defaults to value of APP_NAMESPACE.
+
--suffix: Append the component suffix to the generated class name.
+
--force: Set this flag to overwrite existing files on destination.
+
+
+
備註
+
Do you need to have the generated code in a subfolder? Let’s say if you want to create a controller
+class to reside in the Admin subfolder of the main Controllers folder, you will just need
+to prepend the subfolder to the class name, like this: phpsparkmake:controlleradmin/login. This
+command will create the Login controller in the Controllers/Admin subfolder with
+a namespace of App\Controllers\Admin.
+
+
+
備註
+
Working on modules? Code generation will set the root namespace to a default of APP_NAMESPACE.
+Should you need to have the generated code elsewhere in your module namespace, make sure to set
+the --namespace option in your command, e.g., phpsparkmake:modelblog--namespaceAcme\Blog.
+
+
+
警告
+
Make sure when setting the --namespace option that the supplied namespace is a valid
+namespace defined in your $psr4 array in Config\Autoload or defined in your composer autoload
+file. Otherwise, code generation will be interrupted.
+
+
+
警告
+
Use of migrate:create to create migration files is now deprecated. It will be removed in
+future releases. Please use make:migration as replacement. Also, please use make:migration--session
+to use instead of the deprecated session:migration.
Sometimes in our development phase we are creating functionalities by groups, such as creating an Admin group.
+This group will contain its own controller, model, migration files, or even entities. You may be tempted to type
+each generator command one-by-one in the terminal and wishfully thinking it would be great to have a single generator
+command to rule them all.
+
Fret no more! CodeIgniter4 is also shipped with a dedicated make:scaffold command that is basically a
+wrapper to the controller, model, entity, migration, and seeder generator commands. All you need is the class
+name that will be used to name all the generated classes. Also, individual options supported by each
+generator command are recognized by the scaffold command.
+
Running this in your terminal:
+
phpsparkmake:scaffolduser
+
+
+
will create the following classes:
+
+
App\Controllers\User;
+
App\Models\User;
+
App\Database\Migrations\<somedatehere>_User; and
+
App\Database\Seeds\User.
+
+
To include an Entity class in the scaffolded files, just include the --returnentity to the command
+and it will be passed to the model generator.
Like Services, Factories are an extension of autoloading that helps keep your code
+concise yet optimal, without having to pass around object instances between classes. At its
+simplest, Factories provide a common way to create a class instance and access it from
+anywhere. This is a great way to reuse object states and reduce memory load from keeping
+multiple instances loaded across your app.
+
Anything can be loaded by Factories, but the best examples are those classes that are used
+to work on or transmit common data. The framework itself uses Factories internally, e.g., to
+make sure the correct configuration is loaded when using the Config class.
+
Take a look at Models as an example. You can access the Factory specific to Models
+by using the magic static method of the Factories class, Factories::models(). Because of
+the common path structure for namespaces and folders, Factories know that the model files
+and classes are found within Models, so you can request a model by its shorthand base name:
Factories takes as a second parameter an array of option values (described below).
+These directives will override the default options configured for each component.
+
Any more parameters passed at the same time will be forwarded on to the class
+constructor, making it easy to configure your class instance on-the-fly. For example, say
+your app uses a separate database for authentication and you want to be sure that any attempts
+to access user records always go through that connection:
The default behavior might not work for every component. For example, say your component
+name and its path do not align, or you need to limit instances to a certain type of class.
+Each component takes a set of options to direct discovery and instantiation.
+
+
+
+
+
+
+
+
+
Key
+
Type
+
Description
+
Default
+
+
+
+
component
+
string or null
+
The name of the component (if different than the static method). This can be used to alias one component to another.
+
null (defaults to the component name)
+
+
path
+
string or null
+
The relative path within the namespace/folder to look for classes.
+
null (defaults to the component name)
+
+
instanceOf
+
string or null
+
A required class name to match on the returned instance.
+
null (no filtering)
+
+
getShared
+
boolean
+
Whether to return a shared instance of the class or load a fresh one.
+
true
+
+
preferApp
+
boolean
+
Whether a class with the same basename in the App namespace overrides other explicit class requests.
To set default component options, create a new Config files at app/Config/Factory.php
+that supplies options as an array property that matches the name of the component. For example,
+if you wanted to ensure that all Filters used by your app were valid framework instances,
+your Factories.php file might look like this:
The Factories class has a static method to allow runtime option configuration: simply
+supply the desired array of options using the setOptions() method and they will be
+merged with the default values and stored for the next call:
Factories’s magic static call takes as a second parameter an array of option values.
+These directives will override the stored options configured for each component and can be
+used at call time to get exactly what you need. The input should be an array with option
+names as keys to each overriding value.
+
For example, by default Factories assumes that you want to locate a shared instance of
+a component. By adding a second parameter to the magic static call, you can control whether
+that single call will return a new or shared instance:
+
$users=Factories::models('UserModel',['getShared'=>true]);// Default; will always be the same instance
+$other=Factories::models('UserModel',['getShared'=>false]);// Will always create a new instance
+
You could modify the config file to detect the environment and automatically update the defaultGroup value to the correct one by adding the required logic within the class’ constructor:
Returns the current database connection from $db. Useful for
+accessing ConnectionInterface methods that are not directly
+available to the Query Builder, like insertID() or errors().
CodeIgniter supports creating databases straight from your favorite terminal using the dedicated db:create
+command. By using this command it is assumed that the database is not yet existing. Otherwise, CodeIgniter
+will complain that the database creation has failed.
+
To start, just type the command and the name of the database (e.g., foo):
+
phpsparkdb:createfoo
+
+
+
If everything went fine, you should expect the Database"foo"successfullycreated. message displayed.
+
If you are on a testing environment or you are using the SQLite3 driver, you may pass in the file extension
+for the file where the database will be created using the --ext option. Valid values are db and
+sqlite and defaults to db. Remember that these should not be preceded by a period.
+
phpsparkdb:createfoo--extsqlite
+// will create the db file in WRITEPATH/foo.sqlite
+
+
+
+
備註
+
When using the special SQLite3 database name :memory:, expect that the command will still
+produce a success message but no database file is created. This is because SQLite3 will just use
+an in-memory database.
CodeIgniter supports creating databases straight from your favorite terminal using the dedicated db:create
+command. By using this command it is assumed that the database is not yet existing. Otherwise, CodeIgniter
+will complain that the database creation has failed.
+
To start, just type the command and the name of the database (e.g., foo):
+
phpsparkdb:createfoo
+
+
+
If everything went fine, you should expect the Database"foo"successfullycreated. message displayed.
+
If you are on a testing environment or you are using the SQLite3 driver, you may pass in the file extension
+for the file where the database will be created using the --ext option. Valid values are db and
+sqlite and defaults to db. Remember that these should not be preceded by a period.
+
phpsparkdb:createfoo--extsqlite
+// will create the db file in WRITEPATH/foo.sqlite
+
+
+
+
備註
+
When using the special SQLite3 database name :memory:, expect that the command will still
+produce a success message but no database file is created. This is because SQLite3 will just use
+an in-memory database.
If you want to automate the generation of seed data, you can use
+the Faker library.
+
To install Faker into your project:
+
>composerrequire--devfakerphp/faker
+
+
+
After installation, an instance of Faker\Generator is available in the main Seeder
+class and is accessible by all child seeders. You must use the static method faker()
+to access the instance.
In addition to explicit registrars defined by the $registrars property, you may also
+define registrars in any namespace using the Config/Registrars.php file, if discovery
+is enabled in Modules. These files work the same as the classes
+described above, using methods named for each configuration class you wish to extend.
$array (array) – The array to be sorted (passed by reference).
+
$sortColumns (array) – The array keys to sort after and the respective PHP
+sort flags as an associative array.
+
+
+
+
傳回:
Whether sorting was successful or not.
+
+
+
傳回型態:
bool
+
+
+
+
+
This method sorts the elements of a multidimensional array by the values of one or
+more keys in a hierarchical way. Take the following array, that might be returned
+from, e.g., the find() function of a model:
Now sort this array by two keys. Note that the method supports the dot-notation
+to access values in deeper array levels, but does not support wildcards:
The $players array is now sorted by the 『order』 value in each players』
+『team』 subarray. If this value is equal for several players, these players
+will be ordered by their 『position』. The resulting array is:
In the same way, the method can also handle an array of objects. In the example
+above it is further possible that each 『player』 is represented by an array,
+while the 『teams』 are objects. The method will detect the type of elements in
+each nesting level and handle it accordingly.
Users may use the $id parameter on their own, but are not required to do so.
+The function uses this parameter internally to track the flattened keys. If users
+will be supplying an initial $id, it will be prepended to all keys.
+
// using the same data from above
+$flattened=array_flatten_with_dots($arrayToFlatten,'foo_');
+
+// $flattened is now:
+[
+ 'foo_personal.first_name'=>'john',
+ 'foo_personal.last_name'=>'smith',
+ 'foo_personal.age'=>'26',
+ 'foo_personal.address'=>'US',
+ 'foo_other_details'=>'marines officer',
+];
+
Note that $path must exist and be a readable image format supported by the data: protocol.
+This function is not recommended for very large files, but it provides a convenient way
+of serving images from your app that are not web-accessible (e.g., in public/).
You will notice that the Helloworld Controller is extending the BaseController. you can also extend the CodeIgniterController if you do not need the functionality of the BaseController.
+
The BaseController provides a convenient place for loading components and performing functions that are needed by all your controllers. You can extend this class in any new controller.
+
For security reasons be sure to declare any new utility methods as protected or private.:
Controller Filters allow you to perform actions either before or after the controllers execute. Unlike events,
-you can very simply choose which URI’s in your application have the filters applied to them. Incoming filters may
-modify the Request, while after filters can act on and even modify the Response, allowing for a lot of flexibility
+you can choose the specific URIs in which the filters will be applied to. Incoming filters may
+modify the Request while after filters can act on and even modify the Response, allowing for a lot of flexibility
and power. Some common examples of tasks that might be performed with filters are:
Performing CSRF protection on the incoming requests
If a Response instance is returned, the Response will be sent back to the client and script execution will stop.
+This can be useful for implementing rate limiting for APIs. See Throttler for an
example.
The AJAX requests depends on the X-Requested-With header, which in some cases is not sent by default in XHR requests via JavaScript (i.e., fetch). See the AJAX Requests section on how to avoid this problem.
Three filters are bundled with CodeIgniter4: Honeypot, CSRF, and DebugToolbar.
+
+
備註
+
The filters are executed in the declared order that is defined in the config file, but there is one exception to this and it concerns the DebugToolbar, which is always executed last. This is because DebugToolbar should be able to register everything that happens in other filters.
An instance of the request class already populated for you if the current class is a descendant of
CodeIgniter\Controller and can be accessed as a class property:
The isAJAX() method depends on the X-Requested-With header, which in some cases is not sent by default in XHR requests via JavaScript (i.e., fetch). See the AJAX Requests section on how to avoid this problem.
You can check the HTTP method that this request represents with the method() method:
// Returns 'post'$method=$request->getMethod();
-
By default, the method is returned as a lower-case string (i.e. 『get』, 『post』, etc). You can get an
-uppercase version by passing in true as the only parameter:
+
By default, the method is returned as a lower-case string (i.e., 『get』, 『post』, etc). You can get an
+uppercase version by wrapping the call in str_to_upper():
If the incoming request has a CONTENT_TYPE header set to 「application/json」, you can also use getVar() to get
+the JSON stream. Using getVar() in this way will always return an object.
+
Get Specific Data from JSON
+
You can get a specific piece of data from a JSON stream by passing a variable name into getVar() for the
+data that you want or you can use 「dot」 notation to dig into the JSON to get data that is not on the root level.
If you want the result to be an associative array instead of an object, you can use getJsonVar() instead and pass
+true in the second parameter. This function can also be used if you can’t guarantee that the incoming request will have the
+correct CONTENT_TYPE header.
+
//With the same request as above
+$data=$request->getJsonVar('fizz');
+//$data->buzz = "baz"
+
+$data=$request->getJsonVar('fizz',true);
+//$data = ["buzz" => "baz"]
+
+
+
+
備註
+
See the documentation for dot_array_search() in the Array helper for more information on 「dot」 notation.
+
Retrieving Raw data (PUT, PATCH, DELETE)
Finally, you can grab the contents of php://input as a raw stream with getRawInput():
You can get access to any header that was sent with the request with the getHeaders() method, which returns
+
You can get access to any header that was sent with the request with the headers() method, which returns
an array of all headers, with the key as the name of the header, and the value is an instance of
CodeIgniter\HTTP\Header:
If you only need a single header, you can pass the name into the getHeader() method. This will grab the
+
If you only need a single header, you can pass the name into the header() method. This will grab the
specified header object in a case-insensitive manner if it exists. If not, then it will return null:
// these are all equivalent
-$host=$request->getHeader('host');
-$host=$request->getHeader('Host');
-$host=$request->getHeader('HOST');
+$host=$request->header('host');
+$host=$request->header('Host');
+$host=$request->header('HOST');
You can always use hasHeader() to see if the header existed in this request:
Class ReferenceIncomingRequest Class to make
-the current request’s headers available.
-The headers are any SERVER data that starts with HTTP_ , like HTTP_HOST . Each message
+the current request’s headers available.
+
The headers are any SERVER data that starts with HTTP_, like HTTP_HOST. Each message
is converted from it’s standard uppercase and underscore format to a ucwords and dash format.
The preceding HTTP_ is removed from the string. So HTTP_ACCEPT_LANGUAGE becomes
Accept-Language.
Routing rules are defined in the app/config/Routes.php file. In it you’ll see that
+
Routing rules are defined in the app/Config/Routes.php file. In it you’ll see that
it creates an instance of the RouteCollection class that permits you to specify your own routing criteria.
Routes can be specified using placeholders or Regular Expressions.
A route simply takes the URI on the left, and maps it to the controller and method on the right,
@@ -486,9 +488,28 @@
This would prefix the 『users』 and 『blog」 URIs with 「admin」, handling URLs like /admin/users and /admin/blog.
-It is possible to nest groups within groups for finer organization if you need it:
This would handle the URL at admin/users/list. Note that options passed to the outer group() (for example
+namespace and filter) are not merged with the inner group() options.
+
At some point, you may want to group routes for the purpose of applying filters or other route
+config options like namespace, subdomain, etc. Without necessarily needing to add a prefix to the group, you can pass
+an empty string in place of the prefix and the routes in the group will be routed as though the group never existed but with the
+given route config options.
The value for the filter must match one of the aliases defined within app/Config/Filters.php. You may also supply parameters to be passed to the filter’s before() and after() methods:
+
The value for the filter must match one of the aliases defined within app/Config/Filters.php. You may also supply arguments to be passed to the filter’s before() and after() methods:
When a user visits the root of your site (i.e. example.com) the controller to use is determined by the value set by
+
When a user visits the root of your site (i.e., example.com) the controller to use is determined by the value set by
the setDefaultController() method, unless a route exists for it explicitly. The default value for this is Home
which matches the controller at /app/Controllers/Home.php:
// example.com routes to app/Controllers/Welcome.php
@@ -896,9 +922,9 @@
Nginx is the second most widely used HTTP server for web hosting.
+Here you can find an example configuration using PHP 7.3 FPM (unix sockets) under Ubuntu Server.
+
This configuration enables URLs without “index.php” in them and using CodeIgniter’s “404 - File Not Found” for URLs ending with “.php”.
In some scenarios you will want to load the framework without actually running the whole
+application. This is particularly useful for unit testing your project, but may also be
+handy for using third-party tools to analyze and modify your code. The framework comes
+with a separate bootstrap script specifically for this scenario: system/Test/bootstrap.php.
+
Most of the paths to your project are defined during the bootstrap process. You may use
+pre-defined constants to override these, but when using the defaults be sure that your
+paths align with the expected directory structure for your installation method.
CodeIgniter 4.0.5 introduces a setting for the cookie SameSite attribute. Prior versions did not set this
+attribute at all. The default setting for cookies is now Lax. This will affect how cookies are handled in
+cross-domain contexts and you may need to adjust this setting in your projects. Separate settings in app/Config/App.php
+exists for Response cookies and for CSRF cookies.
The HTTP layer is moving towards PSR-7 compliance. Towards this end
+Message::getHeader() and Message::getHeaders() are deprecated and should be replaced
+with Message::header() and Message::headers() respectively. Note that this pertains
+to all classes that extend Message as well: Request, Response and their subclasses.
+
Additional related deprecations from the HTTP layer:
+
+
Message::isJSON: Check the 「Content-Type」 header directly
+
Request[Interface]::isValidIP: Use the Validation class with valid_ip
+
Request[Interface]::getMethod(): The $upper parameter will be removed, use str_to_upper()
+
Request[Trait]::$ipAddress: This property will become private
+
Request::$proxyIPs: This property will be removed; access config('App')->proxyIPs directly
+
Request::__construct(): The constructor will no longer take Config\App and has been made nullable to aid transition
+
Response[Interface]::getReason(): Use getReasonPhrase() instead
+
Response[Interface]::getStatusCode(): The explicit int return type will be removed (no action required)
+
+
ResponseInterface
+
This interface intends to include the necessary methods for any framework-compatible response class.
+A number of methods expected by the framework were missing and have noe been added. If you use any
+classes the implement ResponseInterface directly they will need to be compatible with the
+updated requirements. These methods are as follows:
To facilitate use of this interface these methods have been moved from the framework’s Response into a ResponseTrait
+which you may use, and DownloadResponse now extends Response directly to ensure maximum compatibility.
+
ConfigServices
+
Service discovery has been updated to allow third-party services (when enabled via Modules) to take precedence over core services. Update
+app/Config/Services.php so the class extends CodeIgniter\Config\BaseService to allow proper discovery of third-party services.
Autoloader::loadLegacy() method was originally for transition to CodeIgniter v4. Since 4.1.0,
+this support was removed and this method should not be used.
+
Model::fillPlaceholders
+
Replace any use of this method with its equivalent version from Validation instead.
The following example shows a common usage pattern within your controllers.
-
if(!$foo=cache('foo'))
+
if(!$foo=cache('foo')){
- echo'Saving to the cache!<br />';
- $foo='foobarbaz!';
+ echo'Saving to the cache!<br />';
+ $foo='foobarbaz!';
- // Save into the cache for 5 minutes
- cache()->save('foo',$foo,300);
+ // Save into the cache for 5 minutes
+ cache()->save('foo',$foo,300);}echo$foo;
@@ -395,32 +398,32 @@