I'm really new in PHP, our instructor just teaching us C++ OOP and I want to try it on PHP.
I'm creating objects with my class.
class TwitterUser {
private $twittername;
public function TwitterUser($a)
{
$this->twittername = $a;
// echo $this->twittername;
}
}
$reader = new Spreadsheet_Excel_Reader($target_path);
$veriler = $reader->sheets[0]['cells'];
foreach($veriler as $veri)
{
if(!empty($veri[$sutun]) and $veri[$sutun]!="Twitter")
{
$kisiler[] = new TwitterUser(temizle($veri[$sutun]));
}
}
What I want is, if one object has same string with other object in $twittername data member, don't create new object.
This task is usually done using some kind of Model -> database approach (such as Doctrine), in which case you save the model data into database. The database table should be designed to not allow the same name for more than one record and the logic to enforce and error handle this can be built into the model class.
You can achieve the same by pure PHP, but it requires existing instances to be stored somehow so when creating new instances, existing ones can be checked for uniqueness.
You don't want to add the object if the username is test? Basically you can't back out of a constructor. Just add a simple flag to only add "test" user once.
Using your code sample:
$testuserexists = false;
foreach($veriler as $veri)
{
if(!empty($veri[$sutun]) and $veri[$sutun]!="Twitter" && $testuser == false)
{
$kisiler[] = new TwitterUser(temizle($veri[$sutun]));
if ($veri[$sutun] == "Test")
$testuserexists = true;
}
}
Or if you are trying to not have duplicates:
foreach($veriler as $veri)
{
if(!empty($veri[$sutun]) and $veri[$sutun]!="Twitter" && !isset($kisiler[$veri[$sutun]]))
{
$kisiler[$veri[$sutun]] = new TwitterUser(temizle($veri[$sutun]));
}
}
I don't know what the temizle function is supposed to do, but basically you can assign the username as the associative array key and prevent duplicates by adding an isset() to your conditional.
Related
So my problem is : I'm creating a management system with php, html5, css etc(school project).
When a user logs in I save its data in a class. The whole purpose of saving them is to later on use them when a purchase is done, so I can save the product ID and the user ID. But whenever I do the query to the DB I get an Undefined variable error.
This is my class and its methods in it. One is used to save data and one to return them.
class profile_attributes{
public $u_data;
function attributes($u_data){
$this->u_data=$u_data;
}
function attr_get(){
return $u_data;
}
}
How I initially send arguments
$u_data = mysqli_fetch_assoc($result);
$save_info = new profile_attributes()->attributes($u_data);
How I try to get them
$profile = new profile_attributes();
$loged_user = $profile->attr_get();
$user_id = $loged_user['id'];
It doesn't look like you're ever defining $u_data. All you're doing is creating a new instance of profile_attributes and then trying to pull the undefined $u_data.
You are creating two separate instances of your profile_attributes class. An instance's properties and data are specific to itself, and do not get shared if you create a second instance using the new class syntax.
Here's an example of what you're doing. Notice that the data inside the instances are not the same:
class Foo
{
public $data;
}
$instance1 = new Foo();
$instance1->data = array[1, 2, 3];
$instance2 = new Foo();
var_dump($instance1, $instance2);
You need to share the first instance you create and save the database result to the place where you want to retrieve those attributes.
$u_data is not defined, you must precede with $this
class profile_attributes{
public $u_data;
function attributes($u_data){
$this->u_data=$u_data;
}
function attr_get(){
return $this->u_data;
}
}
You were creating an instance to set the attributes and another to access them, use just one for both:
// Use the same instance to set and get atributes
$profile = new profile_attributes();
$u_data = mysqli_fetch_assoc($result);
$save_info = $profile->attributes($u_data);
$loged_user = $profile->attr_get();
$user_id = $loged_user['id'];
Question 1
Is there a name for the pattern below?
class Pattern
{
function createObject(array $data)
{
$object = new Object();
$object->setPropertyA($data['A']);
$object->setPropertyB($data['B']);
$object->setPropertyC($data['C']);
return $object;
}
}
Question 2
Is there a name for the above pattern if it is altered to where $data is acquired inside the method? Specifically code below:
class Pattern2
{
function createObject()
{
$data = $this->service->acquireData();
$object = new Object();
$object->setPropertyA($data['A']);
$object->setPropertyB($data['B']);
$object->setPropertyC($data['C']);
return $object;
}
}
What's the purpose?
My purpose is to seek out a pattern that acquires data from somewhere and returns a ready-to-use single object. To differentiate from the factory method, my purpose is not to decide at run time which polymorphic object to create, but to return a ready to use, populated with data, known single object. I want to know what it is called to help me do better research on the pattern and similar patterns and on how they are used.
I have a few tables configured in Propel, with generated Peer static classes.
My problem is that I need to perform the same search operation on different but similar tables. Those tables have different Peer classes as it is how Propel works. This situation leads to duplicated code regarding to the queries that are performed on these tables.
I was wondering if there is some construct (avoiding the use of the function eval) that might help me in this case; I really would like to avoid writing duplicated code that performs the same exact calls on just different static Peer classes.
example code snippet from a (very long) method of a class I am writing:
$criteria = new Criteria();
$criteria->add(FoobarPeer::CONTRACTNR,$data['contractnr']);
$result = FoobarPeer::doSelect($criteria);
if(count($result) > 1){
throw new FoobarException("status: more than one row with the specified contractnr.");
}
if(count($result) == 0){
// no object with given contractnr. Create new one.
$obj = $this->factory->createORM("foobar");
$obj->setCreatedAt(time());
} else {
// use and update existing object.
$obj = $result[0];
}
As you can see I managed to write a factory method for the row object, but I could not find a way to do the same for static classes. In other words, I would like to have the access to the static classes dynamic and not in a way that is an ugly workaround.
Any ideas?
thanks :)
I'm not really sure I fully understand what you are asking, but here's a solution to what I think you are asking:
function orm_for($type) {
return strtolower($type);
}
function peer_for($type) {
return ucfirst($type)."Peer";
}
function exception_for($type) {
return ucfirst($type)."Exception";
}
function query($type, $data) {
$peer = $peer_for($type);
$exception = $exception_for($type);
$obj = null;
$criteria = new Criteria();
$criteria->add($peer::CONTRACTNR, $data["contractnr"]);
$result = $peer::doSelect($criteria);
if(count($result) > 1) {
throw new $exception("status: more than one row with the specified contractnr.");
} else if(count($result) == 0) {
$obj = $this->factory->createORM(orm_for($type));
$obj->setCreatedAt(time());
} else {
$obj = $result[0];
}
}
I think the code is self-explanatory. Let me know whether or not I interpreted your question correctly.
A live example (just a POC) can be found here
You should be able to use behaviors to achieve what you're trying to do. You can use behaviors to add custom code to the generated peer objects. See here.
Among other things, your behaviors can implement the following methods:
staticAttributes() // add static attributes to the peer class
staticMethods() // add static methods to the peer class
You should be able to use these to add the code you want to the peers. You only need to worry about writing the code once. Propel will duplicate the code during the code generation process, but this shouldn't be too much of a concern, as a lot of the generated is duplicated anyway. At least the duplication is only introduced by an automated process.
I've an ORM model (PHP Active Record), say, for a blogging system. I've something that's a post model that stores the number of likes. The post could either be a picture or quote (say), and they are different tables (and hence models).
The schema is that a post holds data like number of shares, likes, description, etc. along with either a picture or a quote.
So when writing getters for the post model I'm having to write
public function getX() {
if ($this->isPicture()) {
return $this->picture->getX();
}
else if ($this->isQuote()) {
return $this->quote->getX()
}
else {
return self::DEFAULT_X
}
}
I'm currently having to write this structure for many getter. Is there something I can do to avoid that?
PS: Tagged as PHP because that's my code in.
EDIT
Changed comments to code.
This is a model (and a corresponding table in the DB) that has more data than just a picture and quote. Example, description that's part of the post and doesn't reside on either the picture or the quote.
There's tables for pictures and quotes.
Using PHP Active Record and each of the three classes extends the generic model class provided by PHP Active Record.
The picture model has it's own data. Same for quote.
To expand on the idea of the Strategy pattern mentioned in the comments:
class Post {
// get the correct 'strategy'
public function getModel() {
if ($this->isPicture()) {
return $this->picture;
}
if ($this->isQuote()) {
return $this->quote;
}
return null;
}
// using the strategy
public function getX() {
$model = $this->getModel();
if (null === $model) {
return self::DEFAULT_X;
}
return $model->getX();
}
}
Each strategy would presumably implement the same interface as the Post class for exposing those getters. Even better would be to provide a default strategy (rather than returning null) and have that return the default values. That way, the null check in each getter becomes redundant.
An alternative approach to this is a very basic form of metaprogramming. The idea is that you go a level higher than calling your methods by hand, and let the code do it for you.
(Assume that the method definitions are all part of Post)
public function getX($model = null) {
if ($model) return $model->getX();
else return self::DEFAULT_X;
}
// usage
$postModel->getX($pictureModel);
What's happening here is that, in this single instance of getX in your Post model, you're passing in the name of another class, and executing the `getX' method on that instance (if it exists and is callable).
You can extend this in other ways. For example, maybe you don't want to pass an instance in, when the method can do it anyway:
public function getX($model_name = null) {
if ($model_name && $class_exists($model_name) && is_callable(array($model_name, 'getX')) {
$model = new $model_name;
return $model->getX();
} else {
return self::DEFAULT_X;
}
}
// usage
$postModel->getX('Picture');
In this instance, you pass the model in as a string, and the method will do the rest. While this makes it quicker to get what you want, you might find that you don't want to work with fresh instances all the time (or you can't), so there's a bit of a trade-off with this 'convenient' way.
That still doesn't fully solve your problem, though, since you still have to repeat that for each getter, over and over again. Instead, you can try something like this:
public function __call($method, $args) {
$class = $args[0];
if (class_exists($class) && is_callable(array($class, $method))) {
$model = new $class;
return $model->$method();
}
}
// usage
$postModel->getX('Picture');
$postModel->getY('Quote');
$postModel->getZ('Picture');
If you call a function that doesn't exist on the Post model, that magic method will be called, and it'll fire up a new instance of the model name you supply as an argument, and call the getWhatever method on it, if it exists.
It's important to note that you must not define these getters in Post, unless you want to override the methods in the other classes.
There is still the problem of this creating new instances all the time, though, and to remedy this you can use a bit of dependency injection. This means that you let the Post class contains a list of other instances of classes that it wants to use in future, so you can add and remove them at will.
This is what I would consider the actual solution, with the other examples hopefully showing how I've got here (will edit to clarify things, of course).
public $models = array();
public function addModel($instance) {
$this->models[get_class($instance)] = $instance;
}
public function __call($method, $args) {
$class = $args[0];
if (array_key_exists($class, $this->models)) {
$model = $this->models[$class];
if (is_callable(array($model, $method)) {
return $model->$method();
}
}
}
// usage
$this->addModel($pictureModel);
$this->addModel($quoteModel);
$this->getX('Picture');
$this->getY('Quote');
Here, you're passing in your existing instances of models into the Post class, which then stores them in an array, keyed by the name of the class. Then, when you use the class as described in the last example, instead of creating a new instance, it will use the instance it has already stored. The benefit of this is that you might do things to your instances that you'd want reflected in the Post model.
This means that you can add as many new models as you like that need to plug into Post, and the only thing you need to do is inject them with addModel, and implement the getters on those models.
They all require you to tell the class what models to call at some point or another. Since you have an array of dependent models, why not add a way to get everything?
public function __call($method, $args) {
$class = $args[0];
if (array_key_exists($class, $this->models)) {
$model = $this->models[$class];
if (is_callable(array($model, $method)) {
return $model->$method();
}
} elseif ($class === 'all') {
// return an array containing the results of each method call on each model
return array_map(function($model) use ($method) {
if (is_callable(array($model, $method) return $model->$method();
}, $this->models);
}
}
// usage
$postModel->getX('all');
Using this, you'll get an array containing the return values of each getX method on each model you added with addModel. You can create pretty powerful functions and classes that do all this stuff without you having to repeat tedious logic.
I have to mention that these examples are untested, but at the very least I hope the concept of what you can do has been made clear.
Note:
The same thing can be applied to __GET and __SET methods, too, which are used for accessing properties. It's also worth saying that there may be the slight risk of a library already using these magic methods, in which case you'll need to make the code a little more intelligent.
I'm writing my first application with Zendframework.
My question is about the Model–View–Controller (MVC) architectural pattern.
I currently have a model with refer to a database table.
Here's the classes that I currently have :
Model_Person
Model_PersonMapper
Model_DbTable_Person
Now, I see a lot of examples on the net, but all of them are simple cases of insert/update/delete.
In my situation, I have to check if a person exists, and if it doesn't, I have to insert it and retrieve the ID (I know save return the Id, but it's not exactly what I have to do, this is and example).
It's quit simple, but I want to know where to put the database logic for all the others specific cases. Some others cases might involve checks across other tables or ... whatever !
Should I add all the specific functions in my Model_XXXXMapper with something that would be very specific with the current validation/process that I want to do? like a function getIdOfThePersonByNameOrInsertIfNotExists() (sample name of course!!!)
Or should it reside in the controller with some less specifics access to my model would be validated?
In other word, where do I put all the data specifics functions or check ?
I think the real work should occur in your model objects, not in the controller. Any selects/creates that start with the person table would be in the DbTable_Person object, things like:
// DbTable_Person
// returns sets of or single Person objects
public function createByName( $name ) // perhaps throws exception if name already exists
public function findById( $id )
public function findByName( $name )
public function findHavingAccount( $account_id ) // references another table
// controller
// with your example, like what Galen said,
// I would let the controller handle this logic
$person = $person_table->findByName($name);
if ( !$person ) {
$person = $person_table->createByName($name);
}
if ( !$person ) { throw new Zend_Exception('huh?'); }
$id = $person->id; // you wanted the ID
I would definitely split the function up into search/create functions.
Here's a basic implementation...
$personTG = new Model_PersonTableGateway;
if ( !$person = $personTG->findByName( $name ) ) {
$person = new Model_Person;
$person->name = $name;
// other variables
$newPersonId = $personTG->create( $person ); // creates a new person
}
I use table gateway. You can substitute your class for the TG.
You can have the create() function return just the id of the newly created person, or the entire person...it's up to you.
You might be interested in Zend_Validate_Db_NoRecordExists and its sister. If you are using Zend_Form you can add this validator to your form element. Many folks use Zend_Form to validate and filter data before they reach the domain model.
If you are not using Zend_Form, you can simply use this validation class in your service layer. A simple service class could be something like
`
class Service_Person_Validate
{
public function creatable($data)
{ // return true|false
}
}