Category Archives: CakePHP

Working nginx cakephp 3

Use bellow on sites-enabled

server {
listen 80;
listen 443 ssl;
server_name cake3.app;
root "/home/vagrant/Cake3/my_app2/webroot";
rewrite 301 cake3.app$1 permanent;

index index.html index.htm index.php;

charset utf-8;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt  { access_log off; log_not_found off; }

access_log off;
error_log  /var/log/nginx/cake3.app-error.log error;

sendfile off;

client_max_body_size 100m;

location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}

location ~ /\.ht {
deny all;
}

ssl_certificate     /etc/nginx/ssl/homestead.app.crt;
ssl_certificate_key /etc/nginx/ssl/homestead.app.key;
}

Generate unique slugs in CakePHP

I believe it was WordPress who came up with the term “slug”. It has been adopted by many other systems though, and it basically means the following: a unique identifier which can be used in a URL to create a permalink to a page.

At least, that’s my interpretation of it. In this article I will show you how you can generate a unique slug easily when working with the CakePHP Framework.

Since the slug should be unique across records in the same database table, the best place to store slug-generating functionality is in the AppModel, which is, strictly speaking, the only business logic layer that may access the database.

If you haven’t got an AppModel created yet, add one in /app/app_model.PHP. You may fill it with the following code:

  1. <?php
  2. class AppModel extends Model {
  3. function createSlug ($string, $id=null) {
  4. $slug = Inflector::slug ($string,'-');
  5. $slug = low ($slug);
  6. $i = 0;
  7. $params = array ();
  8. $params ['conditions']= array();
  9. $params ['conditions'][$this->name.'.slug']= $slug;
  10. if (!is_null($id)) {
  11. $params ['conditions']['not'] = array($this->name.'.id'=>$id);
  12. }
  13. while (count($this->find ('all',$params))) {
  14. if (!preg_match ('/-{1}[0-9]+$/', $slug )) {
  15. $slug .= '-' . ++$i;
  16. } else {
  17. $slug = preg_replace ('/[0-9]+$/', ++$i, $slug );
  18. }
  19. $params ['conditions'][$this->name . '.slug']= $slug;
  20. }
  21. return $slug;
  22. }
  23. }
  24. ?>
  25. Download this code: /code/generate_unique_slugs_in_cakephp1.txt

Goal

What this code does, is providing a method, createSlug (), which can be accessed from all models in your application. It’ll normalize the string, make it URL-friendly and last but not least, it makes it unique.

To demonstrate the “unique” part, let’s say we’ve got a record with the title “I love CakePHP“. The createSlug method will turn this into “i-love-cakePHP“. Human friendly and search-engine friendly.
What happens when I wish to create two more items in my database called “I love CakePHP“? The createSlug method will generate the following two slugs: i-love-cakePHP-1 and i-love-cakePHP-2.

This way users can bookmark your URLs and always end up in the right place, even though the titles of your records may be similar.

How to use?

It’s simple, really. Since the method is created in the AppModel base class, you can invoke it from every model in your application. When saving a record, you can simply call…

  1. $slug = $this->generateSlug ('my title');
  2. Download this code: /code/generate_unique_slugs_in_cakephp2.txt

…from within your models, or…

  1. $slug = $this->MyModel->generateSlug ('my title');
  2. Download this code: /code/generate_unique_slugs_in_cakephp3.txt

…from within your controllers, right before you insert new data.

Note that you have to pass the id from the current record when you’re modifying existing records, so it can exclude that from its check, like this:

  1. $slug = $this->generateSlug ('my title', 10);
  2. Download this code: /code/generate_unique_slugs_in_cakephp4.txt

How does it work?

  1. $slug = Inflector::slug ($string,'-');
  2. $slug = low ($slug);
  3. Download this code: /code/generate_unique_slugs_in_cakephp5.txt

These lines normalize the string into a human friendly, easily readable slug.

[php]
$params = array ();
$params [‘conditions’]= array();
$params [‘conditions’][$this->name.’.slug’]= $slug;
if (!is_null($id)) {
$params [‘conditions’][‘not’] = array($this->name.’.id’=>$id);
}
[/php]

This code will create the $params array, which is used in checking wether or not a slug already exists.

[php]

while (count($this->find (‘all’,$params))) {
if (!preg_match (‘/-{1}[0-9]+$/’, $slug )) {
$slug .= ‘-‘ . ++$i;
} else {
$slug = preg_replace (‘/[0-9]+$/’, ++$i, $slug );
}
$params [‘conditions’][$this->name . ‘.slug’]= $slug;
}

[/php]

 

 

This while loop will append the slug with an incrementing value until no results are returned from the Model::find method. This ensures the final slug string is unique.

I’ve used this method in multiple projects now, and have found it very useful. I hope it’ll be of some use to you as well, and would like to know what you think this method can do better. Let me know in the comments!

CakePHP delete records

Deleting Data

CakePHP’s Model class offers a few ways to delete records from your database.

delete

delete(int $id = null, boolean $cascade = true);

Deletes the record identified by $id. By default, also deletes records dependent on the record specified to be deleted.

For example, when deleting a User record that is tied to many Recipe records (User ‘hasMany’ or ‘hasAndBelongsToMany’ Recipes):

  • if $cascade is set to true, the related Recipe records are also deleted if the model’s dependent-value is set to true.
  • if $cascade is set to false, the Recipe records will remain after the User has been deleted.

If your database supports foreign keys and cascading deletes, it’s often more efficient to rely on that feature than CakePHP’s cascading. The one benefit to using the cascade feature of Model::delete() is that it allows you to leverage behaviors and model callbacks:

$this->Comment->delete($this->request->data('Comment.id'));

You can hook custom logic into the delete process using the beforeDelete and afterDelete callbacks present in both Models and Behaviors. See Callback Methods for more information.

deleteAll

deleteAll(mixed $conditions, $cascade = true, $callbacks = false)

deleteAll() is similar to delete(), except that deleteAll() will delete all records that match the supplied conditions. The $conditions array should be supplied as a SQL fragment or array.

  • conditions Conditions to match
  • cascade Boolean, Set to true to delete records that depend on this record
  • callbacks Boolean, Run callbacks

Return boolean True on success, false on failure.

Example:

// Delete with array conditions similar to find()
$this->Comment->deleteAll(array('Comment.spam' => true), false);

If you delete with either callbacks and/or cascade, rows will be found and then deleted. This will often result in more queries being issued.

Note

deleteAll() will return true even if no records are deleted, as the conditions for the delete query were successful and no matching records remain.