Jump to content

Adding pages through the API


jrtderonde
 Share

Recommended Posts

Hey,

I'm working around a module that adds pages in my ProcessWire installation. The pages are added based on a JSON array that will be imported through a page save. Everything works fine except for when the pages are added. I get the following error

Integrity constraint violation: 1062 Duplicate entry '3e215ecd6774fd99c2b0eb5cadf36a07-1269' for key 'name_parent_id'

I'm using the following code/loop to generate the pages.

// Loop through the files
foreach ($p->importFile as $file)
{
    // Set the file location
    $name = $file->data["basename"];
    $path = $p->importFile->path;
    $location = $path . $name;

    // Get the file
    $json = file_get_contents($location);
    $json = json_decode($json);

    // Loop through the rows of the import
    foreach ($json->ttEntityDelAddrLink as $client)
    {
        // Create new page
        $new = new Page();

        // Create unique hash
        $unique = md5(date("Y-m-d H:i:s") . "-" . $client->CustomerCode);

        // Set some variables for the new page
        $new->setOutputFormatting(false);
        $new->template = "_client";
        $new->parent = $p;

        // Create hash
        $new->title = $client->DelAddressName;
        $new->name = $unique;

        // Page specific fields
        $new->company = $client->DelAddressName;
        $new->companyId = $client->CustomerCode;
        $new->city = $client->DelAddressCity;
        $new->address = $client->DelAddressStreet;
        $new->postcode = $client->DelAddressZipCode;
        $new->country = $countries[$client->DelAddressCountryCode];

        // Save the page
        $new->save();
    }

    // Exit for debugging
    exit;
}


Does anybody know what's wrong?

Link to comment
Share on other sites

Ok, but that's why I'm trying to prevent with the hash as $page->name. I'm using the ID of the customer combined with a timestamp to generate a md5 hash that's "unique". (See the code, I'm pretty sure it should work). 

Also, the next entry in the array has a complete different customer id. So it should be "impossible" to be duplicated.

I'm using this code within a pageSaveHook (module). Could this be a problem? Furthermore, the array counts 11000+ entries, could it be that this is a problem? The platform is hosted on a stable and fast VPS and I cranked up the PHP execution time to 10 minutes, so it shouldn't cause any serious trouble.

Link to comment
Share on other sites

1 hour ago, jrtderonde said:

Ok, but that's why I'm trying to prevent with the hash as $page->name. I'm using the ID of the customer combined with a timestamp to generate a md5 hash that's "unique". (See the code, I'm pretty sure it should work). 

What @BitPoet said. In other words, PHP is fast, MySQL is fast. So, there is no guarantee that you will have only 1 page created per second (your date), or even per microsecond! That leaves you with uniqueness dependent only on the customer ID ($client->CustomerCode). If you can guarantee that customer IDs are unique and that they only appear once per data set, (your JSON array) then you would be fine. The fact that you are getting a SQL error tells us that either your customer IDs are not unique and/or one customer ID is appearing more than once in your data set (i.e., it may be uniqe to the customer, but not the data set). If the database says so, then it must be so ;). Let me illustrate (non-unique customer ID and/or replicated customer ID):

 

$clientCustomerCode = 12345;// replicating repeated use of customer ID
$p = $pages->get(1722);

for ($i=0; $i < 30; $i++) { 
	// Create new page
	$new = new Page();
	// Create unique hash {no guarantee this will be unique if same customer ID used}
	$unique = md5(date("Y-m-d H:i:s") . "-" . $clientCustomerCode);
        // even these (microseconds) do not guarantee uniqueness throughout
	#$unique = round(microtime(true) * 1000) . "-". $clientCustomerCode;
	#$unique = microtime(true) . "-". $clientCustomerCode;
	#$unique = microtime() . "-". $clientCustomerCode;

	echo $i . ': ' . $unique . '<br>';// display 'uniqueness'; you should see duplicates here

	// Set some variables for the new page
	//$new->setOutputFormatting(false);// not needed for a new page (I think)
	$new->template = "basic-page";
	$new->parent = $p;   
	// Create hash
	$new->title = "Title " . rand(5,15);// just for testing
	$new->name = $unique;// not really unique!
	// Save the page
	#$new->save();// you'll get PDO error here within a second

}

Using the above code, you'll be hit by the duplicate entry violation error within a second...

Edited by kongondo
  • Like 7
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Saleena Jhon
      Hello There, I have saw a post that was covering event-calendar with php, ajax and js. That was showing a monthly overview when I click on a "month" button or when I switch the month. And show the events on one particular date when I pick a day. Also, most events are kind of exhibitions and so they have a start date and an end date much later, and occur on each day in-between as well. So on the template I put two date picking fileds date_start and date_end. Is there an elegant way to select the events using the API? If yes, kindly help me out.
      Thanks in Advance
      Regards: 
       
    • By spercy16
      I was previously using individual fields to capture and output multiple cards onto my web page but after recently learning about repeaters would prefer to use this field type, as it will be a lot more user friendly for end users to create new cards. I tried to modify my code to grab the fields from the new Repeater field(s) but am getting this error message on the page:
      Here is the code I'm currently trying to use for the cards:
      <?php // https://processwire.com/api/arrays/ // check if the array of images has items foreach($page->tall_card as $card) { $count = 0; $count++; $options = array( 'quality' => 70 ); $image = $card->image; $img = $card->image->size(550, 400, $options); $cardHeading = $card->title; $cardBody = $card->plain_paragraph; $raised = $card->raised_amount; $goal = $card->goal_amount; $link = $card->link; if ($raised == 0 ) : $percent = 0; else: $percent = $raised_amount / $goal_amount * 100; endif; if ($percent <= 5) : $percent = 0; endif; ?> <span id="card<?php echo $count?>" class="card"> <img class="cardThumb" src="<?php echo $img->url; ?>" alt="<?php echo $image->description; ?> Thumbnail" /> <div class="cardBody"> <div class="cardText"> <h2><?php echo $cardHeading; ?></h2> <?php echo $cardBody; ?> </div> <div class="progressBarSection"> <progress class="progressBar" id="progressbar<?php echo $count; ?>" value="<?php echo $percent; ?>" max="100"></progress> <span class="raisedAmount"> $<?php echo $raised; ?> usd </span> <span class="goalAmount"> $<?php echo $goal; ?> usd </span> </div> <div class="primaryBtn"> <a href="https://www.paypal.com/donate?hosted_button_id= <?php echo $link; ?> &source=url"> <button> <i class="fas fa-donate"></i> Donate </button> </a> </div> </div> </span> <?php } ?> Thanks in advance for any help!
    • By opalepatrick
      I am working on my first Process Module. I am creating forms. Fairly straightforward. However, I really can't work out how to create multiple fieldsets?
      $fieldset = $this->modules->get('InputfieldFieldset'); $fieldset->label = 'Customer Source'; $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1449, include=hidden'; $field->labelFieldName = 'yff-lead'; $field->name = 'yfflead'; $field->columnWidth = 16; $fieldset->add($field); $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1452, include=hidden'; $field->labelFieldName = 'customer-type'; $field->name = 'customertype'; $field->columnWidth = 16; $fieldset->add($field); //Rinse and Repeat $fieldset->label = 'Contacts'; $field = $this->modules->get('InputfieldPage'); $field->inputfield = 'InputfieldSelect'; $field->findPagesSelector = 'parent_id=1538, include=hidden'; $field->labelFieldName = 'salutation'; $field->name = 'salutation'; $field->columnWidth = 16; $fieldset->add($field); I can create the first fieldset (Customer Source) but then get into trouble as the second fieldset overwrites the first. I understand why, but trying to use the open and close fieldset routine has flummoxed me. Any help appreciated.
    • By VeiJari
      Hello forum, we're trying to use Processwire as our REST-API. We are having problems with our API login to Processwire from frontend. It gives us 403 error.
      We have installed ProcessWire to subdirectory (/api/*) and our frontend is static JS files at root ( / ). Apache access logs gives 404 to our POST-request, but browser devtools shows 403 for our POST /api/login request. 
      Processwire backend panel works. We also have a GET endpoint for the API that returns 200 with correct payload.  So we're wondering why does our GET works but POST doesn't?
      Does this have something to do with Processwire .htaccess, or is this because of our webhost? What should we check first? Any help would be appreciated.
    • By CachePuzzles
      Hi there,
      I'm probably missing something simple, but I'm just setting up my first site so I guess that's bound to happen.
      I've installed the LoginRegistration module and at first I was thinking that the confirmation emails weren't being sent. However I now see that new user confirmation emails are taking 20+ minutes to arrive. Is there a way to speed this up?
      Also the email is coming from processwire@mydomain - I couldn't found a place to change this.
      Any advice or help would be great!
      Brian
×
×
  • Create New...