Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are actually two issues here. The first is that your interface design is too specific. The other is that you're mixing the data model with the database access layer, and that's making your code more complicated.</p> <p>I've skipped some details in my examples for brevity (and the code is untested), but I presume you can fill in the gaps.</p> <h3>Generalize the Interface</h3> <p>The first order of business is to make your interface more general. Instead of using one method that does everything, split <code>county</code>, <code>skill</code>, etc. into different methods:</p> <pre><code>class userFilter { protected $db; protected $params; protected function __construct() { $this-&gt;db = new database_connection(); } public static function create() { return new userFilter(); } public function addCounty($county) { // For simplicity, 'county' is the column name $this-&gt;params['county'][] = $county; // Return $this to enable method chaining, used below return $this; } public function addSkill($skill) { $this-&gt;params['skill'][] = $skill; return $this; } public function addHometown($hometown) { return $this; } public function fetchUsers() { return '$data'; } } </code></pre> <p>With the above interface, you can optionally add any number of parameters, and each (potentially) has its own logic associated with validating input, writing SQL conditions, etc.</p> <h3>Database Access Layer</h3> <p>The hard part of this solution is writing the actual SQL. For that, you need to know a few things:</p> <ol> <li>Which columns do you want (the <code>SELECT</code> clause)?</li> <li>Which rows do you want (the <code>WHERE</code> clause)?</li> <li>What does your schema look like, or more specifically, which column names correspond to which parameters?</li> <li>Do you want to select a single parameter multiple times? (I've assumed multiple)</li> </ol> <p>The easy way to solve this problems is by using arrays, because you can easily <code>foreach</code> over them to include whichever may be specified, and you can use their key=>value pairing to maintain associations with respect to your database schema.</p> <p>Now when you go to write the query for <code>fetchUsers()</code> you can iterate over <code>$this-&gt;params</code> using <a href="http://www.php.net/manual/en/function.array-keys.php" rel="nofollow noreferrer"><code>array_keys($this-&gt;params)</code></a> as the column names and <code>$this-&gt;params</code> as the data. That might look something like this:</p> <pre><code>// Select all columns present in $this-&gt;params $sql = 'SELECT id, '.implode(', ', array_keys($this-&gt;params)); $sql .= 'FROM table_name WHERE '; $where = array() foreach($this-&gt;params as $column =&gt; $ids){ $where[] = $column . ' IN ('.implode(', ', $ids).')'; } $sql .= implode(' AND ', $where); </code></pre> <p>With a more complicated schema that requires joins, you may need a switch to handle each join and join condition, or you may find a way to cram that into an array. You'll also need extra logic to make sure you don't add an empty <code>WHERE</code> clause or other silly things, but the meat of it is there.</p> <h3>Using the Interface</h3> <p>When the above code is self-contained in a class, fetching data is very simple.</p> <pre><code>$results = userFilter::create() -&gt;addCounty($county) -&gt;addHometown($hometown) -&gt;addSkill($skill) -&gt;addSkill($skill) -&gt;addSkill($skill) -&gt;fetchUsers(); </code></pre> <p>If you want to conditionally use certain methods:</p> <pre><code>$userFilter = userFilter::create(); if(isset($_GET['hometown'])){ $userFilter-&gt;addHometown($_GET['hometown']); } if(isset($_GET['skill'])){ $userFilter-&gt;addSkill($_GET['skill']); } $userFilter-&gt;fetchUsers(); </code></pre> <h3>Extra</h3> <ul> <li>More on <a href="https://stackoverflow.com/questions/293353/fluent-interfaces-method-chaining">method chaining / fluent interfaces</a></li> <li>You may want to look into an ORM such as <a href="http://www.doctrine-project.org/" rel="nofollow noreferrer">Doctrine</a> or <a href="http://www.propelorm.org/" rel="nofollow noreferrer">Propel</a></li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload