{"id":28754223,"url":"https://github.com/zeroasterisk/cakephp-behavior-rangeable","last_synced_at":"2025-06-17T01:08:00.877Z","repository":{"id":137479247,"uuid":"1156546","full_name":"zeroasterisk/cakephp-behavior-rangeable","owner":"zeroasterisk","description":"CakePHP Behavior for lat/lon Ranged Searches","archived":false,"fork":false,"pushed_at":"2011-11-08T18:43:33.000Z","size":159,"stargazers_count":10,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-15T01:28:22.409Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeroasterisk.png","metadata":{"files":{"readme":"readme.textile","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-12-10T16:26:10.000Z","updated_at":"2016-01-24T13:10:05.000Z","dependencies_parsed_at":"2023-03-14T09:30:38.978Z","dependency_job_id":null,"html_url":"https://github.com/zeroasterisk/cakephp-behavior-rangeable","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zeroasterisk/cakephp-behavior-rangeable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroasterisk%2Fcakephp-behavior-rangeable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroasterisk%2Fcakephp-behavior-rangeable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroasterisk%2Fcakephp-behavior-rangeable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroasterisk%2Fcakephp-behavior-rangeable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeroasterisk","download_url":"https://codeload.github.com/zeroasterisk/cakephp-behavior-rangeable/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeroasterisk%2Fcakephp-behavior-rangeable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260269458,"owners_count":22983647,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-17T01:07:58.903Z","updated_at":"2025-06-17T01:08:00.855Z","avatar_url":"https://github.com/zeroasterisk.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"h1. Rangeable Behavior for CakePHP\n\nAfter some really shoddy implementations of this functionality as components and whatnot, I finally made a clean and simple behavior which you can use naturally as a custom find type, even within paginate().\n\nIt will also sort the results for you based on distance to the source lat/lon, injecting a 'distance' field and setting as the key of the array.\n\nh2. Requirements\n\n* CakePHP 1.3.x. (untested with the 1.2.x series)\n* Model for a table which has lat/lon fields _(field names setable)_\n* Optionally, a Zip Model for zip code --\u003e lat/lon lookup _(model and field names setable)_\n\nh2. Installation\n\ngit clone into app/plugins/rangeable\n\non your model, add @Rangeable@ to your $actsAs array:\n\n\u003cpre\u003e\u003ccode\u003e\u003c?php\n# ./app/models/job.php\nclass Job extends AppModel {\n\tvar $actsAs = array('Rangeable.Rangeable');\n}\n?\u003e\u003c/code\u003e\u003c/pre\u003e\n\nh2. Extra Setup\n\nIdeally you'd have a @Zip@ model which maps to a table with at least the fields: @zip@, @lat@, @lon@.  That facilitates the automatic lookup by a zip from the conditions array, without it, we don't know how to lookup the lat/lon for the condition, so you'd have to include it in the search terms.\n\nNeed a zips table?  Contact me.  Have a great zips table?  Contact me.  _(I have one, US only, but I'm sure it's out of date...  hook me up)_   \n\nh2. Usage\n\nThe behavior exposes a custom find type (kudos to \"cloud behavior\":https://github.com/felixge/debuggable-scraps/blob/master/cakephp/behaviors/cloud/cloud.php for pointing me in the right direction) which is super simple to use.\n\n\u003cpre\u003e\u003ccode\u003e\u003c?php\n# ./app/controller/jobs_controller.php\nclass JobsController extends AppController {\n\t\n\t// simple example\n\tfunction near_lat_lon($lat='38.113972', $lon='-85.837158') {\n\t\t$jobs = $this-\u003eJob-\u003efind('range', array(\n\t\t\t'conditions' =\u003e array(\n\t\t\t\t'Job.is_active' =\u003e 1, // whatever other conditions you like\n\t\t\t\t),\n\t\t\t'limit' =\u003e 10,\n\t\t\t// following parameters are optional and can be set in the settings on the behavior\n\t\t\t'lat' =\u003e $lat,\n\t\t\t'lon' =\u003e $lon,\n\t\t\t'range' =\u003e 10, // look for all jobs within 10 miles, default = 20\n\t\t\t'range_out_till_count_is' =\u003e false,\n\t\t\t));\n\t\t$this-\u003eset(compact('jobs', 'zip'));\n\t}\n\t\n\t// simple example of translating a zip to a lat/lon automatically\n\tfunction near_zip($zip='40206') {\n\t\t$jobs = $this-\u003eJob-\u003efind('range', array(\n\t\t\t'conditions' =\u003e array(\n\t\t\t\t'Job.zip' =\u003e $zip,\n\t\t\t\t'Job.is_active' =\u003e 1, // whatever other conditions you like\n\t\t\t\t),\n\t\t\t'limit' =\u003e 10,\n\t\t\t));\n\t\t$this-\u003eset(compact('jobs', 'zip'));\n\t}\n\t\n\t// an example of automatically increasing the range until we hit a minimum number of results\n\tfunction near_zip_at_least($zip='40206', $at_least=20) {\n\t\t$jobs = $this-\u003eJob-\u003efind('range', array(\n\t\t\t'conditions' =\u003e array(\n\t\t\t\t'Job.zip' =\u003e $zip,\n\t\t\t\t'Job.is_active' =\u003e 1, // whatever other conditions you like\n\t\t\t\t),\n\t\t\t'limit' =\u003e 10,\n\t\t\t// following parameters are optional and can be set in the settings on the behavior\n\t\t\t'range' =\u003e 20, // starting range = 20 miles\n\t\t\t'range_out_till_count_is' =\u003e $at_least,\n\t\t\t'range_out_increment' =\u003e 20, // increasing range by this increment\n\t\t\t'range_out_limit' =\u003e 20, // maximum tries - max range = range + (range_out_increment * range_out_limit)\n\t\t\t'order_by_distance' =\u003e false,\n\t\t\t));\n\t\t$this-\u003eset(compact('jobs', 'zip'));\n\t\t/*\n\t\tThis should return at least $at_least results, assuming they can be found.\n\t\tBasically, while count of results \u003c $at_least\n\t\t\t$range = $range + $range_out_increment\n\t\tThat way, you can start narrow on results and expand untill you return at lest X results\n\t\t*/\n\t}\n\t\n\t// an example which sorts the results by distance\n\tfunction near_zip_sorted($zip='40206', $at_least=20) {\n\t\t$jobs = $this-\u003eJob-\u003efind('range', array(\n\t\t\t'conditions' =\u003e array(\n\t\t\t\t'Job.zip' =\u003e $zip,\n\t\t\t\t'Job.is_active' =\u003e 1, // whatever other conditions you like\n\t\t\t\t),\n\t\t\t'limit' =\u003e 10,\n\t\t\t// following parameters are optional and can be set in the settings on the behavior\n\t\t\t'range' =\u003e 20, // starting range = 20 miles\n\t\t\t'range_out_till_count_is' =\u003e $at_least,\n\t\t\t'range_out_increment' =\u003e 20, // increasing range by this increment\n\t\t\t'range_out_limit' =\u003e 20, // maximum tries - max range = range + (range_out_increment * range_out_limit)\n\t\t\t'order_by_distance' =\u003e true, // resorts the results by distance\n\t\t\t'limitless' =\u003e true, // initial find doesn't have a limit, so resulst can be sorted correctly\n\t\t\t// ^ note: because we are incrementing our search from a small range, this shouldn't be too slow, but \n\t\t\t// ^ if it is, just set to an integer as the new limit, or false to disable\n\t\t\t));\n\t\t$this-\u003eset(compact('jobs', 'zip'));\n\t}\n\t\n\t// and a paginate() example\n\tfunction near_zip_paginated($zip='40206') {\n\t\t$this-\u003epaginate = array(\n\t\t\t'type' =\u003e 'range',\n\t\t\t'conditions' =\u003e array(\n\t\t\t\t'Job.zip' =\u003e $zip,\n\t\t\t\t'Job.is_active' =\u003e 1, // whatever other conditions you like\n\t\t\t\t),\n\t\t\t'limit' =\u003e 10,\n\t\t\t// following parameters are optional and can be set in the settings on the behavior\n\t\t\t'range' =\u003e 20, // starting range = 20 miles\n\t\t\t'range_out_till_count_is' =\u003e 20, // expand search range until we have at least 20 results (note, the limit is less, so we really will only get 10)\n\t\t\t'range_out_increment' =\u003e 20, // increasing range by this increment\n\t\t\t'range_out_limit' =\u003e 20, // maximum tries - max range = range + (range_out_increment * range_out_limit)\n\t\t\t'order_by_distance' =\u003e true, // resorts the results by distance\n\t\t\t'limitless' =\u003e true, // initial find doesn't have a limit, so resulst can be sorted correctly\n\t\t\t// ^ note: because we are incrementing our search from a small range, this shouldn't be too slow, but \n\t\t\t// ^ if it is, just set to an integer as the new limit, or false to disable\n\t\t\t);\n\t\t$jobs = $this-\u003epaginate('Job');\n\t\t$this-\u003eset(compact('jobs', 'zip'));\n\t}\n}\n?\u003e\u003c/code\u003e\u003c/pre\u003e\n\nh2. License\n\nOffered under an MIT license.  Do what you need.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeroasterisk%2Fcakephp-behavior-rangeable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeroasterisk%2Fcakephp-behavior-rangeable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeroasterisk%2Fcakephp-behavior-rangeable/lists"}