I'm using cakePHP 2.3 to build an application with a restaurant database. Now, the person before me has saved restaurant details in a table called 'locations' which has a row for cuisine which has multiple values in one column, like 1 location can have chinese, indian, korean etc.
If I fetch data using post and retrieve from the column using exact value like this:
$restaurant_cuisine = $this->params['url']['restaurant_cuisine'];
$data = $this->Location->findAllByCuisine($restaurant_cuisine);
Then it is displaying value only if it exactly matches...eg:If i post "north indian,chinese,mughlai" then it matches it word to word.
I want a query where I can search Chinese and all restaurants having chinese display even if they have other cuisines.
Please help!
you can't use magic find type because they don't allow LIKE conditions. You must use full syntax:
$data = $this->Location->find(
'all',
array(
'conditions' => array('Location.cuisine LIKE' => "%$restaurant_cuisine%")
));
Related
I have a table named booking which has a column contact_number.
What will be the best practice to insert multiple contact numbers for single booking? I have attached an image in which 1 entry has contact numbers separated with commas and other made 2 entries for same booking. Last thing i think of is to create a separate table for contacts. What will be the best way?
There will be an array for multiple contacts, I am coding in codeigniter.
There are 3 ways that I can think of:
Using a separate table and having a one to many relationship with the booking
best for scalability, indexing, architecture
Using a JSON string to store them in one field
not easily searchable, if you plan not to use it somewhere except the booking page, it's better
Using multiple fields like up to 5 (contact number 1, contact number 2..)
if you think to assign a limit for that, and you may sometime search for a number
Choose wisely. Think what you (will) need and what you plan to do first, then choose the method.
if I was you I would make a customer table with customer information. If they [ the customer ] have multiple contact numbers you can make a "more information" column (something like this) and when they book again you kown who they are, they will already havea record. It will give you a feel to remember who they are (is somthing like market strategies [maybe?])
Create an array and encode with JSON
$contact_number = array(
'mobile' => '+1 32313213',
'fax' => '+1 32432432',
'phone' => '+1 8984234234'
);
$booking_contact = json_encode($contact_number);
Now you can insert $booking_contact into your database. If you want to use it just decode JSON pass true for associative array
//Suppose $row is containing you row result
$booking_contact = json_decode($row['booking_contact'], true);
echo $booking_contact['mobile']; // Output +1 32313213
echo $booking_contact['fax']; // Output +1 32313213
echo $booking_contact['phone']; // Output +1 8984234234
There is an unspoken rule in RDBMS - never ever use commaseparated strings for the purpose of m:n relations - it is simply violating the first normal form.
For more information regarding this matter take a look here
In your case you need :
a Table - booking (as you already mentioned)
a Table - contact (i assume you already have one as you already have numbers for) a Table
a Table - booking_contact with fields (booking_id, contact_id)
Now if you want all contacts from a booking ID you simply write in Codeigniter style
$query = $this->db
->select('*')
->from('contact c')
->join('booking_contact bc', 'c.contact_id = bc.contact_id', 'left')
->join('booking b', 'bc.booking_id = b.booking_id')
->where('b.booking_id', 1)
->get();
I need to make an import method that takes the CSV file and imports everything in the database.
I've done the parsing with one of Laravel's CSV addons and it works perfectly giving me a big array of values set as:
[
'col1_name' => 'col1 value',
'col2_name' => 'col2 value',
'col3_name' => 'col3 value,
'...' => '...'
]
This is also perfect since all the column names fit my model which makes the database inserts a breeze.
However - a lot of column values are strings that i'd like to set as separate tables/relations. For example, one column contains the name of the item manufacturer, and i have the manufacturer table set in my database.
My question is - what's the easy way to go through the imported CSV and swap the strings with the corresponding ID from the relationship table, making it compatible with my database design?
Something that would make the imported line:
[
'manufacturer' => 'Dell',
]
into:
[
'manufacturer' => '32',
]
I know i could just do a foreach loop comparing the needed values with values from the relationship models but I'm sure there's an easier and more clean way of doing it.
I don't think theres any "nice" way to do this - you'll need to look up each value for "manufacturer" - the question is, how many queries will you run to do so?
A consideration you need to make here is how many rows you will be importing from your CSV file.
You have a couple of options.
1) Querying 1 by 1
I'm assuming you're going to be looping through every line of the CSV file anyway, and then making a new model? In which case, you can add an extra database call in here;
$model->manufacturer_id = Manufacturer::whereName($colXValue)->first()->id;
(You'd obviously need to put in your own checks etc. here to make sure manufacturers exist)
This method is fine relatively small datsets, however, if you're importing lots and lots of rows, it might end up sluggish with alot of arguably unnecessary database calls.
2) Mapping ALL your Manufacturers
Another option would be to create a local map of all your Manufacturers before you loop through your CSV lines;
$mappedManufacturers = Manufacturer::all()->pluck('id', 'name');
This will make $mappedManufacturers an array of manufacturers that has name as a key, id as a value. This way, when you're building your model, you can do;
$model->manufacturer_id = $mappedManufacturers[$colXValue];
This method is also fine, unless you have tens of thousands of Manufacturers!
3) Where in - then re-looping
Another option would be to build up a list of manufacturer names when looping through your CSV lines, going to the database with 1 whereIn query and then re-looping through your models to populate the manufacturer ID.
So in your initial loop through your CSV, you can temporarily set a property to store the name of the manufacturer, whilst adding it to another array;
$models = collect();
$model->..... = ....;
$model->manufacturer = $colXValue;
$models->push($colXValue);
Then you'll end up with a collection of models. You then query the database for ONLY manufacturers which have appeared:
$manufacturers = Manufacturer::whereIn('name', $models->lists('manufacturer'))->get()->keyBy('name')->toArray();
This will give you array of manufacturers, keyed by their name.
You then loop through your $models collection again, assigning the correct manufacturer id using the map;
$model->manufacturer_id = $manufacturers[$model->manufacturer];
Hopefully this will give you some ideas of how you can achieve this. I'd say the solution mostly depends on your use case - if this was going to be a heavy duty ask - I'd definitely Queue it and be tempted to use Option 1! :P
I have a movies table (has data from a legacy project) with the field genre which contains values serialized by PHP like:
a:3:{i:0;s:9:"Animation";i:1;s:9:"Adventure";i:2;s:5:"Drama";}
I'm working in a search page, & I need to find all unique genres of the current search result to be used as a filter in the page,
as an example, if the search result was these 2 movies:
The Dark Knight (action, crime, drama)
Black Knight (fantasy, adventure, comedy)
I want to know the combination of there genres, which will be:
['action', 'crime', 'drama', 'fantasy', 'adventure', 'comedy']
how to get the genres array? (I'm using Yii2).
You should unserialize your data
$data = 'a:3:{i:0;s:9:"Animation";i:1;s:9:"Adventure";i:2;s:5:"Drama";}';
$data = unserialize($data);
print_r($data);
and you will get
Array
(
[0] => Animation
[1] => Adventure
[2] => Drama
)
If you need to search the entire table for "Drama" to decide which shows/movies to display, you could always use wildcards in your search
select * from table where column like '%Drama%'
but of course make sure to take appropriate database precautions.
Suppose you have a serialize string that have various values in different position and you need to search from serialized field. You want particular key’s value using MySQL query. It is very easy with MySQL “%like%” statement but “%like%” fetches more matches which you do not require.
Search from serialized field: Suppose you have a following serialize string in database:
a:9:{s:2:"m1";s:4:"1217";s:2:"m2";s:8:"9986-961";s:2:"m3";s:19:"1988-03-07 00:00:00";s:2:"m4";s:0:"";s:2:"m5";s:0:"";s:2:"m6";s:0:"";s:2:"m7";s:3:"104";s:2:"m8";s:6:"150000";s :2:"m9";s:18:"Ok Then, Yes It Is";}
And you need the row in which the m9 value is ‘Yes It Is’.
So the sql will be like:
SELECT * FROM table WHERE field REGEXP '.*"array_key";s:[0-9]+:".array_value.".*'
test code
SELECT * FROM table WHERE field REGEXP '.*"m9";s:[0-9]+:".Ok Then, Yes It Is.".*'
I have been struggling with the proper way to extract the data I need. I am using MySQL with PHP and will be putting the data into a list format. My only problem is with the actual query itself. Here is how the DB is setup:
I have a 'chars' table for characteristics with the columns 'id', 'descrip', and 'class'.
I have a 'animal' table with the columns 'animal_id', 'charlist', ...
In 'chars' id is an incremented int, 'descrip' and 'class' are text/strings.
'id' and 'descrip' are different for every row but 'class' will be the same sometimes having a value like 'habitat', 'size', 'diet', et cetra.
What I am going for is a list that will look like this:
Habitatundergroundarctic
Dietfishinsectsomnivore
Here is where I start to have trouble. On a 'Details' page I am showing all of the data specific to a certain animal (whichever is clicked) and to reference the 'characteristics' each animal has it's own 'charlist' value in the database. This value is a string of numbers that reference the 'chars' table, like '2,55,67,90,122'.
So I've pulled all my (specific) animal data to a php variable on the page that I want to supply with the information. Now I need to use the 'charlist' data from that animal to lookup and list the characteristics relative to the animal.
My queries are looking like this, and I know I'm waaay off:
SELECT * FROM 'chars' LEFT INNER JOIN 'animals' ON chars.id IN (animals.charlist) WHERE ...
I've tried a lot of different ways and this is where I get lost. My brain is telling me to join the tables, find the numbers that are in the charlist WHERE animal.animal_id = mysql_real_escape_string($animal_id) - and of course MySQL tells me I can't do it this way.
I know that for the titles of the lists I'll probably have to do this with a GROUP BY condition.
Any help on the query and query syntax would be great. I'm fairly new to MySQL and I'm very happy and eager to learn how to do this right.
Thanks for reading.
a IN (x) returns true if (and only if) a equals x.
If x is a string (even one delimited by commas), then the statement will only be true if a is equal to that same string. That is, 123 IN ('123,456,789') is false. Note that this is not the same as passing multiple arguments such as 123 IN (123, 456, 789).
In MySQL, one could instead use FIND_IN_SET(), which expects a string delimited by commas. However, storing delimited lists in database columns is a really bad idea. You should instead define a third, relationship, table in which you store foreign keys into both of your existing tables: (animal_id, characteristic_id):
CREATE TABLE animal_characteristics (
PRIMARY KEY (animal_id, characteristic_id),
FOREIGN KEY (animal_id) REFERENCES animal (animal_id),
FOREIGN KEY (characteristic_id) REFERENCES chars (id)
) SELECT animal.animal_id, chars.id AS characteristic_id
FROM animal JOIN chars ON FIND_IN_SET(chars.id, animal.charlist)
;
Then you can do:
SELECT *
FROM animals
JOIN animal_characteristics USING (animal_id)
JOIN chars ON chars.id = animal_characteristics.characteristic_id
WHERE ...
I am currently planning out how a table will look in MYSQL database. I want to do something like the below, where plant1 and plant2 would be the columns, and then each of those plants would have characteristics assigned to them as you see below.
Is it possible to display info this way in MYSQL?
Array (
[plant1] => Array (
[image_url] => http://www.example.com/image1.png
[botanical_name] => Foo
[common_name] => Bar
),
[plant2] => Array (
[image_url] => http://www.example.com/image2.png
[botanical_name] => Foo
[common_name] => Bar
)
Well, i don't suggest that, but you can insert php array to that field and then parse it in php when you are getting data from database. So the content of that field would be like that:
$plant1 = array('plant1' => array('image_url' => 'http://www.example.com/image1.png', 'botanical_name' => 'Foo', 'common_name' => 'Bar'));
$plant2 = array('plant2' => array('image_url' => 'http://www.example.com/image2.png', 'botanical_name' => 'Foo', 'common_name' => 'Bar'));
You can insert $plant1 $plant2 to your mysql fields and then print it like this to get wanted result:
print_r(array_merge($mysql_plant1, $mysql_plant2));
Function array_merge connects arrays together.
You can do it storing as a serialized value (http://www.php.net/manual/en/function.serialize.php) but it's not a good idea.
For that you will have to create another table to store the caracteristics of each plant like:
**plants**
id_plant
name
**plants_ccharacteristics**
id_plant_characteristic
fk_plant
name
value
In that way you can store it properly.
As an extra point, that structure you want to store looks quite good for use NoSQL databases like MongoDB.
Your table design is flawed. What you should have is Plant being a row, with each item in the array being a column in the plants table.
If you need Plants to be a column in another table, then assign the first column of the plants table to be a unique, auto-incrementing key and then put that key in the column of the other table. Eg:
**Garden_Plants**
gp_key
gp_garden_id
gp_plant_id <-- p_id from Plants_Table
**Plants_Table**
p_id
p_botanical_name
p_common_name
p_image_url
you would have a table called plants, this would have a related table called plantDetails that has a referencing ID from the plant in question.
this would give 1 plant, with multiple references
This doesn't seem optimised for querying the database, however if you have a specific reason for doing it this way please let us know..
A more optimised solution:
Have a table called Plants, with fields ID, image_url, botanical_name, common_name.
Store all plants in that table. ID is a unique Identifier for that plant, probably set with autonumber so cannot be duplicated
If you need to store some kind of relationship between 2 plants, have a table called plant_relationships with fields for something like plant_ID_1 and plant_ID_2
You can then query your full list of plants directly, or query the relationships table to find plants related to other plants
If you want multiple values in one mysql field, i would suggest to put your information in one string before storing it in the database. Each substring need to be separated by a character that will not be used in the substrings.
$value1 = aaa
$value2 = bbb
$value3 = ccc
$valueAll = aaa:bbb:ccc
When you get the data out of the DB, you will need to split the string with the : or the other character selected.